diff options
Diffstat (limited to 'src/cairo-xlib-surface.c')
-rw-r--r-- | src/cairo-xlib-surface.c | 433 |
1 files changed, 367 insertions, 66 deletions
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 41fb00c44..f06d409e2 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -46,7 +46,17 @@ typedef int (*cairo_xlib_error_func_t) (Display *display, typedef struct _cairo_xlib_surface cairo_xlib_surface_t; -static void _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface); +static void +_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface); + +static void +_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface); + +static void +_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface); + +static cairo_bool_t +_cairo_surface_is_xlib (cairo_surface_t *surface); /* * Instead of taking two round trips for each blending request, @@ -70,11 +80,25 @@ struct _cairo_xlib_surface { int render_major; int render_minor; + /* TRUE if the server has a bug with repeating pictures + * + * https://bugs.freedesktop.org/show_bug.cgi?id=3566 + * + * We can't test for this because it depends on whether the + * picture is in video memory or not. + */ + cairo_bool_t buggy_repeat; + int width; int height; int depth; - Picture picture; + Picture dst_picture, src_picture; + + cairo_bool_t have_clip_rects; + XRectangle *clip_rects; + int num_clip_rects; + XRenderPictFormat *format; }; @@ -157,7 +181,6 @@ _CAIRO_FORMAT_XRENDER_FORMAT(Display *dpy, cairo_format_t format) static cairo_surface_t * _cairo_xlib_surface_create_similar (void *abstract_src, cairo_format_t format, - int drawable, int width, int height) { @@ -197,8 +220,11 @@ static cairo_status_t _cairo_xlib_surface_finish (void *abstract_surface) { cairo_xlib_surface_t *surface = abstract_surface; - if (surface->picture) - XRenderFreePicture (surface->dpy, surface->picture); + if (surface->dst_picture) + XRenderFreePicture (surface->dpy, surface->dst_picture); + + if (surface->src_picture) + XRenderFreePicture (surface->dpy, surface->src_picture); if (surface->owns_pixmap) XFreePixmap (surface->dpy, surface->drawable); @@ -206,6 +232,9 @@ _cairo_xlib_surface_finish (void *abstract_surface) if (surface->gc) XFreeGC (surface->dpy, surface->gc); + if (surface->clip_rects) + free (surface->clip_rects); + surface->dpy = NULL; return CAIRO_STATUS_SUCCESS; @@ -281,7 +310,7 @@ _get_image_surface (cairo_xlib_surface_t *surface, rect.x = interest_rect->x; rect.y = interest_rect->y; rect.width = interest_rect->width; - rect.height = interest_rect->width; + rect.height = interest_rect->height; if (rect.x > x1) x1 = rect.x; @@ -425,14 +454,54 @@ _get_image_surface (cairo_xlib_surface_t *surface, ximage->data = NULL; XDestroyImage (ximage); - _cairo_image_surface_set_repeat (image, surface->base.repeat); - _cairo_image_surface_set_matrix (image, &(surface->base.matrix)); - *image_out = image; return CAIRO_STATUS_SUCCESS; } static void +_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface) +{ + if (!surface->src_picture) + surface->src_picture = XRenderCreatePicture (surface->dpy, + surface->drawable, + surface->format, + 0, NULL); +} + +static void +_cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface) +{ + if (surface->have_clip_rects) + XRenderSetPictureClipRectangles (surface->dpy, surface->dst_picture, + 0, 0, + surface->clip_rects, + surface->num_clip_rects); +} + +static void +_cairo_xlib_surface_set_gc_clip_rects (cairo_xlib_surface_t *surface) +{ + if (surface->have_clip_rects) + XSetClipRectangles(surface->dpy, surface->gc, + 0, 0, + surface->clip_rects, + surface->num_clip_rects, YXSorted); +} + +static void +_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface) +{ + if (!surface->dst_picture) { + surface->dst_picture = XRenderCreatePicture (surface->dpy, + surface->drawable, + surface->format, + 0, NULL); + _cairo_xlib_surface_set_picture_clip_rects (surface); + } + +} + +static void _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface) { XGCValues gcv; @@ -443,6 +512,7 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface) gcv.graphics_exposures = False; surface->gc = XCreateGC (surface->dpy, surface->drawable, GCGraphicsExposures, &gcv); + _cairo_xlib_surface_set_gc_clip_rects (surface); } static cairo_status_t @@ -499,10 +569,12 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf cairo_status_t status; status = _get_image_surface (surface, NULL, &image, NULL); - if (status == CAIRO_STATUS_SUCCESS) - *image_out = image; + if (status) + return status; - return status; + *image_out = image; + + return CAIRO_STATUS_SUCCESS; } static void @@ -525,10 +597,12 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac cairo_status_t status; status = _get_image_surface (surface, interest_rect, &image, image_rect_out); - if (status == CAIRO_STATUS_SUCCESS) - *image_out = image; + if (status) + return status; - return status; + *image_out = image; + + return CAIRO_STATUS_SUCCESS; } static void @@ -567,7 +641,7 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface, cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; clone = (cairo_xlib_surface_t *) - _cairo_xlib_surface_create_similar (surface, image_src->format, 0, + _cairo_xlib_surface_create_similar (surface, image_src->format, image_src->width, image_src->height); if (clone == NULL) return CAIRO_STATUS_NO_MEMORY; @@ -588,7 +662,7 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface, { XTransform xtransform; - if (!surface->picture) + if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; xtransform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx); @@ -617,7 +691,7 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; } - XRenderSetPictureTransform (surface->dpy, surface->picture, &xtransform); + XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform); return CAIRO_STATUS_SUCCESS; } @@ -628,7 +702,7 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, { char *render_filter; - if (!surface->picture) + if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface)) @@ -660,7 +734,7 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, break; } - XRenderSetPictureFilter (surface->dpy, surface->picture, + XRenderSetPictureFilter (surface->dpy, surface->src_picture, render_filter, NULL, 0); return CAIRO_STATUS_SUCCESS; @@ -672,13 +746,13 @@ _cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, int repeat) XRenderPictureAttributes pa; unsigned long mask; - if (!surface->picture) + if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; mask = CPRepeat; pa.repeat = repeat; - XRenderChangePicture (surface->dpy, surface->picture, mask, &pa); + XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa); return CAIRO_STATUS_SUCCESS; } @@ -689,6 +763,8 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, { cairo_int_status_t status; + _cairo_xlib_surface_ensure_src_picture (surface); + status = _cairo_xlib_surface_set_matrix (surface, &attributes->matrix); if (status) return status; @@ -711,6 +787,139 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, return CAIRO_STATUS_SUCCESS; } +/* Checks whether we can can directly draw from src to dst with + * the core protocol: either with CopyArea or using src as a + * a tile in a GC. + */ +static cairo_bool_t +_surfaces_compatible (cairo_xlib_surface_t *src, + cairo_xlib_surface_t *dst) +{ + + if (src->dpy != dst->dpy) + return FALSE; + + /* We must not only match depth and format/visual, we must also + * match screen. We don't have that information, and rather than + * asking for it round-trip, we'll just return FALSE if we have + * more than one screen on the display. + */ + if (ScreenCount (dst->dpy) > 1) + return FALSE; + + return (src->depth == dst->depth && + ((src->format != NULL && src->format == dst->format) || + (src->visual != NULL && src->visual == dst->visual))); +} + +static cairo_bool_t +_surface_has_alpha (cairo_xlib_surface_t *surface) +{ + if (surface->format) { + if (surface->format->type == PictTypeDirect && + surface->format->direct.alphaMask != 0) + return TRUE; + else + return FALSE; + } else { + + /* In the no-render case, we never have alpha */ + return FALSE; + } +} + +/* There is a bug in most older X servers with compositing using a repeating + * source pattern when the source is in off-screen video memory. When that + * bug could be triggered, we need a fallback: in the common case where we have no + * transformation and the source and destination have the same format/visual, + * we can do the operation using the core protocol, otherwise, we need + * a software fallback. + */ +typedef enum { + DO_RENDER, /* use render */ + DO_XLIB, /* core protocol fallback */ + DO_UNSUPPORTED /* software fallback */ +} composite_operation_t; + +/* Initial check for the bug; we need to recheck after we turn + * patterns into surfaces, since that may introduce a repeating + * pattern for gradient patterns. + * + * All we do here is reject cases where we *know* are going to + * hit the bug and won't be able to use a core protocol fallback. + */ +static composite_operation_t +_categorize_composite_repeat (cairo_xlib_surface_t *dst, + cairo_operator_t operator, + cairo_pattern_t *src_pattern, + cairo_bool_t have_mask) + +{ + if (!dst->buggy_repeat) + return DO_RENDER; + + if (src_pattern->type == CAIRO_PATTERN_SURFACE) + { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern; + + if (_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) && + src_pattern->extend == CAIRO_EXTEND_REPEAT) + { + /* This is the case where we have a bug; reject some cases where a + * core protocol fallback is impossible. + */ + if (have_mask || + !(operator == CAIRO_OPERATOR_SOURCE || operator == CAIRO_OPERATOR_OVER)) + return DO_UNSUPPORTED; + + if (_cairo_surface_is_xlib (surface_pattern->surface)) { + cairo_xlib_surface_t *src = (cairo_xlib_surface_t *)surface_pattern->surface; + + if (operator == CAIRO_OPERATOR_OVER && _surface_has_alpha (src)) + return DO_UNSUPPORTED; + + if (src->dpy == dst->dpy && !_surfaces_compatible (src, dst)) + return DO_UNSUPPORTED; + } + } + } + + return DO_RENDER; +} + +/* Recheck for composite-repeat once we've turned patterns into Xlib surfaces + * If we end up returning DO_UNSUPPORTED here, we're throwing away work we + * did to turn gradients into a pattern, but most of the time we can handle + * that case with core protocol fallback. + */ +static composite_operation_t +_recategorize_composite_repeat (cairo_xlib_surface_t *dst, + cairo_operator_t operator, + cairo_xlib_surface_t *src, + cairo_surface_attributes_t *src_attr, + cairo_bool_t have_mask) +{ + if (!dst->buggy_repeat) + return DO_RENDER; + + if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) && + src_attr->extend == CAIRO_EXTEND_REPEAT && + (src->width != 1 || src->height != 1)) + { + if (!have_mask && + (operator == CAIRO_OPERATOR_SOURCE || + (operator == CAIRO_OPERATOR_OVER && !_surface_has_alpha (src)))) + { + if (_surfaces_compatible (dst, src)) + return DO_XLIB; + } + + return DO_UNSUPPORTED; + } + + return DO_RENDER; +} + static int _render_operator (cairo_operator_t operator) { @@ -770,10 +979,16 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, cairo_xlib_surface_t *src; cairo_xlib_surface_t *mask; cairo_int_status_t status; + composite_operation_t operation; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; + operation = _categorize_composite_repeat (dst, operator, src_pattern, + mask_pattern != NULL); + if (operation == DO_UNSUPPORTED) + return CAIRO_INT_STATUS_UNSUPPORTED; + status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, &dst->base, src_x, src_y, @@ -785,16 +1000,28 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, if (status) return status; + operation = _recategorize_composite_repeat (dst, operator, src, &src_attr, + mask_pattern != NULL); + if (operation == DO_UNSUPPORTED) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto FAIL; + } + status = _cairo_xlib_surface_set_attributes (src, &src_attr); - if (CAIRO_OK (status)) { + if (status) + goto FAIL; + + if (operation == DO_RENDER) + { + _cairo_xlib_surface_ensure_dst_picture (dst); if (mask) { status = _cairo_xlib_surface_set_attributes (mask, &mask_attr); - if (CAIRO_OK (status)) + if (status == CAIRO_STATUS_SUCCESS) XRenderComposite (dst->dpy, _render_operator (operator), - src->picture, - mask->picture, - dst->picture, + src->src_picture, + mask->src_picture, + dst->dst_picture, src_x + src_attr.x_offset, src_y + src_attr.y_offset, mask_x + mask_attr.x_offset, @@ -804,9 +1031,9 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, } else { XRenderComposite (dst->dpy, _render_operator (operator), - src->picture, + src->src_picture, 0, - dst->picture, + dst->dst_picture, src_x + src_attr.x_offset, src_y + src_attr.y_offset, 0, 0, @@ -814,6 +1041,30 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, width, height); } } + else /* DO_XLIB */ + { + /* This case is only used for bug fallbacks, though it is theoretically + * applicable to the case where we don't have the RENDER extension as + * well. + * + * We've checked that we have a repeating unscaled source in + * _recategorize_composite_repeat. + */ + int itx, ity; + + _cairo_xlib_surface_ensure_gc (dst); + _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity); + + XSetTSOrigin (dst->dpy, dst->gc, + - (itx + src_attr.x_offset), - (ity + src_attr.y_offset)); + XSetTile (dst->dpy, dst->gc, src->drawable); + XSetFillStyle (dst->dpy, dst->gc, FillTiled); + + XFillRectangle (dst->dpy, dst->drawable, dst->gc, + dst_x, dst_y, width, height); + } + + FAIL: if (mask) _cairo_pattern_release_surface (&dst->base, &mask->base, &mask_attr); @@ -842,9 +1093,10 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, render_color.alpha = color->alpha_short; /* XXX: This XRectangle cast is evil... it needs to go away somehow. */ + _cairo_xlib_surface_ensure_dst_picture (surface); XRenderFillRectangles (surface->dpy, _render_operator (operator), - surface->picture, + surface->dst_picture, &render_color, (XRectangle *) rects, num_rects); return CAIRO_STATUS_SUCCESS; @@ -867,11 +1119,16 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, cairo_xlib_surface_t *dst = abstract_dst; cairo_xlib_surface_t *src; cairo_int_status_t status; + composite_operation_t operation; int render_reference_x, render_reference_y; int render_src_x, render_src_y; if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; + + operation = _categorize_composite_repeat (dst, operator, pattern, TRUE); + if (operation == DO_UNSUPPORTED) + return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_pattern_acquire_surface (pattern, &dst->base, src_x, src_y, width, height, @@ -879,7 +1136,13 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, &attributes); if (status) return status; - + + operation = _recategorize_composite_repeat (dst, operator, src, &attributes, TRUE); + if (operation == DO_UNSUPPORTED) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto FAIL; + } + if (traps[0].left.p1.y < traps[0].left.p2.y) { render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x); render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y); @@ -892,16 +1155,18 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, render_src_y = src_y + render_reference_y - dst_y; /* XXX: The XTrapezoid cast is evil and needs to go away somehow. */ + _cairo_xlib_surface_ensure_dst_picture (dst); status = _cairo_xlib_surface_set_attributes (src, &attributes); - if (CAIRO_OK (status)) + if (status == CAIRO_STATUS_SUCCESS) XRenderCompositeTrapezoids (dst->dpy, _render_operator (operator), - src->picture, dst->picture, + src->src_picture, dst->dst_picture, XRenderFindStandardFormat (dst->dpy, PictStandardA8), render_src_x + attributes.x_offset, render_src_y + attributes.y_offset, (XTrapezoid *) traps, num_traps); + FAIL: _cairo_pattern_release_surface (&dst->base, &src->base, &attributes); return status; @@ -913,14 +1178,22 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface, { cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; + if (surface->clip_rects) { + free (surface->clip_rects); + surface->clip_rects = NULL; + } + + surface->have_clip_rects = FALSE; + surface->num_clip_rects = 0; + if (region == NULL) { if (surface->gc) XSetClipMask (surface->dpy, surface->gc, None); - if (surface->picture) { + if (surface->format && surface->dst_picture) { XRenderPictureAttributes pa; pa.clip_mask = None; - XRenderChangePicture (surface->dpy, surface->picture, + XRenderChangePicture (surface->dpy, surface->dst_picture, CPClipMask, &pa); } } else { @@ -946,15 +1219,15 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface, rects[i].height = boxes[i].y2 - boxes[i].y1; } + surface->have_clip_rects = TRUE; + surface->clip_rects = rects; + surface->num_clip_rects = n_boxes; + if (surface->gc) - XSetClipRectangles(surface->dpy, surface->gc, - 0, 0, rects, n_boxes, YXSorted); - if (surface->picture) - XRenderSetPictureClipRectangles (surface->dpy, surface->picture, - 0, 0, rects, n_boxes); - - if (rects) - free (rects); + _cairo_xlib_surface_set_gc_clip_rects (surface); + + if (surface->dst_picture) + _cairo_xlib_surface_set_picture_clip_rects (surface); } return CAIRO_STATUS_SUCCESS; @@ -1003,6 +1276,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = { NULL, /* copy_page */ NULL, /* show_page */ _cairo_xlib_surface_set_clip_region, + NULL, /* intersect_clip_path */ _cairo_xlib_surface_get_extents, _cairo_xlib_surface_show_glyphs }; @@ -1043,15 +1317,12 @@ _cairo_xlib_surface_create_internal (Display *dpy, surface->gc = NULL; surface->drawable = drawable; surface->owns_pixmap = FALSE; - surface->visual = visual; - surface->format = format; surface->use_pixmap = 0; surface->width = width; surface->height = height; - surface->depth = depth; if (format) { - surface->depth = format->depth; + depth = format->depth; } else if (visual) { int i, j, k; @@ -1061,10 +1332,10 @@ _cairo_xlib_surface_create_internal (Display *dpy, for (i = 0; i < ScreenCount (dpy); i++) { Screen *screen = ScreenOfDisplay (dpy, i); for (j = 0; j < screen->ndepths; j++) { - Depth *depth = &screen->depths[j]; - for (k = 0; k < depth->nvisuals; k++) { - if (&depth->visuals[k] == visual) { - surface->depth = depth->depth; + Depth *d = &screen->depths[j]; + for (k = 0; k < d->nvisuals; k++) { + if (&d->visuals[k] == visual) { + depth = d->depth; goto found; } } @@ -1080,22 +1351,34 @@ _cairo_xlib_surface_create_internal (Display *dpy, surface->render_minor = -1; } - surface->picture = None; + surface->buggy_repeat = FALSE; + if (strcmp (ServerVendor (dpy), "The X.Org Foundation") == 0) { + if (VendorRelease (dpy) <= 60802000) + surface->buggy_repeat = TRUE; + } + + surface->dst_picture = None; + surface->src_picture = None; if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) { - if (!format) { - if (visual) { + if (visual) format = XRenderFindVisualFormat (dpy, visual); - } else if (depth == 1) + else if (depth == 1) format = XRenderFindStandardFormat (dpy, PictStandardA1); } - - if (format) - surface->picture = XRenderCreatePicture (dpy, drawable, - format, 0, NULL); + } else { + format = NULL; } + surface->visual = visual; + surface->format = format; + surface->depth = depth; + + surface->have_clip_rects = FALSE; + surface->clip_rects = NULL; + surface->num_clip_rects = 0; + return (cairo_surface_t *) surface; } @@ -1479,8 +1762,8 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font, XRenderCompositeText32 (self->dpy, _render_operator (operator), - src->picture, - self->picture, + src->src_picture, + self->dst_picture, g->a8_pict_format, source_x, source_y, 0, 0, @@ -1556,8 +1839,8 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font, XRenderCompositeText16 (self->dpy, _render_operator (operator), - src->picture, - self->picture, + src->src_picture, + self->dst_picture, g->a8_pict_format, source_x, source_y, 0, 0, @@ -1632,8 +1915,8 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font, XRenderCompositeText8 (self->dpy, _render_operator (operator), - src->picture, - self->picture, + src->src_picture, + self->dst_picture, g->a8_pict_format, source_x, source_y, 0, 0, @@ -1678,11 +1961,16 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_glyph_cache_key_t key; glyphset_cache_entry_t **entries; glyphset_cache_entry_t *stack_entries [N_STACK_BUF]; + composite_operation_t operation; int i; - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self)) + if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->format) return CAIRO_INT_STATUS_UNSUPPORTED; + operation = _categorize_composite_repeat (self, operator, pattern, TRUE); + if (operation == DO_UNSUPPORTED) + return CAIRO_INT_STATUS_UNSUPPORTED; + status = _cairo_pattern_acquire_surface (pattern, &self->base, source_x, source_y, width, height, (cairo_surface_t **) &src, @@ -1690,6 +1978,12 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, if (status) return status; + operation = _recategorize_composite_repeat (self, operator, src, &attributes, TRUE); + if (operation == DO_UNSUPPORTED) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto FAIL; + } + status = _cairo_xlib_surface_set_attributes (src, &attributes); if (status) goto FAIL; @@ -1738,21 +2032,28 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, /* Call the appropriate sub-function. */ + _cairo_xlib_surface_ensure_dst_picture (self); if (elt_size == 8) + { status = _cairo_xlib_surface_show_glyphs8 (scaled_font, operator, g, &key, src, self, source_x + attributes.x_offset, source_y + attributes.y_offset, glyphs, entries, num_glyphs); + } else if (elt_size == 16) + { status = _cairo_xlib_surface_show_glyphs16 (scaled_font, operator, g, &key, src, self, source_x + attributes.x_offset, source_y + attributes.y_offset, glyphs, entries, num_glyphs); + } else + { status = _cairo_xlib_surface_show_glyphs32 (scaled_font, operator, g, &key, src, self, source_x + attributes.x_offset, source_y + attributes.y_offset, glyphs, entries, num_glyphs); + } for (i = 0; i < num_glyphs; ++i) _xlib_glyphset_cache_destroy_entry (g, entries[i]); |