[cairo] Re: crash at XRenderAddGlyphs.

sunmoon1997 sunmoon1997 at gmail.com
Wed Sep 28 05:01:43 PDT 2005


my mistake again, attached a wrong file,
sunmoon1997 wrote:
> hi,
>  here is an earlier stage patch, it just make apps not crash and not
> works very well, some character disappeared...:(.
> 
> sunmoon1997 wrote:
> 
>>sorry, i accidently encrypted this mail.
>>sunmoon1997 wrote:
>>
>>
>>>>hi,
>>>>   Currenty cairo xlib backend assume that the depth of glyphs from a font face are the same, but this is not true for some embedded bitmap fonts.  The may have two different depth glyphs, from my attached file,
>>>>you can see the fist four glyphs are 1-bit bitmap, but latter depth become 8-bit. Cairo only extracts the format information from the fisrt glyph, if glyph depth changed, cairo still use the old formation info,
>>>>and sends the glyph to X server, then X will complain cairo sended too much bits to it and reply an error (bad length) that will crash a lot of apps.
>>
>>
>>------------------------------------------------------------------------
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x81104d0) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x814b790 "@", owns_data = 1,
>>has_clip = 0,
>>  width = 13, height = 13, stride = 4, depth = 1, pixman_image = 0x8117eb8}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x8141bc8) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x8118950 " ", owns_data = 1,
>>has_clip = 0,
>>  width = 13, height = 13, stride = 4, depth = 1, pixman_image = 0x814bb38}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x8141c28) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x814bc20 "\020\001", owns_data = 1,
>>  has_clip = 0, width = 13, height = 13, stride = 4, depth = 1,
>>  pixman_image = 0x814bc58}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x8118668) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x814bd60 " ", owns_data = 1,
>>has_clip = 0,
>>  width = 13, height = 13, stride = 4, depth = 1, pixman_image = 0x814bdc0}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x81186c8) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x814bec8 " ", owns_data = 1,
>>has_clip = 0,
>>  width = 13, height = 13, stride = 4, depth = 1, pixman_image = 0x814bf28}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x8118728) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x814c030 "\204", owns_data = 1,
>>  has_clip = 0, width = 13, height = 13, stride = 4, depth = 1,
>>  pixman_image = 0x814c090}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x8118788) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x814c198 "\030", owns_data = 1,
>>  has_clip = 0, width = 13, height = 13, stride = 4, depth = 1,
>>  pixman_image = 0x814c1f8}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x81187e8) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -11, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A1, data = 0x814c300 "\202", owns_data = 1,
>>  has_clip = 0, width = 13, height = 13, stride = 4, depth = 1,
>>  pixman_image = 0x814c360}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x8118848) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 0, device_y_offset = -0, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A8, data = 0x0, owns_data = 0, has_clip = 0,
>>  width = 0, height = 0, stride = 0, depth = 8, pixman_image = 0x814c490}
>>(gdb)
>>Continuing.
>>
>>Breakpoint 1, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x81188a8) at
>>cairo-xlib-surface.c:2076
>>2076        cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 1, device_y_offset = -9, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A8, data = 0x814c598 "hå?´è±?", owns_data = 1,
>>  has_clip = 0, width = 5, height = 9, stride = 8, depth = 8,
>>  pixman_image = 0x814c610}
>>(gdb) display glyph_info
>>6: glyph_info = {width = 53502, height = 47051, x = 10020, y = -18443,
>>  xOff = -26856, yOff = -16490}
>>(gdb) b 2195
>>Breakpoint 2 at 0xb7f1b444: file cairo-xlib-surface.c, line 2195.
>>(gdb) continue
>>Continuing.
>>
>>Breakpoint 2, _cairo_xlib_surface_add_glyph (dpy=0x8099520,
>>    scaled_font=0x8118c38, scaled_glyph=0x81188a8) at
>>cairo-xlib-surface.c:2195
>>2195        XSync(dpy, 0);
>>6: glyph_info = {width = 5, height = 9, x = -1, y = 9, xOff = 0, yOff = 0}
>>5: *scaled_glyph->surface = {base = {backend = 0xb7f52060, ref_count = 1,
>>    status = CAIRO_STATUS_SUCCESS, finished = 0, user_data = {size = 0,
>>      num_elements = 0, element_size = 12, elements = 0x0},
>>    device_x_offset = 1, device_y_offset = -9, device_x_scale = 1,
>>    device_y_scale = 1, next_clip_serial = 0, current_clip_serial = 0},
>>  format = CAIRO_FORMAT_A8, data = 0x814c598 "hå?´è±?", owns_data = 1,
>>  has_clip = 0, width = 5, height = 9, stride = 8, depth = 8,
>>  pixman_image = 0x814c610}
>>(gdb)
>>Continuing.
>>fcitx: BadLength (poly request too large or internal Xlib length error)
>>X Error of failed request:  BadLength (poly request too large or
>>internal Xlib length error)
>>  Major opcode of failed request:  150 (RENDER)
>>  Minor opcode of failed request:  20 (RenderAddGlyphs)
>>  Serial number of failed request:  721
>>  Current serial number in output stream:  722
>>
>>
>>------------------------------------------------------------------------
>>
>>_______________________________________________
>>cairo mailing list
>>cairo at cairographics.org
>>http://cairographics.org/cgi-bin/mailman/listinfo/cairo
-------------- next part --------------
Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.121
diff -u -p -r1.121 cairo-xlib-surface.c
--- cairo-xlib-surface.c	20 Sep 2005 00:24:52 -0000	1.121
+++ cairo-xlib-surface.c	28 Sep 2005 08:31:22 -0000
@@ -2005,38 +2005,83 @@ cairo_xlib_surface_set_drawable (cairo_s
     surface->height = height;
 }
 
