[cairo-commit] cairo/src cairo_png_surface.c,NONE,1.1 cairo.h,1.46,1.47 cairo-features.h.in,1.3,1.4

Olivier Andrieu commit at pdx.freedesktop.org
Mon Aug 15 11:12:59 PDT 2005


Committed by: oandrieu

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

Modified Files:
	cairo.h cairo-features.h.in 
Added Files:
	cairo_png_surface.c 
Log Message:
Add PNG backend (cairo_set_target_png and cairo_png_surface_create).

--- NEW FILE: cairo_png_surface.c ---
#include <png.h>

#include "cairoint.h"

static const cairo_surface_backend_t cairo_png_surface_backend;

void
cairo_set_target_png (cairo_t	*cr,
		      FILE	*file,
		      cairo_format_t	format,
		      int	       	width,
		      int		height)
{
    cairo_surface_t *surface;

    surface = cairo_png_surface_create (file, format, 
					width, height);

    if (surface == NULL) {
	cr->status = CAIRO_STATUS_NO_MEMORY;
	return;
    }

    cairo_set_target_surface (cr, surface);

    /* cairo_set_target_surface takes a reference, so we must destroy ours */
    cairo_surface_destroy (surface);
}

typedef struct cairo_png_surface {
    cairo_surface_t base;

    /* PNG-specific fields */
    FILE *file;

    png_structp png_w;
    png_infop png_i;

    cairo_image_surface_t *image;
} cairo_png_surface_t;


static void
_cairo_png_surface_erase (cairo_png_surface_t *surface);

cairo_surface_t *
cairo_png_surface_create (FILE			*file,
			  cairo_format_t	format,
			  int			width,
			  int			height)
{
    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;
    }

    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;
    }

    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;
}


static cairo_surface_t *
_cairo_png_surface_create_similar (void		*abstract_src,
				   cairo_format_t	format,
				   int		width,
				   int		height)
{
    return NULL;
}

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);

    free (surface);
}

static void
_cairo_png_surface_erase (cairo_png_surface_t *surface)
{
    cairo_color_t transparent;

    _cairo_color_init (&transparent);
    _cairo_color_set_rgb (&transparent, 0., 0., 0.);
    _cairo_color_set_alpha (&transparent, 0.);
    _cairo_surface_fill_rectangle (&surface->image->base,
				   CAIRO_OPERATOR_SRC,
				   &transparent,
				   0, 0,
				   surface->image->width,
				   surface->image->height);
}

static double
_cairo_png_surface_pixels_per_inch (void *abstract_surface)
{
    return 96.0;
}

static cairo_image_surface_t *
_cairo_png_surface_get_image (void *abstract_surface)
{
    cairo_png_surface_t *surface = abstract_surface;

    cairo_surface_reference (&surface->image->base);

    return surface->image;
}

static cairo_status_t
_cairo_png_surface_set_image (void			*abstract_surface,
			      cairo_image_surface_t	*image)
{
    cairo_png_surface_t *surface = abstract_surface;

    if (image == surface->image)
	return CAIRO_STATUS_SUCCESS;

    /* XXX: Need to call _cairo_image_surface_set_image here, but it's
       not implemented yet. */

    return CAIRO_INT_STATUS_UNSUPPORTED;
}

static cairo_status_t
_cairo_png_surface_set_matrix (void		*abstract_surface,
			       cairo_matrix_t	*matrix)
{
    cairo_png_surface_t *surface = abstract_surface;

    return _cairo_image_surface_set_matrix (surface->image, matrix);
}

static cairo_status_t
_cairo_png_surface_set_filter (void		*abstract_surface,
			       cairo_filter_t	filter)
{
    cairo_png_surface_t *surface = abstract_surface;

    return _cairo_image_surface_set_filter (surface->image, filter);
}

static cairo_status_t
_cairo_png_surface_set_repeat (void		*abstract_surface,
			       int		repeat)
{
    cairo_png_surface_t *surface = abstract_surface;

    return _cairo_image_surface_set_repeat (surface->image, repeat);
}

