summaryrefslogtreecommitdiff
path: root/src/cairo-xlib-surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-xlib-surface.c')
-rw-r--r--src/cairo-xlib-surface.c433
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]);