[cairo-commit] cairo/src cairo-image-surface.c, 1.37, 1.38 cairo-png.c, 1.7, 1.8 cairo.c, 1.79, 1.80 cairo.h, 1.101, 1.102

Kristian Hogsberg commit at pdx.freedesktop.org
Mon Apr 25 20:42:56 PDT 2005


Committed by: krh

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv14976/src

Modified Files:
	cairo-image-surface.c cairo-png.c cairo.c cairo.h 
Log Message:
2005-04-25  Kristian Høgsberg  <krh at redhat.com>

        * src/cairo-png.c (cairo_surface_write_png): Factor out bulk of
        the code into a new callback based function, write_png().  Call it
        with a stdio write callback.
        (cairo_surface_write_png_to_stream): New function to write a
        surface to a PNG stream.
        (cairo_image_surface_create_from_png): Likewise, move most of the
        code to read_png(), clean up error handling and reduce this
        function to calling read_png() with a stdio based read function.
        (cairo_image_surface_create_from_png_stream): New function to
        create an image surface from a PNG stream.

        * src/cairo-image-surface.c (cairo_image_surface_get_width)
        (cairo_image_surface_get_height): New functions to get widht and
        height of an image surface.

        * src/cairo.h: Add new prototype and error codes.

        * test/create-for-png.c (draw): Adjust to new PNG API.



Index: cairo-image-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-image-surface.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- cairo-image-surface.c	19 Apr 2005 23:29:05 -0000	1.37
+++ cairo-image-surface.c	26 Apr 2005 03:42:54 -0000	1.38
@@ -225,6 +225,38 @@
 }
 DEPRECATE(cairo_surface_create_for_image, cairo_image_surface_create_for_data);
 
+/**
+ * cairo_image_surface_get_width:
+ * @surface: a #cairo_image_surface_t
+ * 
+ * Get the width of the image surface in pixels.
+ * 
+ * Return value: the width of the surface in pixels.
+ **/
+int
+cairo_image_surface_get_width (cairo_surface_t *surface)
+{
+    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
+
+    return image_surface->width;
+}
+
+/**
+ * cairo_image_surface_get_height:
+ * @surface: a #cairo_image_surface_t
+ * 
+ * Get the height of the image surface in pixels.
+ * 
+ * Return value: the height of the surface in pixels.
+ **/
+int
+cairo_image_surface_get_height (cairo_surface_t *surface)
+{
+    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
+
+    return image_surface->height;
+}
+
 static cairo_surface_t *
 _cairo_image_surface_create_similar (void		*abstract_src,
 				     cairo_format_t	format,

Index: cairo-png.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-png.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cairo-png.c	23 Apr 2005 00:32:12 -0000	1.7
+++ cairo-png.c	26 Apr 2005 03:42:54 -0000	1.8
@@ -61,24 +61,11 @@
     }
 }
 
