[cairo-commit] cairo/src cairo_png_surface.c,1.4,1.5

Carl Worth commit at pdx.freedesktop.org
Tue May 4 09:25:56 PDT 2004


Committed by: cworth

Update of /cvs/cairo/cairo/src
In directory pdx:/tmp/cvs-serv7705/src

Modified Files:
	cairo_png_surface.c 
Log Message:

        * src/cairo_png_surface.c (cairo_png_surface_create): Move all
        libpng-related code into copy_page.
        (unpremultiply_data): Add missing unpremultiply step.
        (_cairo_png_surface_copy_page): Move PNG output to copy_page. Add
        support for A8 and A1 images. Remove time from header (we may want
        to add it again later, but for now it messes up my test suite).
        (_cairo_png_surface_destroy): Call copy_page if it hasn't been
        called already.
        (_cairo_png_surface_show_page): Add implementation.


Index: cairo_png_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_png_surface.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** a/cairo_png_surface.c	16 Apr 2004 15:33:20 -0000	1.4
--- b/cairo_png_surface.c	4 May 2004 16:25:54 -0000	1.5
***************
*** 5,8 ****
--- 5,11 ----
  static const cairo_surface_backend_t cairo_png_surface_backend;
  
+ static cairo_int_status_t
+ _cairo_png_surface_copy_page (void *abstract_surface);
+ 
  void
  cairo_set_target_png (cairo_t	*cr,
***************
*** 32,41 ****
  
      /* PNG-specific fields */
      FILE *file;
  
!     png_structp png_w;
!     png_infop png_i;
  
-     cairo_image_surface_t *image;
  } cairo_png_surface_t;
  
--- 35,44 ----
  
      /* PNG-specific fields */
+     cairo_image_surface_t *image;
      FILE *file;
+     int copied;
  
!     cairo_format_t format;
  
  } cairo_png_surface_t;
  
***************
*** 51,146 ****
  {
      cairo_png_surface_t *surface;
-     time_t now = time (NULL);
-     png_time png_time;
- 
-     if (format == CAIRO_FORMAT_A8 ||
- 	format == CAIRO_FORMAT_A1 ||
- 	file == NULL)
- 	return NULL;
  
      surface = malloc (sizeof (cairo_png_surface_t));
      if (surface == NULL)
! 	goto failure;
  
      _cairo_surface_init (&surface->base, &cairo_png_surface_backend);
-     surface->png_w = NULL;
-     surface->png_i = NULL;
  
      surface->image = (cairo_image_surface_t *)
  	cairo_image_surface_create (format, width, height);
-     if (surface->image == NULL)
- 	goto failure;
- 
-     _cairo_png_surface_erase (surface);
- 
-     surface->file = file;
- 
-     surface->png_w = png_create_write_struct (PNG_LIBPNG_VER_STRING,
- 					      NULL, NULL, NULL);
-     if (surface->png_w == NULL)
- 	goto failure;
-     surface->png_i = png_create_info_struct (surface->png_w);
-     if (surface->png_i == NULL)
- 	goto failure;
  
!     if (setjmp (png_jmpbuf (surface->png_w)))
! 	goto failure;
!     
!     png_init_io (surface->png_w, surface->file);
! 
!     switch (format) {
!     case CAIRO_FORMAT_ARGB32:
!     png_set_IHDR (surface->png_w, surface->png_i,
! 		  width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
! 		  PNG_INTERLACE_NONE,
! 		  PNG_COMPRESSION_TYPE_DEFAULT,
! 		  PNG_FILTER_TYPE_DEFAULT);
!     break;
!     case CAIRO_FORMAT_RGB24:
!     png_set_IHDR (surface->png_w, surface->png_i,
! 		  width, height, 8, PNG_COLOR_TYPE_RGB,
! 		  PNG_INTERLACE_NONE,
! 		  PNG_COMPRESSION_TYPE_DEFAULT,
! 		  PNG_FILTER_TYPE_DEFAULT);
!     break;
!     case CAIRO_FORMAT_A8:
!     case CAIRO_FORMAT_A1:
! 	/* These are not currently supported. */
! 	break;
      }
  
!     png_convert_from_time_t (&png_time, now);
!     png_set_tIME (surface->png_w, surface->png_i, &png_time);
  
!     png_write_info (surface->png_w, surface->png_i);
  
!     switch (format) {
!     case CAIRO_FORMAT_ARGB32:
! 	png_set_bgr (surface->png_w);
! 	break;
!     case CAIRO_FORMAT_RGB24:
! 	png_set_filler (surface->png_w, 0, PNG_FILLER_AFTER);
! 	png_set_bgr (surface->png_w);
! 	break;
!     case CAIRO_FORMAT_A8:
!     case CAIRO_FORMAT_A1:
! 	/* These are not currently supported. */
! 	break;
!     }
  
      return &surface->base;
- 
- 
-   failure:
-     if (surface) {
- 	if (surface->image)
- 	    cairo_surface_destroy (&surface->image->base);
- 	if (surface->png_i)
- 	    png_destroy_write_struct (&surface->png_w, &surface->png_i);
- 	else if (surface->png_w)
- 	    png_destroy_write_struct (&surface->png_w, NULL);
- 	free (surface);
-     }
-     return NULL;
  }
  
