[cairo] Re: crash at XRenderAddGlyphs.
sunmoon1997
sunmoon1997 at gmail.com
Wed Sep 28 05:21:21 PDT 2005
sunmoon1997 wrote:
>>>+ x_offset += x_advance;
>>>+ y_offset += y_advance;
>>>
glyphs += i; is missed here.
new patch attached, works now:D
-------------- 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 12:15:33 -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[3];
} 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,
- 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);
+ 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;
+ glyphs += i;
+ done = i;
+ }
if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded (operator)) {
cairo_rectangle_t extents;
@@ -2491,8 +2589,10 @@ _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