[gtk+] [broadway] Use cairo to generate png uris



commit cfd8150759828f3e1e1c3f5ebd21ae59492634c3
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Apr 18 20:23:19 2011 +0200

    [broadway] Use cairo to generate png uris

 gdk/broadway/broadway.c |  454 ++++++++++-------------------------------------
 1 files changed, 90 insertions(+), 364 deletions(-)
---
diff --git a/gdk/broadway/broadway.c b/gdk/broadway/broadway.c
index 710cb3a..9f27746 100644
--- a/gdk/broadway/broadway.c
+++ b/gdk/broadway/broadway.c
@@ -3,7 +3,7 @@
 #include <stdio.h>
 #include <assert.h>
 #include <errno.h>
-#include <zlib.h>
+#include <cairo.h>
 
 #include "broadway.h"
 
@@ -53,391 +53,117 @@ base64_uint32 (guint32 v, char *c)
   c[5] = base64_alphabet[(v >> 30) & 0x2];
 }
 
-/************************************************************************
- *  conversion of raw image data to uncompressed png data: uris         *
- ************************************************************************/
-
-/* Table of CRCs of all 8-bit messages. */
-static unsigned long crc_table[256];
+/***********************************************************
+ *  conversion of raw image data to png data: uris         *
+ ***********************************************************/
 
-/* Flag: has the table been computed? Initially false. */
-static int crc_table_computed = 0;
+struct PngTarget {
+  GString *url;
+  int state;
+  int save;
+};
 
-/* Make the table for a fast CRC. */
-static void
-make_crc_table(void)
+static cairo_status_t
+write_png_url (void		  *closure,
+	       const unsigned char *data,
+	       unsigned int	   data_len)
 {
-  unsigned long c;
-  int n, k;
-
-  for (n = 0; n < 256; n++) {
-    c = (unsigned long) n;
-    for (k = 0; k < 8; k++) {
-      if (c & 1)
-	c = 0xedb88320L ^ (c >> 1);
-      else
-	c = c >> 1;
-    }
-    crc_table[n] = c;
-  }
-  crc_table_computed = 1;
-}
+  struct PngTarget *target = closure;
+  gsize res, old_len;
 
-static unsigned long
-update_crc(unsigned long crc, unsigned char *buf, int len)
-{
-  unsigned long c = crc;
-  int n;
-
-  if (!crc_table_computed)
-    make_crc_table();
-  for (n = 0; n < len; n++) {
-    c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
-  }
-  return c;
-}
+  old_len = target->url->len;
+  g_string_set_size (target->url,
+		     old_len + (data_len / 3 + 1) * 4 + 4);
 
-static unsigned long
-crc(unsigned char *buf, int len)
-{
-  return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
-}
+  res = g_base64_encode_step (data, data_len, FALSE,
+			      target->url->str + old_len,
+			      &target->state, &target->save);
 