-typedef struct _cairo_xlib_surface_font_private {
-    Display		*dpy;
+#define GLYPH_INFO_MAX (3)
+typedef struct _cairo_xlib_font_glyph_info {
     GlyphSet		glyphset;
     XRenderPictFormat	*format;
+} cairo_xlib_font_glyph_info_t;
+
+typedef struct _cairo_xlib_surface_font_private {
+    Display		         *dpy;
+    cairo_xlib_font_glyph_info_t glyph_info[GLYPH_INFO_MAX];
 } cairo_xlib_surface_font_private_t;
 
 static cairo_status_t
 _cairo_xlib_surface_font_init (Display		    *dpy,
-			       cairo_scaled_font_t  *scaled_font,
-			       cairo_format_t	     format)
+			       cairo_scaled_font_t  *scaled_font)
 {
     cairo_xlib_surface_font_private_t	*font_private;
-
+    int i;
     font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
     if (!font_private)
 	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);
+    for (i = 0; i < GLYPH_INFO_MAX; i ++) {
+	font_private->glyph_info[i].format = NULL;
+	font_private->glyph_info[i].glyphset = None;
+    }
+
     scaled_font->surface_private = font_private;
     scaled_font->surface_backend = &cairo_xlib_surface_backend;
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_xlib_font_glyph_info_t *
+_cairo_xlib_surface_font_get_glyph_info (cairo_scaled_font_t *scaled_font,
+					 cairo_format_t	     format)
+{
+    cairo_xlib_surface_font_private_t	*font_private = scaled_font->surface_private;
+    cairo_xlib_font_glyph_info_t        *glyph_info = &font_private->glyph_info[0];
+    int i;
+    
+    switch (format) {
+    case CAIRO_FORMAT_A1:
+	i = 0;
+	break;
+    case CAIRO_FORMAT_A8:
+	i = 1;
+	break;
+    case CAIRO_FORMAT_ARGB32:
+	i = 2;
+	break;
+    case CAIRO_FORMAT_RGB24:
+    default:
+	ASSERT_NOT_REACHED;
+    }
+    
+    if (glyph_info[i].glyphset == None) {
+	glyph_info[i].format = _CAIRO_FORMAT_XRENDER_FORMAT(font_private->dpy,
+							    format);
+	glyph_info[i].glyphset = XRenderCreateGlyphSet (font_private->dpy, 
+							glyph_info[i].format);
+    }
+
+    return glyph_info + i;
+}
+
 static void
 _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
 {
     cairo_xlib_surface_font_private_t	*font_private = scaled_font->surface_private;
+    int i;
 
     if (font_private) {
-	XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
+	for (i = 0; i < GLYPH_INFO_MAX; i ++) {
+	    if (font_private->glyph_info[i].glyphset)
+		XRenderFreeGlyphSet (font_private->dpy,
+				     font_private->glyph_info[i].glyphset);
+	}
 	free (font_private);
     }
 }
