[cairo-commit] 2 commits - src/cairo-meta-surface.c src/cairo-png.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Apr 21 10:35:41 PDT 2008


 src/cairo-meta-surface.c |    8 ++++++--
 src/cairo-png.c          |   19 ++++++++++++++-----
 2 files changed, 20 insertions(+), 7 deletions(-)

New commits:
commit f2f91db131e7c7df1e87bcd41ae17c07429bbcb8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Apr 21 18:20:16 2008 +0100

    [cairo-png] Create an ARGB32 surface for paletted PNGs.
    
    jeremie54 reported a regression in the handling of transparent paletted
    PNGs beween 1.4.14 and 1.6.4. This was caused by the change to load
    opaque PNGs into a RGB24 image surface, which made the assumption that
    indexed PNGs were opaque. However, alpha/transparency in PNG is more
    complicated, as PNG uses a tRNS chunk to supply transparency data for
    paletted images and other image types that don't need a full alpha
    channel. Therefore if the PNG contains a tRNS chunk always generate an
    ARGB32 surface.

diff --git a/src/cairo-png.c b/src/cairo-png.c
index 0db4b09..3ec85c0 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -434,6 +434,7 @@ read_png (png_rw_ptr	read_func,
     unsigned int i;
     cairo_format_t format;
     cairo_status_t status;
+    cairo_bool_t need_alpha;
 
     /* XXX: Perhaps we'll want some other error handlers? */
     png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
@@ -485,8 +486,11 @@ read_png (png_rw_ptr	read_func,
     }
 
     /* transform transparency to alpha */
-    if (png_get_valid (png, info, PNG_INFO_tRNS))
+    need_alpha = FALSE;
+    if (png_get_valid (png, info, PNG_INFO_tRNS)) {
         png_set_tRNS_to_alpha (png);
+	need_alpha = TRUE;
+    }
 
     if (depth == 16)
         png_set_strip_16 (png);
@@ -513,11 +517,16 @@ read_png (png_rw_ptr	read_func,
 	    break;
 
 	case PNG_COLOR_TYPE_GRAY:
-	case PNG_COLOR_TYPE_PALETTE:
 	case PNG_COLOR_TYPE_RGB:
-	    format = CAIRO_FORMAT_RGB24;
-	    png_set_read_user_transform_fn (png, convert_bytes_to_data);
-	    png_set_filler (png, 0xff, PNG_FILLER_AFTER);
+	case PNG_COLOR_TYPE_PALETTE:
+	    if (need_alpha) {
+		format = CAIRO_FORMAT_ARGB32;
+		png_set_read_user_transform_fn (png, premultiply_data);
+	    } else {
+		format = CAIRO_FORMAT_RGB24;
+		png_set_read_user_transform_fn (png, convert_bytes_to_data);
+		png_set_filler (png, 0xff, PNG_FILLER_AFTER);
+	    }
 	    break;
     }
 
commit ea6dbfd36f2182fda16cb82bca92007e0f7b8d77
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Apr 16 17:24:43 2008 +0100

    [cairo-meta-surface] Save and restore the original clip.
    
    When replaying the meta-surface to the target, we apply a stack-based
    clip to the surface. However, we did not remove this clip from the
    surface and so a pointer into our stack existed beyond the scope of
    function.
    
    Saving the original clip pointer and restoring it before leaving the
    function resolves the issue and appears to fix
    https://bugzilla.mozilla.org/show_bug.cgi?id=429071.

diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 441a7d6..61c9b5d 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -658,8 +658,8 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
     cairo_meta_surface_t *meta;
     cairo_command_t *command, **elements;
     int i, num_elements;
-    cairo_int_status_t status;
-    cairo_clip_t clip;
+    cairo_int_status_t status, status2;
+    cairo_clip_t clip, *old_clip;
     cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target);
     cairo_matrix_t *device_transform = &target->device_transform;
     cairo_path_fixed_t path_copy, *dev_path;
@@ -674,6 +674,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
     status = CAIRO_STATUS_SUCCESS;
 
     _cairo_clip_init (&clip, target);
+    old_clip = _cairo_surface_get_clip (target);
 
     num_elements = meta->commands.num_elements;
     elements = _cairo_array_index (&meta->commands, 0);
@@ -867,6 +868,9 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
     }
 
     _cairo_clip_reset (&clip);
+    status2 = _cairo_surface_set_clip (target, old_clip);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = status2;
 
     return _cairo_surface_set_error (surface, status);
 }


More information about the cairo-commit mailing list