commit 154b4face2de9b1cf5bf7f70ed427b70587ac264 Author: Carl Worth Date: Mon May 1 10:17:08 2006 -0700 Support multiple glyph image formats within the same font. If we find a glyph image of a format that is different from the font's format, then we use a temporary image and convert to the font's format. This is the simplest way to avoid the crash identified in bug #4075: https://bugs.freedesktop.org/show_bug.cgi?id=4705 A later improvement would guarantee that the "font's format" was carefully chosen to be able to contain all glyphs in the font without information loss. diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 0f195bf..c2eeab9 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -2009,7 +2009,8 @@ cairo_xlib_surface_set_drawable (cairo_s typedef struct _cairo_xlib_surface_font_private { Display *dpy; GlyphSet glyphset; - XRenderPictFormat *format; + cairo_format_t format; + XRenderPictFormat *xrender_format; } cairo_xlib_surface_font_private_t; static cairo_status_t @@ -2024,8 +2025,9 @@ _cairo_xlib_surface_font_init (Display return CAIRO_STATUS_NO_MEMORY; font_private->dpy = dpy; - font_private->format = _CAIRO_FORMAT_XRENDER_FORMAT(dpy, format); - font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->format); + font_private->format = format; + font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format); + font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format); scaled_font->surface_private = font_private; scaled_font->surface_backend = &cairo_xlib_surface_backend; return CAIRO_STATUS_SUCCESS; @@ -2072,7 +2074,7 @@ _cairo_xlib_surface_add_glyph (Display * XGlyphInfo glyph_info; unsigned long glyph_index; unsigned char *data; - cairo_status_t status; + cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_xlib_surface_font_private_t *font_private; cairo_image_surface_t *glyph_surface = scaled_glyph->surface; @@ -2084,6 +2086,32 @@ _cairo_xlib_surface_add_glyph (Display * } font_private = scaled_font->surface_private; + /* If the glyph format does not match the font format, then we + * create a temporary surface for the glyph image with the font's + * format. + */ + if (glyph_surface->format != font_private->format) { + cairo_t *cr; + cairo_surface_t *tmp_surface; + + tmp_surface = cairo_image_surface_create (font_private->format, + glyph_surface->width, + glyph_surface->height); + cr = cairo_create (tmp_surface); + cairo_set_source_surface (cr, &glyph_surface->base, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + status = cairo_status (cr); + + cairo_destroy (cr); + + glyph_surface = (cairo_image_surface_t *) tmp_surface; + + if (status) + goto BAIL; + } + /* * Most of the font rendering system thinks of glyph tiles as having * an origin at (0,0) and an x and y bounding box "offset" which @@ -2139,8 +2167,10 @@ _cairo_xlib_surface_add_glyph (Display * unsigned char *new, *n; new = malloc (c); - if (!new) - return CAIRO_STATUS_NO_MEMORY; + if (!new) { + status = CAIRO_STATUS_NO_MEMORY; + goto BAIL; + } n = new; d = data; while (c--) @@ -2163,8 +2193,10 @@ _cairo_xlib_surface_add_glyph (Display * unsigned char *new, *n; new = malloc (c); - if (new == NULL) - return CAIRO_STATUS_NO_MEMORY; + if (new == NULL) { + status = CAIRO_STATUS_NO_MEMORY; + goto BAIL; + } n = new; d = data; while ((c -= 4) >= 0) @@ -2196,7 +2228,11 @@ _cairo_xlib_surface_add_glyph (Display * if (data != glyph_surface->data) free (data); - return CAIRO_STATUS_SUCCESS; + BAIL: + if (glyph_surface != scaled_glyph->surface) + cairo_surface_destroy (&glyph_surface->base); + + return status; } #define N_STACK_BUF 1024 @@ -2252,7 +2288,7 @@ _cairo_xlib_surface_old_show_glyphs8 (c _render_operator (op), src->src_picture, self->dst_picture, - font_private->format, + font_private->xrender_format, source_x + elts[0].xOff, source_y + elts[0].yOff, 0, 0, elts, num_glyphs); @@ -2314,7 +2350,7 @@ _cairo_xlib_surface_old_show_glyphs16 (c _render_operator (op), src->src_picture, self->dst_picture, - font_private->format, + font_private->xrender_format, source_x + elts[0].xOff, source_y + elts[0].yOff, 0, 0, elts, num_glyphs); @@ -2376,7 +2412,7 @@ _cairo_xlib_surface_old_show_glyphs32 (c _render_operator (op), src->src_picture, self->dst_picture, - font_private->format, + font_private->xrender_format, source_x + elts[0].xOff, source_y + elts[0].yOff, 0, 0, elts, num_glyphs); @@ -2413,7 +2449,6 @@ _cairo_xlib_surface_old_show_glyphs (cai int i; unsigned long max_index = 0; - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->format) return CAIRO_INT_STATUS_UNSUPPORTED;