@@ -2049,8 +2094,10 @@ _cairo_xlib_surface_scaled_glyph_fini (c
 
     if (font_private != NULL && scaled_glyph->surface_private != NULL) {
 	unsigned long	glyph_index = _cairo_scaled_glyph_index(scaled_glyph);
+	cairo_xlib_font_glyph_info_t *glyph_info = scaled_glyph->surface_private;
+
 	XRenderFreeGlyphs (font_private->dpy,
-			   font_private->glyphset,
+			   glyph_info->glyphset,
 			   &glyph_index, 1);
     }
 }
@@ -2073,16 +2120,23 @@ _cairo_xlib_surface_add_glyph (Display *
     unsigned char *data;
     cairo_status_t status;
     cairo_xlib_surface_font_private_t *font_private;
+    cairo_xlib_font_glyph_info_t * cairo_glyph_info;
     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
 
     if (scaled_font->surface_private == NULL) {
-	status = _cairo_xlib_surface_font_init (dpy, scaled_font, 
-						glyph_surface->format);
+	status = _cairo_xlib_surface_font_init (dpy, scaled_font);
 	if (status)
 	    return status;
     }
     font_private = scaled_font->surface_private;
 
+    cairo_glyph_info = _cairo_xlib_surface_font_get_glyph_info (scaled_font,
+								glyph_surface->format);
+    if (cairo_glyph_info->glyphset == None)
+	return CAIRO_STATUS_NO_MEMORY;
+    
+    scaled_glyph->surface_private = cairo_glyph_info;
+
     /*
      *  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
@@ -2187,7 +2241,7 @@ _cairo_xlib_surface_add_glyph (Display *
 
     glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
     
-    XRenderAddGlyphs (dpy, font_private->glyphset,
+    XRenderAddGlyphs (dpy, cairo_glyph_info->glyphset,
 		      &glyph_index, &(glyph_info), 1,
 		      (char *) data,
 		      glyph_surface->stride * glyph_surface->height);
@@ -2201,16 +2255,18 @@ _cairo_xlib_surface_add_glyph (Display *
 #define N_STACK_BUF 1024
 
 static cairo_status_t
-_cairo_xlib_surface_show_glyphs8  (cairo_scaled_font_t    *scaled_font,
-				   cairo_operator_t       operator,
-				   cairo_xlib_surface_t   *src,
-				   cairo_xlib_surface_t   *self,
-				   int                    source_x,
-				   int                    source_y,
-				   const cairo_glyph_t    *glyphs,
-				   int                    num_glyphs)
+_cairo_xlib_surface_show_glyphs8  (cairo_scaled_font_t          *scaled_font,
+				   cairo_operator_t             operator,
+				   cairo_xlib_surface_t         *src,
+				   cairo_xlib_surface_t         *self,
+				   int                          source_x,
+				   int                          source_y,
+				   const cairo_glyph_t          *glyphs,
+				   int                          num_glyphs,
+				   cairo_xlib_font_glyph_info_t *glyph_info,
+				   int                          *x_advance,
+				   int                          *y_advance)
 {
-    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
     XGlyphElt8 *elts = NULL;
     XGlyphElt8 stack_elts [N_STACK_BUF];
 
@@ -2238,7 +2294,7 @@ _cairo_xlib_surface_show_glyphs8  (cairo
 	chars[i] = glyphs[i].index;
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
-	elts[i].glyphset = font_private->glyphset;
+	elts[i].glyphset = glyph_info->glyphset;
 	thisX = (int) floor (glyphs[i].x + 0.5);
 	thisY = (int) floor (glyphs[i].y + 0.5);
 	elts[i].xOff = thisX - lastX;
@@ -2251,7 +2307,7 @@ _cairo_xlib_surface_show_glyphs8  (cairo
 			    _render_operator (operator),
 			    src->src_picture,
 			    self->dst_picture,
-			    font_private->format,
+			    glyph_info->format,
 			    source_x + elts[0].xOff, source_y + elts[0].yOff,
 			    0, 0,
 			    elts, num_glyphs);
@@ -2259,20 +2315,25 @@ _cairo_xlib_surface_show_glyphs8  (cairo
     if (elts != stack_elts)
 	free (elts);
 
+    *x_advance = elts[num_glyphs - 1].xOff;
+    *y_advance = elts[num_glyphs - 1].yOff;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t    *scaled_font,
-				   cairo_operator_t       operator,
-				   cairo_xlib_surface_t   *src,
-				   cairo_xlib_surface_t   *self,
-				   int                    source_x,
-				   int                    source_y,
-				   const cairo_glyph_t    *glyphs,
-				   int                    num_glyphs)
+_cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t         *scaled_font,
+				   cairo_operator_t             operator,
+				   cairo_xlib_surface_t         *src,
+				   cairo_xlib_surface_t         *self,
+				   int                          source_x,
+				   int                          source_y,
+				   const cairo_glyph_t          *glyphs,
+				   int                          num_glyphs,
+				   cairo_xlib_font_glyph_info_t *glyph_info,
+				   int                          *x_advance,
+				   int                          *y_advance)
 {
-    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
     XGlyphElt16 *elts = NULL;
     XGlyphElt16 stack_elts [N_STACK_BUF];
 
@@ -2300,7 +2361,7 @@ _cairo_xlib_surface_show_glyphs16 (cairo
 	chars[i] = glyphs[i].index;
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
-	elts[i].glyphset = font_private->glyphset;
+	elts[i].glyphset = glyph_info->glyphset;
 	thisX = (int) floor (glyphs[i].x + 0.5);
 	thisY = (int) floor (glyphs[i].y + 0.5);
 	elts[i].xOff = thisX - lastX;
@@ -2313,7 +2374,7 @@ _cairo_xlib_surface_show_glyphs16 (cairo
 			    _render_operator (operator),
 			    src->src_picture,
 			    self->dst_picture,
-			    font_private->format,
+			    glyph_info->format,
 			    source_x + elts[0].xOff, source_y + elts[0].yOff,
 			    0, 0,
 			    elts, num_glyphs);
@@ -2321,20 +2382,25 @@ _cairo_xlib_surface_show_glyphs16 (cairo
     if (elts != stack_elts)
 	free (elts);
 
+    *x_advance = elts[num_glyphs - 1].xOff;
+    *y_advance = elts[num_glyphs - 1].yOff;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t    *scaled_font,
-				   cairo_operator_t       operator,
-				   cairo_xlib_surface_t   *src,
-				   cairo_xlib_surface_t   *self,
-				   int                    source_x,
-				   int                    source_y,
-				   const cairo_glyph_t    *glyphs,
-				   int                    num_glyphs)
+_cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t          *scaled_font,
+				   cairo_operator_t             operator,
+				   cairo_xlib_surface_t         *src,
+				   cairo_xlib_surface_t         *self,
+				   int                          source_x,
+				   int                          source_y,
+				   const cairo_glyph_t          *glyphs,
+				   int                          num_glyphs,
+				   cairo_xlib_font_glyph_info_t *glyph_info,
+				   int                          *x_advance,
+				   int                          *y_advance)
 {
-    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
     XGlyphElt32 *elts = NULL;
     XGlyphElt32 stack_elts [N_STACK_BUF];
 
@@ -2362,7 +2428,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo
 	chars[i] = glyphs[i].index;
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
-	elts[i].glyphset = font_private->glyphset;
+	elts[i].glyphset = glyph_info->glyphset;
 	thisX = (int) floor (glyphs[i].x + 0.5);
 	thisY = (int) floor (glyphs[i].y + 0.5);
 	elts[i].xOff = thisX - lastX;
@@ -2375,7 +2441,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo
 			    _render_operator (operator),
 			    src->src_picture,
 			    self->dst_picture,
-			    font_private->format,
+			    glyph_info->format,
 			    source_x + elts[0].xOff, source_y + elts[0].yOff,
 			    0, 0,
 			    elts, num_glyphs);
@@ -2383,6 +2449,9 @@ _cairo_xlib_surface_show_glyphs32 (cairo
     if (elts != stack_elts)
 	free (elts);
 
+    *x_advance = elts[num_glyphs - 1].xOff;
+    *y_advance = elts[num_glyphs - 1].yOff;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -2406,9 +2475,13 @@ _cairo_xlib_surface_show_glyphs (cairo_s
     cairo_xlib_surface_t *src;
     composite_operation_t operation;
     cairo_scaled_glyph_t *scaled_glyph;
+    cairo_xlib_font_glyph_info_t *glyphs_info;
     cairo_xlib_surface_font_private_t *font_private;
-    int i;
     unsigned long max_index = 0;
+    int x_offset, y_offset;
+    int x_advance, y_advance;
+    int i, done;
+
     
 
     if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->format)
@@ -2424,23 +2497,27 @@ _cairo_xlib_surface_show_glyphs (cairo_s
 	(font_private != NULL && font_private->dpy != self->dpy))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
+    glyphs_info = malloc (sizeof (cairo_xlib_font_glyph_info_t) * num_glyphs);
+    if (glyphs_info == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
+
     status = _cairo_pattern_acquire_surface (pattern, &self->base,
 					     source_x, source_y, width, height,
 					     (cairo_surface_t **) &src,
 					     &attributes);
     if (status)
-	return status;
+	goto FAIL;
 
     operation = _recategorize_composite_operation (self, operator, src, &attributes, TRUE);
     if (operation == DO_UNSUPPORTED) {
 	status = CAIRO_INT_STATUS_UNSUPPORTED;
-	goto FAIL;
+	goto FAIL1;
     }
 	
     status = _cairo_xlib_surface_set_attributes (src, &attributes);
     if (status)
-	goto FAIL;
-    
+	goto FAIL1;
+
     /* Send all unsent glyphs to the server */
     for (i = 0; i < num_glyphs; i++) {
 	if (glyphs[i].index > max_index)
@@ -2453,28 +2530,49 @@ _cairo_xlib_surface_show_glyphs (cairo_s
 	    return status;
 	if (scaled_glyph->surface_private == NULL) {
 	    _cairo_xlib_surface_add_glyph (self->dpy, scaled_font, scaled_glyph);
-	    scaled_glyph->surface_private = (void *) 1;
 	}
+	glyphs_info[i] = *(cairo_xlib_font_glyph_info_t *)scaled_glyph->surface_private;
     }
     
     _cairo_xlib_surface_ensure_dst_picture (self);
     /* Call the appropriate sub-function. */
+    status = CAIRO_STATUS_SUCCESS;
+    x_offset = source_x + attributes.x_offset - dest_x;
+    y_offset = source_y + attributes.y_offset - dest_y; 
+    done = 0;
+
+    while (done < num_glyphs && !status) {
+	for (i = done + 1; i < num_glyphs; i ++) {
+	    if (glyphs_info[i - 1].glyphset != glyphs_info[i].glyphset)
+		break;
+	}
+
+	if (max_index < 256)
+	    status = _cairo_xlib_surface_show_glyphs8 (scaled_font, operator, 
+						       src, self,
+						       x_offset, y_offset, 
+						       glyphs, i - done,
+						       &glyphs_info[done],
+						       &x_advance, &y_advance);
+	else if (max_index < 65536)
+	    status = _cairo_xlib_surface_show_glyphs16 (scaled_font, operator,
+							src, self,
+							x_offset, y_offset, 
+							glyphs, i - done,
+							&glyphs_info[done],
+							&x_advance, &y_advance);
+	else 
+	    status = _cairo_xlib_surface_show_glyphs32 (scaled_font, operator,
+							src, self,
+							x_offset, y_offset,
+							glyphs, i - done,
+							&glyphs_info[done],
+							&x_advance, &y_advance);
+	x_offset += x_advance;
+	y_offset += y_advance;
 
-    if (max_index < 256)
-	status = _cairo_xlib_surface_show_glyphs8 (scaled_font, operator, src, self,
-						   source_x + attributes.x_offset - dest_x,
-						   source_y + attributes.y_offset - dest_y, 
-						   glyphs, num_glyphs);
-    else if (max_index < 65536)
-	status = _cairo_xlib_surface_show_glyphs16 (scaled_font, operator, src, self,
-						    source_x + attributes.x_offset - dest_x,
-						    source_y + attributes.y_offset - dest_y, 
-						    glyphs, num_glyphs);
-    else 
-	status = _cairo_xlib_surface_show_glyphs32 (scaled_font, operator, src, self,
-						    source_x + attributes.x_offset - dest_x,
-						    source_y + attributes.y_offset - dest_y, 
-						    glyphs, num_glyphs);
+	done = i;
+    }
 
     if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded (operator)) {
 	cairo_rectangle_t   extents;
@@ -2491,8 +2589,9 @@ _cairo_xlib_surface_show_glyphs (cairo_s
 			 dest_x, dest_y,
 			 width, height);
     }
- FAIL:
+ FAIL1:
     _cairo_pattern_release_surface (pattern, &src->base, &attributes);
-    
+ FAIL:
+    free (glyphs_info);
     return status;
 }


More information about the cairo mailing list