static cairo_int_status_t
_cairo_png_surface_composite (cairo_operator_t	operator,
			      cairo_surface_t	*generic_src,
			      cairo_surface_t	*generic_mask,
			      void		*abstract_dst,
			      int		src_x,
			      int		src_y,
			      int		mask_x,
			      int		mask_y,
			      int		dst_x,
			      int		dst_y,
			      unsigned int	width,
			      unsigned int	height)
{
    return CAIRO_INT_STATUS_UNSUPPORTED;
}

static cairo_int_status_t
_cairo_png_surface_fill_rectangles (void			*abstract_surface,
				    cairo_operator_t	operator,
				    const cairo_color_t	*color,
				    cairo_rectangle_t	*rects,
				    int			num_rects)
{
    return CAIRO_INT_STATUS_UNSUPPORTED;
}

static cairo_int_status_t
_cairo_png_surface_composite_trapezoids (cairo_operator_t	operator,
					 cairo_surface_t		*generic_src,
					 void			*abstract_dst,
					 int			x_src,
					 int			y_src,
					 cairo_trapezoid_t	*traps,
					 int			num_traps)
{
    return CAIRO_INT_STATUS_UNSUPPORTED;
}

static cairo_int_status_t
_cairo_png_surface_copy_page (void *abstract_surface)
{
    return CAIRO_INT_STATUS_UNSUPPORTED;
}

static cairo_int_status_t
_cairo_png_surface_show_page (void *abstract_surface)
{
    return CAIRO_INT_STATUS_UNSUPPORTED;
}

static const cairo_surface_backend_t cairo_png_surface_backend = {
    _cairo_png_surface_create_similar,
    _cairo_png_surface_destroy,
    _cairo_png_surface_pixels_per_inch,
    _cairo_png_surface_get_image,
    _cairo_png_surface_set_image,
    _cairo_png_surface_set_matrix,
    _cairo_png_surface_set_filter,
    _cairo_png_surface_set_repeat,
    _cairo_png_surface_composite,
    _cairo_png_surface_fill_rectangles,
    _cairo_png_surface_composite_trapezoids,
    _cairo_png_surface_copy_page,
    _cairo_png_surface_show_page
};

Index: cairo.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -C2 -d -r1.46 -r1.47
*** a/cairo.h	18 Feb 2004 02:47:34 -0000	1.46
--- b/cairo.h	24 Feb 2004 20:28:49 -0000	1.47
***************
*** 103,106 ****
--- 103,119 ----
  #endif /* CAIRO_HAS_PS_SURFACE */
  
+ #ifdef CAIRO_HAS_PNG_SURFACE
+ 
+ #include <stdio.h>
+ 
+ void
+ cairo_set_target_png (cairo_t	*cr,
+ 		      FILE	*file,
+ 		      cairo_format_t	format,
+ 		      int	       	width,
+ 		      int		height);
+ 
+ #endif /* CAIRO_HAS_PNG_SURFACE */
+ 
  #ifdef CAIRO_HAS_XLIB_SURFACE
  
***************
*** 668,671 ****
--- 681,696 ----
  #endif /* CAIRO_HAS_PS_SURFACE */
  
+ #ifdef CAIRO_HAS_PNG_SURFACE
+ 
+ /* PNG-surface functions */
+ 
+ cairo_surface_t *
+ cairo_png_surface_create (FILE			*file,
+ 			  cairo_format_t	format,
+ 			  int			width,
+ 			  int			height);
+ 
+ #endif /* CAIRO_HAS_PNG_SURFACE */
+ 
  #ifdef CAIRO_HAS_XLIB_SURFACE
  

Index: cairo-features.h.in
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-features.h.in,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** a/cairo-features.h.in	3 Feb 2004 07:24:14 -0000	1.3
--- b/cairo-features.h.in	24 Feb 2004 20:28:49 -0000	1.4
***************
*** 31,34 ****
--- 31,36 ----
  #define @PS_SURFACE_FEATURE@
  
+ #define @PNG_SURFACE_FEATURE@
+ 
  #define @XLIB_SURFACE_FEATURE@
  





More information about the cairo-commit mailing list