-/**
- * cairo_image_surface_write_png:
- * @surface: a #cairo_surface_t, this must be an image surface
- * @file: a #FILE opened in write mode
- * 
- * Writes the image surface to the given #FILE pointer.  The file
- * should be opened in write mode and binary mode if applicable.
- * 
- * Return value: CAIRO_STATUS_SUCCESS if the PNG file was written
- * successfully.  Otherwise, CAIRO_STATUS_NO_MEMORY is returned if
- * memory could not be allocated for the operation,
- * CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface is not an image
- * surface.
- **/
-cairo_status_t
-cairo_surface_write_png (cairo_surface_t *surface, const char *filename)
+static cairo_status_t
+write_png (cairo_surface_t	*surface,
+	   png_rw_ptr		write_func,
+	   void			*closure)
 {
-    FILE *file;
     int i;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_image_surface_t *image;
@@ -91,16 +78,14 @@
     int png_color_type;
     int depth;
 
-    file = fopen (filename, "wb");
-    if (file == NULL)
-        return CAIRO_STATUS_WRITE_ERROR;
-
     status = _cairo_surface_acquire_source_image (surface,
 						  &image,
 						  &image_extra);
 
-    if (status != CAIRO_STATUS_SUCCESS)
-        goto BAIL0;
+    if (status == CAIRO_STATUS_NO_MEMORY)
+        return CAIRO_STATUS_NO_MEMORY;
+    else if (status != CAIRO_STATUS_SUCCESS)
+	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
 
     rows = malloc (image->height * sizeof(png_byte*));
     if (rows == NULL) {
@@ -128,7 +113,7 @@
 	goto BAIL3;
     }
     
-    png_init_io (png, file);
+    png_set_write_fn (png, closure, write_func, NULL);
 
     switch (image->format) {
     case CAIRO_FORMAT_ARGB32:
@@ -185,13 +170,95 @@
     free (rows);
 BAIL1:
     _cairo_surface_release_source_image (surface, image, image_extra);
-BAIL0:
-    fclose (file);
 
     return status;
 }
 
 static void
+stdio_write_func (png_structp png, png_bytep data, png_size_t size)
+{
+    FILE *fp;
+
+    fp = png_get_io_ptr (png);
+    if (fwrite (data, 1, size, fp) != size)
+	png_error(png, "Write Error");
+}
+
+/**
+ * cairo_surface_write_png:
+ * @surface: a #cairo_surface_t with pixel contents
+ * @file: a #FILE opened in write mode
+ * 
+ * Writes the image surface to the given #FILE pointer.  The file
+ * should be opened in write mode and binary mode if applicable.
+ * 
+ * Return value: CAIRO_STATUS_SUCCESS if the PNG file was written
+ * successfully.  Otherwise, CAIRO_STATUS_NO_MEMORY is returned if
+ * memory could not be allocated for the operation,
+ * CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
+ * pixel contents.
+ **/
+cairo_status_t
+cairo_surface_write_png (cairo_surface_t *surface, const char *filename)
+{
+    FILE *fp;
+    cairo_status_t status;
+
+    fp = fopen (filename, "wb");
+    if (fp == NULL)
+	return CAIRO_STATUS_WRITE_ERROR;
+  
+    status = write_png (surface, stdio_write_func, fp);
+
+    if (fclose (fp) && CAIRO_OK (status))
+	status = CAIRO_STATUS_WRITE_ERROR;
+
+    return status;
+}
+
+struct png_write_closure_t {
+    cairo_write_func_t	write_func;
+    void			*closure;
+};
+
+static void
+stream_write_func (png_structp png, png_bytep data, png_size_t size)
+{
+    struct png_write_closure_t *png_closure;
+
+    png_closure = png_get_io_ptr (png);
+    if (!CAIRO_OK (png_closure->write_func (png_closure->closure, data, size)))
+	png_error(png, "Write Error");
+}
+
+/**
+ * cairo_surface_write_png_to_stream:
+ * @surface: a #cairo_surface_t with pixel contents
+ * @write_func: a #cairo_write_func_t
+ * @closure: closure data for the write function
+ * 
+ * Writes the image surface to the write function.
+ * 
+ * Return value: CAIRO_STATUS_SUCCESS if the PNG file was written
+ * successfully.  Otherwise, CAIRO_STATUS_NO_MEMORY is returned if
+ * memory could not be allocated for the operation,
+ * CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
+ * pixel contents.
+ **/
+cairo_status_t
+cairo_surface_write_png_to_stream (cairo_surface_t	*surface,
+				   cairo_write_func_t	write_func,
+				   void			*closure)
+{
+    struct png_write_closure_t png_closure;
+
+    png_closure.write_func = write_func;
+    png_closure.closure = closure;
+
+    return write_png (surface, stream_write_func, &png_closure);
+}				     
+
+static void
 premultiply_data (png_structp   png,
                   png_row_infop row_info,
                   png_bytep     data)
@@ -230,16 +297,13 @@
  * of the PNG file or %NULL if the file is not a valid PNG file or
  * memory could not be allocated for the operation.
  **/
-cairo_surface_t *
-cairo_image_surface_create_from_png (const char *filename)
+static cairo_surface_t *
+read_png (png_rw_ptr	read_func,
+	  void		*closure)
 {
-    FILE *file;
     cairo_surface_t *surface;
     png_byte *data;
     int i;
-#define PNG_SIG_SIZE 8
-    unsigned char png_sig[PNG_SIG_SIZE];
-    int sig_bytes;
     png_struct *png;
     png_info *info;
     png_uint_32 png_width, png_height, stride;
@@ -247,13 +311,9 @@
     unsigned int pixel_size;
     png_byte **row_pointers;
 
-    file = fopen (filename, "rb");
-    if (file == NULL)
-	return NULL;
-
-    sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file);
-    if (sig_bytes != PNG_SIG_SIZE || png_check_sig (png_sig, sig_bytes) == 0)
-	goto BAIL0;
+    surface = NULL;
+    data = NULL;
+    row_pointers = NULL;
 
     /* XXX: Perhaps we'll want some other error handlers? */
     png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
@@ -261,14 +321,16 @@
                                   NULL,
                                   NULL);
     if (png == NULL)