--- 54,80 ----
  {
      cairo_png_surface_t *surface;
  
      surface = malloc (sizeof (cairo_png_surface_t));
      if (surface == NULL)
! 	return NULL;
  
      _cairo_surface_init (&surface->base, &cairo_png_surface_backend);
  
      surface->image = (cairo_image_surface_t *)
  	cairo_image_surface_create (format, width, height);
  
!     if (surface->image == NULL) {
! 	free (surface);
! 	return NULL;
      }
  
!     _cairo_png_surface_erase (surface);
  
!     surface->file = file;
!     surface->copied = 0;
  
!     surface->format = format;
  
      return &surface->base;
  }
  
***************
*** 156,178 ****
  
  static void
! _cairo_png_surface_destroy (void *abstract_surface)
  {
-     cairo_png_surface_t *surface = abstract_surface;
      int i;
-     png_byte *row;
  
!     if (setjmp (png_jmpbuf (surface->png_w)))
! 	goto failure;
  
!     row = surface->image->data;
!     for (i=0; i < surface->image->height; i++) {
! 	png_write_row (surface->png_w, row);
! 	row += surface->image->stride;
      }
  
!     png_write_end (surface->png_w, surface->png_i);
  
!   failure:
!     png_destroy_write_struct (&surface->png_w, &surface->png_i);
  
      cairo_surface_destroy (&surface->image->base);
--- 90,122 ----
  
  static void
! unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
  {
      int i;
  
!     for (i = 0; i < row_info->rowbytes; i += 4) {
!         unsigned char *b = &data[i];
!         unsigned int pixel;
!         unsigned char alpha;
  
! 	memcpy (&pixel, b, sizeof (unsigned int));
! 	alpha = (pixel & 0xff000000) >> 24;
!         if (alpha == 0) {
! 	    b[0] = b[1] = b[2] = b[3] = 0;
! 	} else {
!             b[0] = (((pixel & 0x0000ff) >>  0) * 255) / alpha;
!             b[1] = (((pixel & 0x00ff00) >>  8) * 255) / alpha;
!             b[2] = (((pixel & 0xff0000) >> 16) * 255) / alpha;
! 	    b[3] = alpha;
! 	}
      }
+ }
  
! static void
! _cairo_png_surface_destroy (void *abstract_surface)
! {
!     cairo_png_surface_t *surface = abstract_surface;
  
!     if (! surface->copied)
! 	_cairo_png_surface_copy_page (surface);
  
      cairo_surface_destroy (&surface->image->base);
***************
*** 297,301 ****
  _cairo_png_surface_copy_page (void *abstract_surface)
  {
!     return CAIRO_INT_STATUS_UNSUPPORTED;
  }
  
--- 241,334 ----
  _cairo_png_surface_copy_page (void *abstract_surface)
  {
!     int i;
!     cairo_status_t status = CAIRO_STATUS_SUCCESS;
!     cairo_png_surface_t *surface = abstract_surface;
!     png_struct *png;
!     png_info *info;
!     png_byte **rows;
!     png_color_16 white;
!     int png_color_type;
!     int depth;
! 
!     rows = malloc (surface->image->height * sizeof(png_byte*));
!     if (rows == NULL)
! 	return CAIRO_STATUS_NO_MEMORY;
! 
!     for (i = 0; i < surface->image->height; i++)
! 	rows[i] = surface->image->data + i * surface->image->stride;
! 
!     png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
!     if (png == NULL)
! 	return CAIRO_STATUS_NO_MEMORY;
! 
!     info = png_create_info_struct (png);
!     if (info == NULL) {
! 	png_destroy_write_struct (&png, NULL);
! 	return CAIRO_STATUS_NO_MEMORY;
!     }
! 
!     if (setjmp (png_jmpbuf (png))) {
! 	status = CAIRO_STATUS_NO_MEMORY;
! 	goto BAIL;
!     }
!     
!     png_init_io (png, surface->file);
! 
!     switch (surface->format) {
!     case CAIRO_FORMAT_ARGB32:
! 	depth = 8;
! 	png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
! 	break;
!     case CAIRO_FORMAT_RGB24:
! 	depth = 8;
! 	png_color_type = PNG_COLOR_TYPE_RGB;
! 	break;
!     case CAIRO_FORMAT_A8:
! 	depth = 8;
! 	png_color_type = PNG_COLOR_TYPE_GRAY;
! 	break;
!     case CAIRO_FORMAT_A1:
! 	depth = 1;
! 	png_color_type = PNG_COLOR_TYPE_GRAY;
! 	break;
!     }
! 
!     png_set_IHDR (png, info,
! 		  surface->image->width,
! 		  surface->image->height, depth,
! 		  png_color_type,
! 		  PNG_INTERLACE_NONE,
! 		  PNG_COMPRESSION_TYPE_DEFAULT,
! 		  PNG_FILTER_TYPE_DEFAULT);
! 
!     white.red = 0xff;
!     white.blue = 0xff;
!     white.green = 0xff;
!     png_set_bKGD (png, info, &white);
! 
! /* XXX: Setting the time is interfereing with the image comparison
!     png_convert_from_time_t (&png_time, time (NULL));
!     png_set_tIME (png, info, &png_time);
! */
! 
!     png_set_write_user_transform_fn (png, unpremultiply_data);
!     if (surface->format == CAIRO_FORMAT_ARGB32 || surface->format == CAIRO_FORMAT_RGB24)
! 	png_set_bgr (png);
!     if (surface->format == CAIRO_FORMAT_RGB24)
! 	png_set_filler (png, 0, PNG_FILLER_AFTER);
! 
!     png_write_info (png, info);
!     png_write_image (png, rows);
!     png_write_end (png, info);
! 
!     surface->copied = 1;
! 
! BAIL:
!     png_destroy_write_struct (&png, &info);
! 
!     free (rows);
!     fclose (surface->file);
! 
!     return status;
  }
  
***************
*** 303,307 ****
  _cairo_png_surface_show_page (void *abstract_surface)
  {
!     return CAIRO_INT_STATUS_UNSUPPORTED;
  }
  
--- 336,349 ----
  _cairo_png_surface_show_page (void *abstract_surface)
  {
!     cairo_int_status_t status;
!     cairo_png_surface_t *surface = abstract_surface;
! 
!     status = _cairo_png_surface_copy_page (surface);
!     if (status)
! 	return status;
! 
!     _cairo_png_surface_erase (surface);
! 
!     return CAIRO_STATUS_SUCCESS;
  }
  





More information about the cairo-commit mailing list