[cairo-commit] src/cairo-meta-surface.c

Vladimir Vukicevic vladimir at kemper.freedesktop.org
Tue Mar 4 00:16:28 PST 2008


 src/cairo-meta-surface.c |   24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

New commits:
commit d89edde84de9cec9ce6f76f4f2c44dd9c1220528
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Mar 4 00:15:46 2008 -0800

    [meta] always copy glyph array before passing to _cairo_surface_show_glyphs
    
    _cairo_surface_show_glyphs is allowed to mutate the glyph array; if it's
    handed the internal array that the meta surface holds, then any subsequent
    playback (such as for fine-grained fallbacks) will result in incorrect
    glyph rendering.
    
    Ref: https://bugzilla.mozilla.org/show_bug.cgi?id=419917
    (I was unable to create a simple cairo testcase to demonstrate the problem.)

diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 5248947..66849b4 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2005 Red Hat, Inc
@@ -803,21 +804,28 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 	case CAIRO_COMMAND_SHOW_GLYPHS:
 	{
 	    cairo_glyph_t *glyphs = command->show_glyphs.glyphs;
-	    cairo_glyph_t *dev_glyphs = glyphs;
+	    cairo_glyph_t *dev_glyphs;
 	    int i, num_glyphs = command->show_glyphs.num_glyphs;
 
+            /* show_glyphs is special because _cairo_surface_show_glyphs is allowed
+	     * to modify the glyph array that's passed in.  We must always
+	     * copy the array before handing it to the backend.
+	     */
+	    dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+	    if (dev_glyphs == NULL) {
+		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		break;
+	    }
+
 	    if (has_device_transform) {
-		dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
-		if (dev_glyphs == NULL) {
-		    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-		    break;
-		}
 		for (i = 0; i < num_glyphs; i++) {
 		    dev_glyphs[i] = glyphs[i];
 		    cairo_matrix_transform_point (device_transform,
 						  &dev_glyphs[i].x,
 						  &dev_glyphs[i].y);
 		}
+	    } else {
+		memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
 	    }
 
 	    status = _cairo_surface_show_glyphs	(target,
@@ -826,9 +834,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 						 dev_glyphs, num_glyphs,
 						 command->show_glyphs.scaled_font);
 
-	    if (dev_glyphs != glyphs)
-		free (dev_glyphs);
-
+	    free (dev_glyphs);
 	    break;
 	}
 	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:


More information about the cairo-commit mailing list