-	goto BAIL0;
+	return NULL;
 
     info = png_create_info_struct (png);
     if (info == NULL)
-	goto BAIL1;
+	goto BAIL;
 
-    png_init_io (png, file);
-    png_set_sig_bytes (png, sig_bytes);
+    png_set_read_fn (png, closure, read_func);
+
+    if (setjmp (png_jmpbuf (png)))
+	goto BAIL;
 
     png_read_info (png, info);
 
@@ -312,11 +374,11 @@
     pixel_size = 4;
     data = malloc (png_width * png_height * pixel_size);
     if (data == NULL)
-	goto BAIL1;
+	goto BAIL;
 
     row_pointers = malloc (png_height * sizeof(char *));
     if (row_pointers == NULL)
-	goto BAIL2;
+	goto BAIL;
 
     for (i = 0; i < png_height; i++)
         row_pointers[i] = &data[i * png_width * pixel_size];
@@ -324,24 +386,93 @@
     png_read_image (png, row_pointers);
     png_read_end (png, info);
 
-    free (row_pointers);
-    png_destroy_read_struct (&png, &info, NULL);
-    fclose (file);
-
     surface = cairo_image_surface_create_for_data (data,
 						   CAIRO_FORMAT_ARGB32,
 						   png_width, png_height, stride);
     _cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
+    data = NULL;
 
-    return surface;
-
- BAIL2:
+ BAIL:
+    free (row_pointers);
     free (data);
- BAIL1:
     png_destroy_read_struct (&png, NULL, NULL);
- BAIL0:
-    fclose (file);
 
-    return NULL;
+    return surface;
 }
-#undef PNG_SIG_SIZE
+
+static void
+stdio_read_func (png_structp png, png_bytep data, png_size_t size)
+{
+    FILE *fp;
+
+    fp = png_get_io_ptr (png);
+    if (fread (data, 1, size, fp) != size)
+	png_error(png, "Read Error");
+}
+
+/**
+ * cairo_image_surface_create_from_png:
+ * @filename: name of PNG file to load 
+ * 
+ * Creates a new image surface and initializes the contents to the
+ * given PNG file.
+ * 
+ * Return value: a new #cairo_surface_t initialized with the contents
+ * of the PNG file or %NULL if the file is not a valid PNG file or
+ * memory could not be allocated for the operation.
+ **/
+cairo_surface_t *
+cairo_image_surface_create_from_png (const char *filename)
+{
+    FILE *fp;
+    cairo_surface_t *surface;
+
+    fp = fopen (filename, "rb");
+    if (fp == NULL)
+	return NULL;
+  
+    surface = read_png (stdio_read_func, fp);
+
+    fclose (fp);
+
+    return surface;
+}
+
+struct png_read_closure_t {
+    cairo_read_func_t	read_func;
+    void			*closure;
+};
+
+static void
+stream_read_func (png_structp png, png_bytep data, png_size_t size)
+{
+    struct png_read_closure_t *png_closure;
+
+    png_closure = png_get_io_ptr (png);
+    if (!CAIRO_OK (png_closure->read_func (png_closure->closure, data, size)))
+	png_error(png, "Read Error");
+}
+
+/**
+ * cairo_image_surface_create_from_png_stream:
+ * @file: a #FILE 
+ * 
+ * Creates a new image surface and initializes the contents to the
+ * given PNG file.
+ * 
+ * Return value: a new #cairo_surface_t initialized with the contents
+ * of the PNG file or %NULL if the file is not a valid PNG file or
+ * memory could not be allocated for the operation.
+ **/
+cairo_surface_t *
+cairo_image_surface_create_from_png_stream (cairo_read_func_t	read_func,
+					    void		*closure)
+{
+    struct png_read_closure_t png_closure;
+
+    png_closure.read_func = read_func;
+    png_closure.closure = closure;
+
+    return read_png (stream_read_func, &closure);
+}
+

Index: cairo.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -d -r1.79 -r1.80
--- cairo.c	19 Apr 2005 23:29:05 -0000	1.79
+++ cairo.c	26 Apr 2005 03:42:54 -0000	1.80
@@ -2323,10 +2323,14 @@
 	return "input string not valid UTF-8";
     case CAIRO_STATUS_INVALID_PATH_DATA:
 	return "input path data not valid";
