[cairo-commit] 2 commits - src/cairo-xlib-private.h src/cairo-xlib-screen.c src/cairo-xlib-surface.c src/cairo-xlib-surface-private.h test/clip-image.c test/clip-image.ref.png test/Makefile.am test/Makefile.sources
Chris Wilson
ickle at kemper.freedesktop.org
Tue Sep 1 16:38:10 PDT 2009
src/cairo-xlib-private.h | 12 --
src/cairo-xlib-screen.c | 50 +++------
src/cairo-xlib-surface-private.h | 2
src/cairo-xlib-surface.c | 197 ++++++++++++++++++---------------------
test/Makefile.am | 1
test/Makefile.sources | 1
test/clip-image.c | 94 ++++++++++++++++++
test/clip-image.ref.png |binary
8 files changed, 212 insertions(+), 145 deletions(-)
New commits:
commit 59c4fe93ee30c8182ae1a29267b9c08602e2f6c5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Wed Sep 2 00:34:37 2009 +0100
[xlib] Eliminate GC clipping
Eradicate the use of clipping with GC. By never using clipping, we never
have to worry about retrieving a dirty clip from the GC cache.
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index e92bb94..33601e8 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -85,7 +85,7 @@ struct _cairo_xlib_screen {
cairo_font_options_t font_options;
GC gc[4];
- int gc_depths; /* 4 x uint8_t, high bit == needs reset */
+ int gc_depths; /* 4 x uint8_t */
cairo_array_t visuals;
};
@@ -171,15 +171,13 @@ _cairo_xlib_screen_close_display (cairo_xlib_screen_t *info);
cairo_private GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- Drawable drawable,
- unsigned int *need_reset);
+ int depth,
+ Drawable drawable);
cairo_private void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- GC gc,
- cairo_bool_t reset_clip);
+ int depth,
+ GC gc);
cairo_private cairo_font_options_t *
_cairo_xlib_screen_get_font_options (cairo_xlib_screen_t *info);
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 38e64af..800c6d2 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -380,9 +380,8 @@ _cairo_xlib_screen_get (Display *dpy,
#if HAS_ATOMIC_OPS
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- Drawable drawable,
- unsigned int *dirty)
+ int depth,
+ Drawable drawable)
{
XGCValues gcv;
int i, new, old;
@@ -394,13 +393,13 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
if (old == 0)
break;
- if (((old >> 0) & 0x7f) == depth)
+ if (((old >> 0) & 0xff) == depth)
i = 0;
- else if (((old >> 8) & 0x7f) == depth)
+ else if (((old >> 8) & 0xff) == depth)
i = 1;
- else if (((old >> 16) & 0x7f) == depth)
+ else if (((old >> 16) & 0xff) == depth)
i = 2;
- else if (((old >> 24) & 0x7f) == depth)
+ else if (((old >> 24) & 0xff) == depth)
i = 3;
else
break;
@@ -411,10 +410,6 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
if (likely (gc != NULL)) {
(void) _cairo_atomic_ptr_cmpxchg (&info->gc[i], gc, NULL);
-
- if (old & 0x80 << (8 * i))
- *dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
-
return gc;
}
@@ -426,25 +421,23 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- GC gc,
- cairo_bool_t reset_clip)
+ int depth,
+ GC gc)
{
int i, old, new;
- depth |= reset_clip ? 0x80 : 0;
do {
do {
i = -1;
old = info->gc_depths;
- if (((old >> 0) & 0x7f) == 0)
+ if (((old >> 0) & 0xff) == 0)
i = 0;
- else if (((old >> 8) & 0x7f) == 0)
+ else if (((old >> 8) & 0xff) == 0)
i = 1;
- else if (((old >> 16) & 0x7f) == 0)
+ else if (((old >> 16) & 0xff) == 0)
i = 2;
- else if (((old >> 24) & 0x7f) == 0)
+ else if (((old >> 24) & 0xff) == 0)
i = 3;
else
goto out;
@@ -468,19 +461,15 @@ out:
#else
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- Drawable drawable,
- unsigned int *dirty)
+ int depth,
+ Drawable drawable)
{
GC gc = NULL;
int i;
CAIRO_MUTEX_LOCK (info->mutex);
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
- if (((info->gc_depths >> (8*i)) & 0x7f) == depth) {
- if (info->gc_depths & 0x80 << (8*i))
- *dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
-
+ if (((info->gc_depths >> (8*i)) & 0xff) == depth) {
info->gc_depths &= ~(0xff << (8*i));
gc = info->gc[i];
break;
@@ -502,17 +491,14 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- GC gc,
- cairo_bool_t reset_clip)
+ int depth,
+ GC gc)
{
int i;
- depth |= reset_clip ? 0x80 : 0;
-
CAIRO_MUTEX_LOCK (info->mutex);
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
- if (((info->gc_depths >> (8*i)) & 0x7f) == 0)
+ if (((info->gc_depths >> (8*i)) & 0xff) == 0)
break;
}
diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h
index b3cbe04..f821569 100644
--- a/src/cairo-xlib-surface-private.h
+++ b/src/cairo-xlib-surface-private.h
@@ -49,7 +49,6 @@ struct _cairo_xlib_surface {
cairo_xlib_screen_t *screen;
cairo_xlib_hook_t close_display_hook;
- GC gc;
Drawable drawable;
cairo_bool_t owns_pixmap;
Visual *visual;
@@ -88,7 +87,6 @@ struct _cairo_xlib_surface {
Picture dst_picture, src_picture;
unsigned int clip_dirty;
- cairo_bool_t gc_has_clip_rects;
XRectangle embedded_clip_rects[8];
XRectangle *clip_rects;
int num_clip_rects;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index b53f4de..1de6a97 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -83,11 +83,10 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
int depth);
static cairo_status_t
-_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface,
- cairo_bool_t set_clip);
+_cairo_xlib_surface_get_gc (cairo_xlib_surface_t *surface, GC *gc);
static void
-_cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t *surface);
+_cairo_xlib_surface_put_gc (cairo_xlib_surface_t *surface, GC gc);
static void
_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface);
@@ -380,14 +379,6 @@ _cairo_xlib_surface_finish (void *abstract_surface)
XRenderFreePicture (surface->dpy, surface->src_picture);
}
- if (surface->gc != NULL) {
- _cairo_xlib_screen_put_gc (surface->screen,
- surface->depth,
- surface->gc,
- surface->gc_has_clip_rects);
- surface->gc = NULL;
- }
-
if (surface->clip_rects != surface->embedded_clip_rects)
free (surface->clip_rects);
@@ -742,8 +733,9 @@ _get_image_surface (cairo_xlib_surface_t *surface,
* temporary pixmap
*/
Pixmap pixmap;
+ GC gc;
- status = _cairo_xlib_surface_ensure_gc (surface, FALSE);
+ status = _cairo_xlib_surface_get_gc (surface, &gc);
if (unlikely (status))
return status;
@@ -752,7 +744,7 @@ _get_image_surface (cairo_xlib_surface_t *surface,
extents.width, extents.height,
surface->depth);
if (pixmap) {
- XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc,
+ XCopyArea (surface->dpy, surface->drawable, pixmap, gc,
extents.x, extents.y,
extents.width, extents.height,
0, 0);
@@ -766,10 +758,10 @@ _get_image_surface (cairo_xlib_surface_t *surface,
XFreePixmap (surface->dpy, pixmap);
}
+ _cairo_xlib_surface_put_gc (surface, gc);
+
if (ximage == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_xlib_surface_maybe_put_gc (surface);
}
_swap_ximage_to_native (ximage);
@@ -947,21 +939,6 @@ _cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface)
}
static void
-_cairo_xlib_surface_set_gc_clip_rects (cairo_xlib_surface_t *surface)
-{
- surface->gc_has_clip_rects = surface->clip_region != NULL;
- if (surface->clip_region != NULL) {
- XSetClipRectangles(surface->dpy, surface->gc,
- 0, 0,
- surface->clip_rects,
- surface->num_clip_rects, YXSorted);
- } else
- XSetClipMask (surface->dpy, surface->gc, None);
-
- surface->clip_dirty &= ~CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
-}
-
-static void
_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface)
{
if (!surface->dst_picture) {
@@ -976,49 +953,23 @@ _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface)
}
static cairo_status_t
-_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface,
- cairo_bool_t set_clip)
+_cairo_xlib_surface_get_gc (cairo_xlib_surface_t *surface, GC *gc)
{
-
- if (surface->gc == NULL) {
- surface->gc = _cairo_xlib_screen_get_gc (surface->screen,
- surface->depth,
- surface->drawable,
- &surface->clip_dirty);
- if (unlikely (surface->gc == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- surface->gc_has_clip_rects =
- surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
- }
-
- if (set_clip) {
- if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC)
- _cairo_xlib_surface_set_gc_clip_rects (surface);
- } else {
- if (surface->gc_has_clip_rects) {
- surface->gc_has_clip_rects = FALSE;
- XSetClipMask (surface->dpy, surface->gc, None);
-
- surface->clip_dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
- }
- }
+ *gc = _cairo_xlib_screen_get_gc (surface->screen,
+ surface->depth,
+ surface->drawable);
+ if (unlikely (*gc == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
static void
-_cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t *surface)
+_cairo_xlib_surface_put_gc (cairo_xlib_surface_t *surface, GC gc)
{
- /* return the GC back to the common pool if clean */
- if (surface->gc_has_clip_rects)
- return;
-
_cairo_xlib_screen_put_gc (surface->screen,
surface->depth,
- surface->gc,
- FALSE);
- surface->gc = NULL;
+ gc);
}
static cairo_status_t
@@ -1036,6 +987,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
cairo_status_t status;
cairo_bool_t own_data;
+ GC gc;
_pixman_format_to_masks (image->pixman_format, &image_masks);
@@ -1173,16 +1125,15 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
}
}
- /* XXX set clip? */
- status = _cairo_xlib_surface_ensure_gc (surface, FALSE);
+ status = _cairo_xlib_surface_get_gc (surface, &gc);
if (unlikely (status))
goto BAIL;
- XPutImage (surface->dpy, surface->drawable, surface->gc,
+ XPutImage (surface->dpy, surface->drawable, gc,
&ximage, src_x, src_y, dst_x, dst_y,
width, height);
- _cairo_xlib_surface_maybe_put_gc (surface);
+ _cairo_xlib_surface_put_gc (surface, gc);
BAIL:
if (own_data)
@@ -2136,6 +2087,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
cairo_bool_t is_integer_translation;
cairo_bool_t needs_alpha_composite;
cairo_content_t src_content;
+ GC gc;
if (mask_pattern != NULL && ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return UNSUPPORTED ("no support for masks");
@@ -2183,10 +2135,6 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
goto BAIL;
}
- status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
- if (unlikely (status))
- goto BAIL;
-
switch (operation)
{
case DO_RENDER:
@@ -2196,6 +2144,10 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
if (unlikely (status))
goto BAIL;
+ status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
+ if (unlikely (status))
+ goto BAIL;
+
_cairo_xlib_surface_ensure_dst_picture (dst);
if (mask) {
status = _cairo_xlib_surface_set_attributes (mask, &mask_attr,
@@ -2231,7 +2183,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
break;
case DO_XCOPYAREA:
- status = _cairo_xlib_surface_ensure_gc (dst, TRUE);
+ status = _cairo_xlib_surface_get_gc (dst, &gc);
if (unlikely (status))
goto BAIL;
@@ -2240,16 +2192,38 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
/* This is a pre-condition for DO_XCOPYAREA. */
assert (is_integer_translation);
- XCopyArea (dst->dpy,
- src->drawable,
- dst->drawable,
- dst->gc,
- src_x + src_attr.x_offset + itx,
- src_y + src_attr.y_offset + ity,
- width, height,
- dst_x, dst_y);
+ if (clip_region == NULL) {
+ XCopyArea (dst->dpy,
+ src->drawable,
+ dst->drawable,
+ gc,
+ src_x + src_attr.x_offset + itx,
+ src_y + src_attr.y_offset + ity,
+ width, height,
+ dst_x, dst_y);
+ } else {
+ int n, num_rects;
+
+ src_x += src_attr.x_offset + itx - dst_x;
+ src_y += src_attr.y_offset + ity - dst_y;
+
+ num_rects = cairo_region_num_rectangles (clip_region);
+ for (n = 0; n < num_rects; n++) {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (clip_region, n, &rect);
+ XCopyArea (dst->dpy,
+ src->drawable,
+ dst->drawable,
+ gc,
+ rect.x + src_x,
+ rect.y + src_y,
+ rect.width, rect.height,
+ rect.x, rect.y);
+ }
+ }
- _cairo_xlib_surface_maybe_put_gc (dst);
+ _cairo_xlib_surface_put_gc (dst, gc);
break;
case DO_XTILE:
@@ -2261,23 +2235,42 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
* _recategorize_composite_operation.
*/
- status = _cairo_xlib_surface_ensure_gc (dst, TRUE);
+ status = _cairo_xlib_surface_get_gc (dst, &gc);
if (unlikely (status))
goto BAIL;
+
is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr.matrix,
&itx, &ity);
/* This is a pre-condition for DO_XTILE. */
assert (is_integer_translation);
- XSetTSOrigin (dst->dpy, dst->gc,
+ XSetTSOrigin (dst->dpy, gc,
- (itx + src_attr.x_offset), - (ity + src_attr.y_offset));
- XSetTile (dst->dpy, dst->gc, src->drawable);
- XSetFillStyle (dst->dpy, dst->gc, FillTiled);
+ XSetTile (dst->dpy, gc, src->drawable);
+ XSetFillStyle (dst->dpy, gc, FillTiled);
+
+ if (clip_region == NULL) {
+ XFillRectangle (dst->dpy, dst->drawable, gc,
+ dst_x, dst_y, width, height);
+ } else {
+ int n, num_rects;
- XFillRectangle (dst->dpy, dst->drawable, dst->gc,
- dst_x, dst_y, width, height);
+ src_x += src_attr.x_offset + itx;
+ src_y += src_attr.y_offset + ity;
- _cairo_xlib_surface_maybe_put_gc (dst);
+ num_rects = cairo_region_num_rectangles (clip_region);
+ for (n = 0; n < num_rects; n++) {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (clip_region, n, &rect);
+ rect.x -= dst_x;
+ rect.y -= dst_y;
+ XFillRectangle (dst->dpy, dst->drawable, gc,
+ rect.x, rect.y, rect.width, rect.height);
+ }
+ }
+
+ _cairo_xlib_surface_put_gc (dst, gc);
break;
case DO_UNSUPPORTED:
@@ -2316,11 +2309,12 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
cairo_solid_pattern_t solid;
cairo_surface_t *solid_surface = NULL;
cairo_surface_attributes_t attrs;
+ GC gc;
int i;
_cairo_pattern_init_solid (&solid, color, CAIRO_CONTENT_COLOR);
- status = _cairo_xlib_surface_ensure_gc (surface, FALSE);
+ status = _cairo_xlib_surface_get_gc (surface, &gc);
if (unlikely (status))
return status;
@@ -2332,25 +2326,27 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
CAIRO_PATTERN_ACQUIRE_NONE,
&solid_surface,
&attrs);
- if (unlikely (status))
- return status;
+ if (unlikely (status)) {
+ _cairo_xlib_surface_put_gc (surface, gc);
+ return status;
+ }
assert (_cairo_surface_is_xlib (solid_surface));
- XSetTSOrigin (surface->dpy, surface->gc,
+ XSetTSOrigin (surface->dpy, gc,
- (surface->base.device_transform.x0 + attrs.x_offset),
- (surface->base.device_transform.y0 + attrs.y_offset));
- XSetTile (surface->dpy, surface->gc,
+ XSetTile (surface->dpy, gc,
((cairo_xlib_surface_t *) solid_surface)->drawable);
- XSetFillStyle (surface->dpy, surface->gc, FillTiled);
+ XSetFillStyle (surface->dpy, gc, FillTiled);
for (i = 0; i < num_rects; i++) {
- XFillRectangle (surface->dpy, surface->drawable, surface->gc,
+ XFillRectangle (surface->dpy, surface->drawable, gc,
rects[i].x, rects[i].y,
rects[i].width, rects[i].height);
}
- _cairo_xlib_surface_maybe_put_gc (surface);
+ _cairo_xlib_surface_put_gc (surface, gc);
_cairo_pattern_release_surface (&solid.base, solid_surface, &attrs);
@@ -2859,11 +2855,6 @@ _cairo_xlib_surface_detach_display (cairo_xlib_display_t *display, void *data)
surface->drawable = None;
surface->owns_pixmap = FALSE;
}
-
- if (surface->gc != NULL) {
- XFreeGC (dpy, surface->gc);
- surface->gc = NULL;
- }
}
static cairo_surface_t *
@@ -2947,7 +2938,6 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
surface->screen = _cairo_xlib_screen_reference (screen);
surface->display = screen->display;
- surface->gc = NULL;
surface->drawable = drawable;
surface->owns_pixmap = FALSE;
surface->use_pixmap = 0;
@@ -2979,7 +2969,6 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
surface->xtransform = identity;
surface->clip_region = NULL;
- surface->gc_has_clip_rects = FALSE;
surface->clip_rects = surface->embedded_clip_rects;
surface->num_clip_rects = 0;
surface->clip_dirty = 0;
commit 075fc5666abe006c434bf7ec28d2d4f0226a1d3a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Wed Sep 2 00:33:22 2009 +0100
[test] Add clip-image
Exercise the XCopyArea() paths under clipping - whilst modifying that code
I noticed that it was not being exercised by the test suite.
diff --git a/test/Makefile.am b/test/Makefile.am
index 4ac776f..aaa520d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -177,6 +177,7 @@ REFERENCE_IMAGES = \
clip-fill-rule.rgb24.ref.png \
clip-fill-rule.test-paginated.rgb24.ref.png \
clip-fill-rule.xlib.rgb24.ref.png \
+ clip-image.ref.png \
clip-nesting.pdf.argb32.ref.png \
clip-nesting.ps2.argb32.ref.png \
clip-nesting.ps2.rgb24.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index c4f2516..3dbdd55 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -18,6 +18,7 @@ test_sources = \
clip-fill.c \
clip-fill-rule.c \
clip-fill-rule-pixel-aligned.c \
+ clip-image.c \
clip-nesting.c \
clip-operator.c \
clip-push-group.c \
diff --git a/test/clip-image.c b/test/clip-image.c
new file mode 100644
index 0000000..e3c8809
--- /dev/null
+++ b/test/clip-image.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#define WIDTH 20
+#define HEIGHT 20
+
+static const char *png_filename = "romedalen.png";
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ const cairo_test_context_t *ctx = cairo_test_get_context (cr);
+ cairo_surface_t *image;
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ image = cairo_test_create_surface_from_png (ctx, png_filename);
+ cairo_set_source_surface (cr, image, 0, 0);
+
+ /* simple clip */
+ cairo_save (cr);
+ cairo_rectangle (cr, 2, 2, 16, 16);
+ cairo_clip (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ cairo_translate (cr, WIDTH, 0);
+
+ /* unaligned clip */
+ cairo_save (cr);
+ cairo_rectangle (cr, 2.5, 2.5, 15, 15);
+ cairo_clip (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ cairo_translate (cr, -WIDTH, HEIGHT);
+
+ /* aligned-clip */
+ cairo_save (cr);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_rectangle (cr, 0, 0, 20, 20);
+ cairo_rectangle (cr, 3, 3, 10, 10);
+ cairo_rectangle (cr, 7, 7, 10, 10);
+ cairo_clip (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ cairo_translate (cr, WIDTH, 0);
+
+ /* force a clip-mask */
+ cairo_save (cr);
+ cairo_arc (cr, 10, 10, 10, 0, 2 * M_PI);
+ cairo_new_sub_path (cr);
+ cairo_arc_negative (cr, 10, 10, 5, 2 * M_PI, 0);
+ cairo_new_sub_path (cr);
+ cairo_arc (cr, 10, 10, 2, 0, 2 * M_PI);
+ cairo_clip (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (clip_image,
+ "Tests painting an image through complex clips.",
+ "clip, paint", /* keywords */
+ NULL, /* requirements */
+ 2 * WIDTH, 2 * HEIGHT,
+ NULL, draw)
diff --git a/test/clip-image.ref.png b/test/clip-image.ref.png
new file mode 100644
index 0000000..b038f2a
Binary files /dev/null and b/test/clip-image.ref.png differ
More information about the cairo-commit
mailing list