summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUli Schlachter <psychon@znc.in>2011-12-11 13:58:10 +0100
committerUli Schlachter <psychon@znc.in>2011-12-11 14:04:16 +0100
commit8025fcc4d38db1e2f7adabe732dbde481b6aeade (patch)
tree03e0fbb08f70bbea3335838bea26292d48d24bc9
parent420110d12bd74969f84d6a1979b33f1d71d63c43 (diff)
xcb: Add a special case for recording surface
An unbounded recording surface will complain loudly when you call acquire_source_image on it and thus we need a special case which draws the recording surface to a temporary surface and then proceeds with that. Signed-off-by: Uli Schlachter <psychon@znc.in>
-rw-r--r--src/cairo-xcb-surface-render.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index afd339ab..13d92f74 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -42,6 +42,8 @@
#include "cairo-surface-snapshot-private.h"
#include "cairo-surface-subsurface-private.h"
#include "cairo-traps-private.h"
+#include "cairo-recording-surface-private.h"
+#include "cairo-paginated-private.h"
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
@@ -1060,6 +1062,66 @@ _cairo_xcb_surface_setup_surface_picture(cairo_xcb_picture_t *picture,
}
static cairo_xcb_picture_t *
+record_to_picture (cairo_surface_t *target,
+ const cairo_surface_pattern_t *pattern,
+ const cairo_rectangle_int_t *extents)
+{
+ cairo_surface_pattern_t tmp_pattern;
+ cairo_xcb_picture_t *picture;
+ cairo_status_t status;
+ cairo_matrix_t matrix;
+ cairo_surface_t *tmp;
+ cairo_surface_t *source = pattern->surface;
+
+ /* XXX: The following is more or less copied from cairo-xlibs-ource.c,
+ * record_source() and recording_pattern_get_surface(), can we share a
+ * single version?
+ */
+
+ /* First get the 'real' recording surface */
+ if (_cairo_surface_is_paginated (source))
+ source = _cairo_paginated_surface_get_recording (source);
+ if (_cairo_surface_is_snapshot (source))
+ source = _cairo_surface_snapshot_get_target (source);
+ assert (_cairo_surface_is_recording (source));
+
+ /* Now draw the recording surface to an xcb surface */
+ tmp = _cairo_surface_create_similar_scratch (target,
+ source->content,
+ extents->width,
+ extents->height);
+ if (tmp->status != CAIRO_STATUS_SUCCESS) {
+ return (cairo_xcb_picture_t *) tmp;
+ }
+
+ cairo_matrix_init_translate (&matrix, extents->x, extents->y);
+ status = _cairo_recording_surface_replay_with_clip (source,
+ &matrix, tmp,
+ NULL);
+ if (unlikely (status)) {
+ cairo_surface_destroy (tmp);
+ return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
+ }
+
+ /* Now that we have drawn this to an xcb surface, try again with that */
+ _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
+ tmp_pattern.surface = tmp;
+
+ if (extents->x | extents->y) {
+ cairo_matrix_t *pmatrix = &tmp_pattern.base.matrix;
+
+ cairo_matrix_init_translate (&matrix, -extents->x, -extents->y);
+ cairo_matrix_multiply (pmatrix, pmatrix, &matrix);
+ }
+
+ picture = _copy_to_picture ((cairo_xcb_surface_t *) tmp);
+ if (picture->base.status == CAIRO_STATUS_SUCCESS)
+ _cairo_xcb_surface_setup_surface_picture (picture, &tmp_pattern, extents);
+ cairo_surface_destroy (tmp);
+ return picture;
+}
+
+static cairo_xcb_picture_t *
_cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
const cairo_surface_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
@@ -1177,6 +1239,14 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
/* pixmap from texture */
}
#endif
+ else if (source->type == CAIRO_SURFACE_TYPE_RECORDING)
+ {
+ /* We have to skip the call to attach_snapshot() because we possibly
+ * only drew part of the recording surface.
+ * TODO: When can we safely attach a snapshot?
+ */
+ return record_to_picture(&target->base, pattern, extents);
+ }
if (picture == NULL) {
cairo_image_surface_t *image;