[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