+    case CAIRO_STATUS_READ_ERROR:
+	return "error while reading from input stream";
     case CAIRO_STATUS_WRITE_ERROR:
 	return "error while writing to output stream";
     case CAIRO_STATUS_SURFACE_FINISHED:
 	return "the target surface has been finished";
+    case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
+	return "the surface type is not appropriate for the operation";
     }
 
     return "<unknown error status>";

Index: cairo.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.h,v
retrieving revision 1.101
retrieving revision 1.102
diff -u -d -r1.101 -r1.102
--- cairo.h	23 Apr 2005 00:32:12 -0000	1.101
+++ cairo.h	26 Apr 2005 03:42:54 -0000	1.102
@@ -135,10 +135,42 @@
     CAIRO_STATUS_NULL_POINTER,
     CAIRO_STATUS_INVALID_STRING,
     CAIRO_STATUS_INVALID_PATH_DATA,
+    CAIRO_STATUS_READ_ERROR,
     CAIRO_STATUS_WRITE_ERROR,
-    CAIRO_STATUS_SURFACE_FINISHED
+    CAIRO_STATUS_SURFACE_FINISHED,
+    CAIRO_STATUS_SURFACE_TYPE_MISMATCH
 } cairo_status_t;
 
+/**
+ * cairo_write_func_t
+ *
+ * #cairo_write_func_t is the type of function which is called when a
+ * backend needs to write data to an output stream.  It is passed the
+ * closure which was specified by the user at the time the write
+ * function was registered, the data to write and the length of the
+ * data in bytes.  The write function should return
+ * CAIRO_STATUS_SUCCESS if all the data was successfully written,
+ * CAIRO_STATUS_WRITE_ERROR otherwise.
+ */
+typedef cairo_status_t (*cairo_write_func_t) (void		  *closure,
+					      const unsigned char *data,
+					      unsigned int	   length);
+
+/**
+ * cairo_read_func_t
+ *
+ * #cairo_read_func_t is the type of function which is called when a
+ * backend needs to read data from an intput stream.  It is passed the
+ * closure which was specified by the user at the time the read
+ * function was registered, the buffer to read the data into and the
+ * length of the data in bytes.  The read function should return
+ * CAIRO_STATUS_SUCCESS if all the data was successfully written,
+ * CAIRO_STATUS_READ_ERROR otherwise.
+ */
+typedef cairo_status_t (*cairo_read_func_t) (void		*closure,
+					     unsigned char	*data,
+					     unsigned int	length);
+
 /* Functions for manipulating state objects */
 cairo_t *
 cairo_create (void);
@@ -895,9 +927,16 @@
 cairo_surface_finish (cairo_surface_t *surface);
 
 #ifdef CAIRO_HAS_PNG_FUNCTIONS
+
 cairo_status_t
 cairo_surface_write_png (cairo_surface_t	*surface,
 			 const char		*filename);
+
+cairo_status_t
+cairo_surface_write_png_to_stream (cairo_surface_t	*surface,
+				   cairo_write_func_t	write_func,
+				   void			*closure);
+
 #endif
 
 /* XXX: Note: The current Render/Ic implementations don't do the right
@@ -959,9 +998,21 @@
 				     int			height,
 				     int			stride);
 
+int
+cairo_image_surface_get_width (cairo_surface_t *surface);
+
+int
+cairo_image_surface_get_height (cairo_surface_t *surface);
+
 #ifdef CAIRO_HAS_PNG_FUNCTIONS
+
 cairo_surface_t *
 cairo_image_surface_create_from_png (const char	*filename);
+
+cairo_surface_t *
+cairo_image_surface_create_from_png_stream (cairo_read_func_t	read_func,
+					    void		*closure);
+
 #endif
 
 /* Pattern creation functions */
@@ -1082,21 +1133,6 @@
 void
 cairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y);
 
-/**
- * cairo_write_func_t
- *
- * #cairo_write_func_t is the type of function which is called when a
- * backend needs to write data to an output stream.  It is passed the
- * closure which was specified by the user at the time the write
- * function was registered, the data to write and the length of the
- * data in bytes.  The write function should return
- * CAIRO_STATUS_SUCCESS if all the data was successfully written,
- * CAIRO_STATUS_WRITE_ERROR otherwise.
- */
-typedef cairo_status_t (*cairo_write_func_t) (void		  *closure,
-					      const unsigned char *data,
-					      unsigned int	   length);
-
 #define CAIRO_API_SHAKEUP_FLAG_DAY 0
 
 #ifndef _CAIROINT_H_




More information about the cairo-commit mailing list