commit 2010753cc750ff804e373f1bdd4cd31def786368 Author: Carl Worth Date: Wed Jul 26 15:48:56 2006 -0700 Elide size-zero glyphs from calls to XRender functions. There appears to be a bug in some X servers which is triggered by rendering 1-bit glyphs with a size of 0x0 via the functions XRenderAddGlyphs and XRenderCompositeText8 (and likely its variants). We avoid this bug by making a copy of the glyphs array which does not include any of the 0x0 glyphs so that the X server never sees them. diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index cac6787..2067c98 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -2674,12 +2674,13 @@ _cairo_xlib_surface_show_glyphs (void cairo_surface_attributes_t attributes; cairo_xlib_surface_t *src = NULL; + cairo_glyph_t *output_glyphs; const cairo_glyph_t *glyphs_chunk; int glyphs_remaining, chunk_size, max_chunk_size; cairo_scaled_glyph_t *scaled_glyph; cairo_xlib_surface_font_private_t *font_private; - int i; + int i, o; unsigned long max_index = 0; cairo_xlib_surface_show_glyphs_func_t show_glyphs_func; @@ -2723,6 +2724,13 @@ _cairo_xlib_surface_show_glyphs (void (font_private != NULL && font_private->dpy != dst->dpy)) return CAIRO_INT_STATUS_UNSUPPORTED; + /* We make a copy of the glyphs so that we can elide any 0x0 + * glyphs to workaround an X server bug, (present in at least Xorg + * 7.1 without EXA). */ + output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t)); + if (output_glyphs == NULL) + return CAIRO_STATUS_NO_MEMORY; + /* After passing all those tests, we're now committed to rendering * these glyphs or to fail trying. We first upload any glyphs to * the X server that it doesn't have already, then we draw @@ -2781,7 +2789,7 @@ _cairo_xlib_surface_show_glyphs (void goto BAIL; /* Send all unsent glyphs to the server, and count the max of the glyph indices */ - for (i = 0; i < num_glyphs; i++) { + for (i = 0, o = 0; i < num_glyphs; i++) { if (glyphs[i].index > max_index) max_index = glyphs[i].index; status = _cairo_scaled_glyph_lookup (scaled_font, @@ -2790,11 +2798,18 @@ _cairo_xlib_surface_show_glyphs (void &scaled_glyph); if (status != CAIRO_STATUS_SUCCESS) goto BAIL; - if (scaled_glyph->surface_private == NULL) { - _cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph); - scaled_glyph->surface_private = (void *) 1; + /* Don't put any size-zero glyphs into output_glyphs to avoid + * an X server bug which stops rendering glyphs after the + * first size-zero glyph. */ + if (scaled_glyph->surface->width && scaled_glyph->surface->height) { + output_glyphs[o++] = glyphs[i]; + if (scaled_glyph->surface_private == NULL) { + _cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph); + scaled_glyph->surface_private = (void *) 1; + } } } + num_glyphs = o; _cairo_xlib_surface_ensure_dst_picture (dst); @@ -2811,7 +2826,7 @@ _cairo_xlib_surface_show_glyphs (void } max_chunk_size /= sz_xGlyphElt; - for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs; + for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs; glyphs_remaining; glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size) { @@ -2826,6 +2841,7 @@ _cairo_xlib_surface_show_glyphs (void BAIL: _cairo_scaled_font_thaw_cache (scaled_font); + free (output_glyphs); if (src) _cairo_pattern_release_surface (src_pattern, &src->base, &attributes);