[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