-#define BASE 65521 /* largest prime smaller than 65536 */
-static unsigned long
-update_adler32(unsigned long adler, unsigned char *buf, int len)
-{
-  unsigned long s1 = adler & 0xffff;
-  unsigned long s2 = (adler >> 16) & 0xffff;
-  int n;
-
-  for (n = 0; n < len; n++) {
-    s1 = (s1 + buf[n]) % BASE;
-    s2 = (s2 + s1)     % BASE;
-  }
-  return (s2 << 16) + s1;
+  g_string_set_size (target->url,  old_len + res);
+
+  return CAIRO_STATUS_SUCCESS;
 }
 
 static char *
 to_png_rgb (int w, int h, int byte_stride, guint32 *data)
 {
-  guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10};
-  guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R',
-			/* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0,
-			/* bpp: */ 8, /* color type: */ 2,
-			0, 0, 0};
-  guchar idat_start[8] = { /* len: */0, 0, 0, 0,   'I', 'D', 'A', 'T' };
-  guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82};
-  gsize data_size, row_size;
-  char row_header[6];
-  guint8 *png, *p, *p_row, *p_idat;
-  guint32 *row;
-  unsigned long adler;
-  guint32 pixel;
-  gsize png_size;
-  int x, y;
-  char *url, *url_base64;
-  int state = 0, outlen;
-  int save = 0;
-
-  *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w);
-  *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h);
-  *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4));
-
-  row_size = 1 + w * 3;
-  row_header[0] = 0;
-  row_header[1] = row_size & 0xff;
-  row_header[2] = (row_size >> 8) & 0xff;
-  row_header[3] = ~row_header[1];
-  row_header[4] = ~row_header[2];
-  row_header[5] = 0;
-
-  data_size = 2 + (6 + w * 3) * h + 4;
-
-  *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size);
-
-  png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend);
-  png = g_malloc (png_size);
-
-  p = png;
-  memcpy (p, header, sizeof(header));
-  p += sizeof(header);
-  memcpy (p, ihdr, sizeof(ihdr));
-  p += sizeof(ihdr);
-  memcpy (p, idat_start, sizeof(idat_start));
-  p += sizeof(idat_start);
-
-  /* IDAT data:
-
-     zlib header:  0x78, 0x01 ,
-     h * scanline: row_header[] + width * r,g,b
-     checksum: adler32
-  */
-
-  p_idat = p - 4;
-
-  /* zlib header */
-  *p++ = 0x78;
-  *p++ = 0x01;
-
-  adler = 1;
-
-  /* scanline data */
-  for (y = 0; y < h; y++) {
-    if (y == h - 1)
-      row_header[0] = 1; /* final block */
-    memcpy (p, row_header, sizeof(row_header));
-    p += sizeof(row_header);
-    p_row = p - 1;
-    row = data;
-    data += byte_stride / 4;
-    for (x = 0; x < w; x++) {
-      pixel = *row++;
-      *p++ = (pixel >> 16) & 0xff; /* red */
-      *p++ = (pixel >> 8) & 0xff; /* green */
-      *p++ = (pixel >> 0) & 0xff; /* blue */
-    }
-    adler = update_adler32(adler, p_row, p - p_row);
-  }
-
-  /* adler32 */
-  *(guint32 *)p = GUINT32_TO_BE(adler);
-  p += 4;
-  *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat));
-  p += 4;
+  cairo_surface_t *surface;
+  struct PngTarget target;
+  gsize res, old_len;
 
-  memcpy (p, iend, sizeof(iend));
-  p += sizeof(iend);
+  target.url = g_string_new ("data:image/png;base64,");
+  target.state = 0;
+  target.save = 0;
 
-  assert(p - png == png_size);
+  surface = cairo_image_surface_create_for_data ((guchar *)data,
+						 CAIRO_FORMAT_RGB24, w, h, byte_stride);
 
-  url = g_malloc (strlen("data:image/png;base64,") +
-		   ((png_size / 3 + 1) * 4 + 4) + 1);
-  strcpy (url, "data:image/png;base64,");
+  cairo_surface_write_to_png_stream (surface, write_png_url, &target);
 
-  url_base64 = url + strlen("data:image/png;base64,");
-  outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save);
-  outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save);
-  url_base64[outlen] = 0;
+  old_len = target.url->len;
 
-  free (png);
+  g_string_set_size (target.url, old_len + 4);
+  res = g_base64_encode_close (FALSE,
+			       target.url->str + old_len,
+			       &target.state, &target.save);
+  g_string_set_size (target.url, old_len + res);
 
