[cairo-commit] src/cairo-xlib-surface.c

Carl Worth cworth at kemper.freedesktop.org
Thu Jul 27 00:23:47 PDT 2006


 src/cairo-xlib-surface.c |   28 ++++++++++++++++++++++------
 1 files changed, 22 insertions(+), 6 deletions(-)

New commits:
diff-tree 456cdb3058f3b416109a9600167cd8842300ae14 (from 8601c2c68306c956744399099a941363d446b906)
Author: Carl Worth <cworth at cworth.org>
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 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.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index cac6787..58ad459 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 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   
         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);


More information about the cairo-commit mailing list