[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