-  return url;
+  return g_string_free (target.url, FALSE);
 }
 
 static char *
 to_png_rgba (int w, int h, int byte_stride, guint32 *data)
 {
-  guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10};
-  guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R',
-			/* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0,
-			/* bpp: */ 8, /* color type: */ 6,
-			0, 0, 0};
-  guchar idat_start[8] = { /* len: */0, 0, 0, 0,   'I', 'D', 'A', 'T' };
-  guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82};
-  gsize data_size, row_size;
-  char row_header[6];
-  guint8 *png, *p, *p_row, *p_idat;
-  guint32 *row;
-  unsigned long adler;
-  guint32 pixel;
-  gsize png_size;
-  int x, y;
-  char *url, *url_base64;
-  int state = 0, outlen;
-  int save = 0;
-
-  *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w);
-  *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h);
-  *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4));
-
-  row_size = 1 + w * 4;
-  row_header[0] = 0;
-  row_header[1] = row_size & 0xff;
-  row_header[2] = (row_size >> 8) & 0xff;
-  row_header[3] = ~row_header[1];
-  row_header[4] = ~row_header[2];
-  row_header[5] = 0;
-
-  data_size = 2 + (6 + w * 4) * h + 4;
-
-  *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size);
-
-  png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend);
-  png = g_malloc (png_size);
-
-  p = png;
-  memcpy (p, header, sizeof(header));
-  p += sizeof(header);
-  memcpy (p, ihdr, sizeof(ihdr));
-  p += sizeof(ihdr);
-  memcpy (p, idat_start, sizeof(idat_start));
-  p += sizeof(idat_start);
-
-  /* IDAT data:
-
-     zlib header:  0x78, 0x01 ,
-     h * scanline: row_header[] + width * r,g,b,a
-     checksum: adler32
-  */
-
-  p_idat = p - 4;
-
-  /* zlib header */
-  *p++ = 0x78;
-  *p++ = 0x01;
-
-  adler = 1;
-
-  /* scanline data */
-  for (y = 0; y < h; y++) {
-    if (y == h - 1)
-      row_header[0] = 1; /* final block */
-    memcpy (p, row_header, sizeof(row_header));
-    p += sizeof(row_header);
-    p_row = p - 1;
-    row = data;
-    data += byte_stride / 4;
-    for (x = 0; x < w; x++) {
-      pixel = *row++;
-      *p++ = (pixel >> 16) & 0xff; /* red */
-      *p++ = (pixel >> 8) & 0xff; /* green */
-      *p++ = (pixel >> 0) & 0xff; /* blue */
-      *p++ = (pixel >> 24) & 0xff; /* alpha */
-    }
-    adler = update_adler32(adler, p_row, p - p_row);
-  }
-
-  /* adler32 */
-  *(guint32 *)p = GUINT32_TO_BE(adler);
-  p += 4;
-  *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat));
-  p += 4;
+  cairo_surface_t *surface;
+  struct PngTarget target;
+  gsize res, old_len;
 
-  memcpy (p, iend, sizeof(iend));
-  p += sizeof(iend);
+  target.url = g_string_new ("data:image/png;base64,");
+  target.state = 0;
+  target.save = 0;
 
-  assert(p - png == png_size);
+  surface = cairo_image_surface_create_for_data ((guchar *)data,
+						 CAIRO_FORMAT_ARGB32, w, h, byte_stride);
 
-  url = g_malloc (strlen("data:image/png;base64,") +
-		   ((png_size / 3 + 1) * 4 + 4) + 1);
-  strcpy (url, "data:image/png;base64,");
+  cairo_surface_write_to_png_stream (surface, write_png_url, &target);
 
-  url_base64 = url + strlen("data:image/png;base64,");
-  outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save);
-  outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save);
-  url_base64[outlen] = 0;
+  old_len = target.url->len;
 
-  free (png);
+  g_string_set_size (target.url, old_len + 4);
+  res = g_base64_encode_close (FALSE,
+			       target.url->str + old_len,
+			       &target.state, &target.save);
+  g_string_set_size (target.url, old_len + res);
 
