[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.)
This commit is contained in:
Vladimir Vukicevic 2008-03-04 00:15:46 -08:00 committed by Vladimir Vukicevic
parent 4a1f65b63e
commit d89edde84d

View file

@ -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: