--- libgxps-0.3.0/libgxps/gxps-brush.c +++ libgxps-0.3.0/libgxps/gxps-brush.c @@ -965,7 +965,7 @@ brush_end_element (GMarkupParseContext g_markup_parse_context_pop (context); } else if (strcmp (element_name, "ImageBrush") == 0) { GXPSBrushImage *brush_image; - GXPSImage *image; + cairo_surface_t *image; GError *err = NULL; brush_image = g_markup_parse_context_pop (context); @@ -976,14 +976,20 @@ brush_end_element (GMarkupParseContext cairo_matrix_t matrix; gdouble x_scale, y_scale; cairo_surface_t *clip_surface; + double *res_x, *res_y; - /* viewbox units is 1/96 inch, convert to pixels */ - brush_image->viewbox.x *= image->res_x / 96; - brush_image->viewbox.y *= image->res_y / 96; - brush_image->viewbox.width *= image->res_x / 96; - brush_image->viewbox.height *= image->res_y / 96; + res_x = cairo_surface_get_user_data (image, (const cairo_user_data_key_t *) 0x1); + res_y = cairo_surface_get_user_data (image, (const cairo_user_data_key_t *) 0x2); - clip_surface = cairo_surface_create_for_rectangle (image->surface, + if (res_x != NULL && res_y != NULL) { + /* viewbox units is 1/96 inch, convert to pixels */ + brush_image->viewbox.x *= *res_x / 96; + brush_image->viewbox.y *= *res_y / 96; + brush_image->viewbox.width *= *res_x / 96; + brush_image->viewbox.height *= *res_y / 96; + } + + clip_surface = cairo_surface_create_for_rectangle (image, brush_image->viewbox.x, brush_image->viewbox.y, brush_image->viewbox.width, --- libgxps-0.3.0/libgxps/gxps-images.c +++ libgxps-0.3.0/libgxps/gxps-images.c @@ -88,6 +88,45 @@ multiply_alpha (int alpha, int color) return ((temp + (temp >> 8)) >> 8); } +static void +image_set_res_x (cairo_surface_t *image, + double res_x) +{ + double *x; + + x = g_new (double, 1); + *x = res_x; + + cairo_surface_set_user_data (image, + (const cairo_user_data_key_t *) 0x1, + x, + (cairo_destroy_func_t) g_free); +} + +static void +image_set_res_y (cairo_surface_t *image, + double res_y) +{ + double *y; + + y = g_new (double, 1); + *y = res_y; + + cairo_surface_set_user_data (image, + (const cairo_user_data_key_t *) 0x2, + y, + (cairo_destroy_func_t) g_free); +} + +static void +image_set_res (cairo_surface_t *image, + double res_x, + double res_y) +{ + image_set_res_x (image, res_x); + image_set_res_y (image, res_y); +} + /* Premultiplies data and converts RGBA bytes => native endian * From cairo's cairo-png.c */ static void @@ -163,14 +202,14 @@ fill_png_error (GError **error, /* Adapted from cairo's read_png in cairo-png.c * http://cairographics.org/ */ -static GXPSImage * +static cairo_surface_t * gxps_images_create_from_png (GXPSArchive *zip, const gchar *image_uri, GError **error) { #ifdef HAVE_LIBPNG GInputStream *stream; - GXPSImage *image = NULL; + cairo_surface_t *image = NULL; char *png_err_msg = NULL; png_struct *png; png_info *info; @@ -181,6 +220,7 @@ gxps_images_create_from_png (GXPSArchive unsigned int i; cairo_format_t format; cairo_status_t status; + double res_x, res_y; stream = gxps_archive_open (zip, image_uri); if (!stream) { @@ -217,7 +257,7 @@ gxps_images_create_from_png (GXPSArchive g_free (png_err_msg); g_object_unref (stream); png_destroy_read_struct (&png, &info, NULL); - gxps_image_free (image); + cairo_surface_destroy (image); g_free (row_pointers); g_free (data); return NULL; @@ -295,13 +335,12 @@ gxps_images_create_from_png (GXPSArchive return NULL; } - image = g_slice_new0 (GXPSImage); - image->res_x = png_get_x_pixels_per_meter (png, info) * METERS_PER_INCH; - if (image->res_x == 0) - image->res_x = 96; - image->res_y = png_get_y_pixels_per_meter (png, info) * METERS_PER_INCH; - if (image->res_y == 0) - image->res_y = 96; + res_x = png_get_x_pixels_per_meter (png, info) * METERS_PER_INCH; + if (res_x == 0) + res_x = 96; + res_y = png_get_y_pixels_per_meter (png, info) * METERS_PER_INCH; + if (res_y == 0) + res_y = 96; data = g_malloc (png_height * stride); row_pointers = g_new (png_byte *, png_height); @@ -315,23 +354,25 @@ gxps_images_create_from_png (GXPSArchive g_object_unref (stream); g_free (row_pointers); - image->surface = cairo_image_surface_create_for_data (data, format, - png_width, png_height, - stride); - if (cairo_surface_status (image->surface)) { + image = cairo_image_surface_create_for_data (data, format, + png_width, png_height, + stride); + if (cairo_surface_status (image)) { fill_png_error (error, image_uri, NULL); - gxps_image_free (image); + cairo_surface_destroy (image); g_free (data); return NULL; } - status = cairo_surface_set_user_data (image->surface, + image_set_res (image, res_x, res_y); + + status = cairo_surface_set_user_data (image, &image_data_cairo_key, data, (cairo_destroy_func_t) g_free); if (status) { fill_png_error (error, image_uri, NULL); - gxps_image_free (image); + cairo_surface_destroy (image); g_free (data); return NULL; } @@ -423,7 +463,7 @@ _jpeg_error_exit (j_common_ptr error) } #endif /* HAVE_LIBJPEG */ -static GXPSImage * +static cairo_surface_t * gxps_images_create_from_jpeg (GXPSArchive *zip, const gchar *image_uri, GError **error) @@ -433,7 +473,7 @@ gxps_images_create_from_jpeg (GXPSArchiv struct jpeg_error_mgr error_mgr; struct jpeg_decompress_struct cinfo; struct _jpeg_src_mgr src; - GXPSImage *image; + cairo_surface_t *image; guchar *data; gint stride; JSAMPARRAY lines; @@ -484,28 +524,26 @@ gxps_images_create_from_jpeg (GXPSArchiv cinfo.do_fancy_upsampling = FALSE; jpeg_start_decompress (&cinfo); - image = g_slice_new (GXPSImage); - image->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, - cinfo.output_width, - cinfo.output_height); - image->res_x = 96; - image->res_y = 96; - if (cairo_surface_status (image->surface)) { + image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, + cinfo.output_width, + cinfo.output_height); + image_set_res (image, 96, 96); + if (cairo_surface_status (image)) { g_set_error (error, GXPS_ERROR, GXPS_ERROR_IMAGE, "Error loading JPEG image %s: %s", image_uri, - cairo_status_to_string (cairo_surface_status (image->surface))); + cairo_status_to_string (cairo_surface_status (image))); jpeg_destroy_decompress (&cinfo); - gxps_image_free (image); + cairo_surface_destroy (image); g_object_unref (stream); return NULL; } - data = cairo_image_surface_get_data (image->surface); - stride = cairo_image_surface_get_stride (image->surface); + data = cairo_image_surface_get_data (image); + stride = cairo_image_surface_get_stride (image); jpeg_stride = cinfo.output_width * cinfo.out_color_components; lines = cinfo.mem->alloc_sarray((j_common_ptr) &cinfo, JPOOL_IMAGE, jpeg_stride, 4); @@ -535,7 +573,7 @@ gxps_images_create_from_jpeg (GXPSArchiv GXPS_DEBUG (g_message ("Unsupported jpeg color space %s", _jpeg_color_space_name (cinfo.out_color_space))); - gxps_image_free (image); + cairo_surface_destroy (image); jpeg_destroy_decompress (&cinfo); g_object_unref (stream); return NULL; @@ -549,27 +587,25 @@ gxps_images_create_from_jpeg (GXPSArchiv } if (cinfo.density_unit == 1) { /* dots/inch */ - image->res_x = cinfo.X_density; - image->res_y = cinfo.Y_density; + image_set_res (image, cinfo.X_density, cinfo.Y_density); } else if (cinfo.density_unit == 2) { /* dots/cm */ - image->res_x = cinfo.X_density * CENTIMETERS_PER_INCH; - image->res_y = cinfo.Y_density * CENTIMETERS_PER_INCH; + image_set_res (image, cinfo.X_density * CENTIMETERS_PER_INCH, cinfo.Y_density * CENTIMETERS_PER_INCH); } jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); g_object_unref (stream); - cairo_surface_mark_dirty (image->surface); + cairo_surface_mark_dirty (image); - if (cairo_surface_status (image->surface)) { + if (cairo_surface_status (image)) { g_set_error (error, GXPS_ERROR, GXPS_ERROR_IMAGE, "Error loading JPEG image %s: %s", image_uri, - cairo_status_to_string (cairo_surface_status (image->surface))); - gxps_image_free (image); + cairo_status_to_string (cairo_surface_status (image))); + cairo_surface_destroy (image); return NULL; } @@ -728,7 +764,7 @@ _tiff_unmap_file (thandle_t handle, } #endif /* #ifdef HAVE_LIBTIFF */ -static GXPSImage * +static cairo_surface_t * gxps_images_create_from_tiff (GXPSArchive *zip, const gchar *image_uri, GError **error) @@ -736,7 +772,7 @@ gxps_images_create_from_tiff (GXPSArchiv #ifdef HAVE_LIBTIFF TIFF *tiff; TiffBuffer buffer; - GXPSImage *image; + cairo_surface_t *image; gint width, height; guint16 res_unit; float res_x, res_y; @@ -802,49 +838,47 @@ gxps_images_create_from_tiff (GXPSArchiv return NULL; } - image = g_slice_new (GXPSImage); - image->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, - width, height); - image->res_x = 96; - image->res_y = 96; + image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, + width, height); + image_set_res (image, 96, 96); if (!TIFFGetField (tiff, TIFFTAG_RESOLUTIONUNIT, &res_unit)) res_unit = 0; if (TIFFGetField (tiff, TIFFTAG_XRESOLUTION, &res_x)) { if (res_unit == 2) { /* inches */ - image->res_x = res_x; + image_set_res_x (image, res_x); } else if (res_unit == 3) { /* centimeters */ - image->res_x = res_x * CENTIMETERS_PER_INCH; + image_set_res_x (image, res_x * CENTIMETERS_PER_INCH); } } if (TIFFGetField (tiff, TIFFTAG_YRESOLUTION, &res_y)) { if (res_unit == 2) { /* inches */ - image->res_y = res_y; + image_set_res_y (image, res_y); } else if (res_unit == 3) { /* centimeters */ - image->res_y = res_y * CENTIMETERS_PER_INCH; + image_set_res_y (image, res_y * CENTIMETERS_PER_INCH); } } - if (cairo_surface_status (image->surface)) { + if (cairo_surface_status (image)) { g_set_error (error, GXPS_ERROR, GXPS_ERROR_IMAGE, "Error loading TIFF image %s: %s", image_uri, - cairo_status_to_string (cairo_surface_status (image->surface))); - gxps_image_free (image); + cairo_status_to_string (cairo_surface_status (image))); + cairo_surface_destroy (image); TIFFClose (tiff); _tiff_pop_handlers (); g_free (buffer.buffer); return NULL; } - data = cairo_image_surface_get_data (image->surface); + data = cairo_image_surface_get_data (image); if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32 *)data, ORIENTATION_TOPLEFT, 1) || _tiff_error) { fill_tiff_error (error, image_uri); - gxps_image_free (image); + cairo_surface_destroy (image); TIFFClose (tiff); _tiff_pop_handlers (); g_free (buffer.buffer); @@ -855,7 +889,7 @@ gxps_images_create_from_tiff (GXPSArchiv _tiff_pop_handlers (); g_free (buffer.buffer); - stride = cairo_image_surface_get_stride (image->surface); + stride = cairo_image_surface_get_stride (image); p = data; while (p < data + (height * stride)) { guint32 *pixel = (guint32 *)p; @@ -869,7 +903,7 @@ gxps_images_create_from_tiff (GXPSArchiv p += 4; } - cairo_surface_mark_dirty (image->surface); + cairo_surface_mark_dirty (image); return image; #else @@ -897,12 +931,12 @@ gxps_images_guess_content_type (GXPSArch return mime_type; } -GXPSImage * +cairo_surface_t * gxps_images_get_image (GXPSArchive *zip, const gchar *image_uri, GError **error) { - GXPSImage *image = NULL; + cairo_surface_t *image = NULL; gchar *image_uri_lower; /* First try with extensions, @@ -942,15 +976,3 @@ gxps_images_get_image (GXPSArchive *zip, return image; } - -void -gxps_image_free (GXPSImage *image) -{ - if (G_UNLIKELY (!image)) - return; - - if (G_LIKELY (image->surface)) - cairo_surface_destroy (image->surface); - - g_slice_free (GXPSImage, image); -} --- libgxps-0.3.0/libgxps/gxps-images.h +++ libgxps-0.3.0/libgxps/gxps-images.h @@ -25,18 +25,9 @@ G_BEGIN_DECLS -typedef struct _GXPSImage GXPSImage; - -struct _GXPSImage { - cairo_surface_t *surface; - double res_x; - double res_y; -}; - -GXPSImage *gxps_images_get_image (GXPSArchive *zip, - const gchar *image_uri, - GError **error); -void gxps_image_free (GXPSImage *image); +cairo_surface_t *gxps_images_get_image (GXPSArchive *zip, + const gchar *image_uri, + GError **error); G_END_DECLS --- libgxps-0.3.0/libgxps/gxps-page.c +++ libgxps-0.3.0/libgxps/gxps-page.c @@ -77,12 +77,12 @@ gxps_page_error_quark (void) } /* Images */ -GXPSImage * +cairo_surface_t * gxps_page_get_image (GXPSPage *page, const gchar *image_uri, GError **error) { - GXPSImage *image; + cairo_surface_t *image; if (page->priv->image_cache) { image = g_hash_table_lookup (page->priv->image_cache, @@ -99,12 +99,12 @@ gxps_page_get_image (GXPSPage *page, page->priv->image_cache = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, - (GDestroyNotify)gxps_image_free); + (GDestroyNotify)cairo_surface_destroy); } g_hash_table_insert (page->priv->image_cache, g_strdup (image_uri), - image); + cairo_surface_reference (image)); return image; } --- libgxps-0.3.0/libgxps/gxps-page-private.h +++ libgxps-0.3.0/libgxps/gxps-page-private.h @@ -58,9 +58,9 @@ struct _GXPSRenderContext { GXPSBrushVisual *visual; }; -GXPSImage *gxps_page_get_image (GXPSPage *page, - const gchar *image_uri, - GError **error); +cairo_surface_t *gxps_page_get_image (GXPSPage *page, + const gchar *image_uri, + GError **error); void gxps_page_render_parser_push (GMarkupParseContext *context, GXPSRenderContext *ctx);