-  return url;
+  return g_string_free (target.url, FALSE);
 }
 
 #if 0
 static char *
 to_png_a (int w, int h, int byte_stride, guint8 *data)
 {
-  guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10};
-  guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R',
-			/* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0,
-			/* bpp: */ 8, /* color type: */ 4,
-			0, 0, 0};
-  guchar idat_start[8] = { /* len: */0, 0, 0, 0,   'I', 'D', 'A', 'T' };
-  guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82};
-  gsize data_size, row_size;
-  char row_header[6];
-  guint8 *png, *p, *p_row, *p_idat;
-  guint8 *row;
-  unsigned long adler;
-  guint32 pixel;
-  gsize png_size;
-  int x, y;
-  char *url, *url_base64;
-  int state = 0, outlen;
-  int save = 0;
-
-  *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w);
-  *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h);
-  *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4));
-
-  row_size = 1 + w * 2;
-  row_header[0] = 0;
-  row_header[1] = row_size & 0xff;
-  row_header[2] = (row_size >> 8) & 0xff;
-  row_header[3] = ~row_header[1];
-  row_header[4] = ~row_header[2];
-  row_header[5] = 0;
-
-  data_size = 2 + (6 + w * 2) * h + 4;
-
-  *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size);
-
-  png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend);
-  png = g_malloc (png_size);
-
-  p = png;
-  memcpy (p, header, sizeof(header));
-  p += sizeof(header);
-  memcpy (p, ihdr, sizeof(ihdr));
-  p += sizeof(ihdr);
-  memcpy (p, idat_start, sizeof(idat_start));
-  p += sizeof(idat_start);
-
-  /* IDAT data:
-
-     zlib header:  0x78, 0x01 ,
-     h * scanline: row_header[] + width * r,g,b,a
-     checksum: adler32
-  */
-
-  p_idat = p - 4;
-
-  /* zlib header */
-  *p++ = 0x78;
-  *p++ = 0x01;
-
-  adler = 1;
-
-  /* scanline data */
-  for (y = 0; y < h; y++) {
-    if (y == h - 1)
-      row_header[0] = 1; /* final block */
-    memcpy (p, row_header, sizeof(row_header));
-    p += sizeof(row_header);
-    p_row = p - 1;
-    row = data;
-    data += byte_stride / 4;
-    for (x = 0; x < w; x++) {
-      pixel = *row++;
-      *p++ = 0x00; /* gray */
-      *p++ = pixel; /* alpha */
-    }
-    adler = update_adler32(adler, p_row, p - p_row);
-  }
-
-  /* adler32 */
-  *(guint32 *)p = GUINT32_TO_BE(adler);
-  p += 4;
-  *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat));
-  p += 4;
+  cairo_surface_t *surface;
+  struct PngTarget target;
+  gsize res, old_len;
 
-  memcpy (p, iend, sizeof(iend));
-  p += sizeof(iend);
+  target.url = g_string_new ("data:image/png;base64,");
+  target.state = 0;
+  target.save = 0;
 
-  assert(p - png == png_size);
+  surface = cairo_image_surface_create_for_data (data,
+						 CAIRO_FORMAT_A8, w, h, byte_stride);
 
-  url = g_malloc (strlen("data:image/png;base64,") +
-		  ((png_size / 3 + 1) * 4 + 4) + 1);
-  strcpy (url, "data:image/png;base64,");
+  cairo_surface_write_to_png_stream (surface, write_png_url, &target);
 
-  url_base64 = url + strlen("data:image/png;base64,");
-  outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save);
-  outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save);
-  url_base64[outlen] = 0;
+  old_len = target.url->len;
 
-  free (png);
+  g_string_set_size (target.url, old_len + 4);
+  res = g_base64_encode_close (FALSE,
+			       target.url->str + old_len,
+			       &target.state, &target.save);
+  g_string_set_size (target.url, old_len + res);
 
-  return url;
+  return g_string_free (target.url, FALSE);
 }
 #endif
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]