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 zero size 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 size-zero glyphs so that the X server never sees them.
This commit is contained in:
Carl Worth 2006-07-26 15:48:56 -07:00
parent 8601c2c683
commit 456cdb3058

View file

@ -2674,12 +2674,13 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
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 *abstract_dst,
(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 size-zero
* 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 *abstract_dst,
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 *abstract_dst,
&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 *abstract_dst,
}
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 *abstract_dst,
BAIL:
_cairo_scaled_font_thaw_cache (scaled_font);
free (output_glyphs);
if (src)
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);