diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-01-18 18:06:51 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-01-22 23:01:50 +0000 |
commit | dc8290814c0e98b38828953bac6dd0893c31c9ad (patch) | |
tree | d4977b496e464a541f277fabad4ac23138752f63 | |
parent | b8eacbfae1c155f412d84120411103cb610e383b (diff) |
Add subsurface.
A subsurface is a region of another surface that may be used either to
restrict the writable area of a context or the readable extents of a
source. Whilst writing, access to the exterior of the subsurface is
prevented via clipping and when used as a source reads from the exterior
of the subsurface are governed via the extend mechanism of the pattern.
-rw-r--r-- | src/Makefile.sources | 2 | ||||
-rw-r--r-- | src/cairo-surface-subsurface-private.h | 48 | ||||
-rw-r--r-- | src/cairo-surface-subsurface.c | 464 | ||||
-rw-r--r-- | src/cairo-types-private.h | 4 | ||||
-rw-r--r-- | src/cairo.h | 7 | ||||
-rw-r--r-- | test/Makefile.am | 3 | ||||
-rw-r--r-- | test/Makefile.sources | 3 | ||||
-rw-r--r-- | test/subsurface-repeat.c | 72 | ||||
-rw-r--r-- | test/subsurface-repeat.ref.png | bin | 0 -> 197 bytes | |||
-rw-r--r-- | test/subsurface-similar-repeat.c | 83 | ||||
-rw-r--r-- | test/subsurface-similar-repeat.ref.png | bin | 0 -> 197 bytes | |||
-rw-r--r-- | test/subsurface.c | 80 | ||||
-rw-r--r-- | test/subsurface.ref.png | bin | 0 -> 1597 bytes |
13 files changed, 765 insertions, 1 deletions
diff --git a/src/Makefile.sources b/src/Makefile.sources index 6bfef7f7..5fc9fbb2 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -90,6 +90,7 @@ cairo_private = \ cairo-surface-private.h \ cairo-surface-clipper-private.h \ cairo-surface-offset-private.h \ + cairo-surface-subsurface-private.h \ cairo-surface-wrapper-private.h \ cairo-tee-surface-private.h \ cairo-types-private.h \ @@ -152,6 +153,7 @@ cairo_sources = \ cairo-surface-fallback.c \ cairo-surface-clipper.c \ cairo-surface-offset.c \ + cairo-surface-subsurface.c \ cairo-surface-wrapper.c \ cairo-system.c \ cairo-tee-surface.c \ diff --git a/src/cairo-surface-subsurface-private.h b/src/cairo-surface-subsurface-private.h new file mode 100644 index 00000000..0f38c057 --- /dev/null +++ b/src/cairo-surface-subsurface-private.h @@ -0,0 +1,48 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2009 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Intel Corporation. + * + * Contributor(s): + * Chris Wilson <chris@chris-wilson.co.uk> + */ + +#ifndef CAIRO_SURFACE_SUBSURFACE_PRIVATE_H +#define CAIRO_SURFACE_SUBSURFACE_PRIVATE_H + +#include "cairo-surface-private.h" + +struct _cairo_surface_subsurface { + cairo_surface_t base; + + cairo_surface_t *target; + cairo_rectangle_int_t extents; +}; + +#endif /* CAIRO_SURFACE_SUBSURFACE_PRIVATE_H */ diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c new file mode 100644 index 00000000..55fe7a3f --- /dev/null +++ b/src/cairo-surface-subsurface.c @@ -0,0 +1,464 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2009 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Intel Corporation. + * + * Contributor(s): + * Chris Wilson <chris@chris-wilson.co.uk> + */ + +#include "cairoint.h" + +#include "cairo-error-private.h" +#include "cairo-surface-offset-private.h" +#include "cairo-surface-subsurface-private.h" + +static cairo_status_t +_cairo_surface_subsurface_finish (void *abstract_surface) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + + cairo_surface_destroy (surface->target); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_surface_t * +_cairo_surface_subsurface_create_similar (void *other, + cairo_content_t content, + int width, int height) +{ + cairo_surface_subsurface_t *surface = other; + return surface->target->backend->create_similar (surface->target, content, width, height); +} + +static cairo_int_status_t +_cairo_surface_subsurface_paint (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_clip_t *clip) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; + cairo_status_t status; + cairo_clip_t target_clip; + + status = _cairo_clip_rectangle (_cairo_clip_init_copy (&target_clip, clip), &rect); + if (unlikely (status)) + goto CLEANUP; + + status = _cairo_surface_offset_paint (surface->target, + -surface->extents.x, -surface->extents.y, + op, source, &target_clip); + CLEANUP: + _cairo_clip_fini (&target_clip); + return status; +} + +static cairo_int_status_t +_cairo_surface_subsurface_mask (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_pattern_t *mask, + cairo_clip_t *clip) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; + cairo_status_t status; + cairo_clip_t target_clip; + + status = _cairo_clip_rectangle (_cairo_clip_init_copy (&target_clip, clip), &rect); + if (unlikely (status)) + goto CLEANUP; + + status = _cairo_surface_offset_mask (surface->target, + -surface->extents.x, -surface->extents.y, + op, source, mask, &target_clip); + CLEANUP: + _cairo_clip_fini (&target_clip); + return status; +} + +static cairo_int_status_t +_cairo_surface_subsurface_fill (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias, + cairo_clip_t *clip) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; + cairo_status_t status; + cairo_clip_t target_clip; + + status = _cairo_clip_rectangle (_cairo_clip_init_copy (&target_clip, clip), &rect); + if (unlikely (status)) + goto CLEANUP; + + status = _cairo_surface_offset_fill (surface->target, + -surface->extents.x, -surface->extents.y, + op, source, path, fill_rule, tolerance, antialias, + &target_clip); + CLEANUP: + _cairo_clip_fini (&target_clip); + return status; +} + +static cairo_int_status_t +_cairo_surface_subsurface_stroke (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_path_fixed_t *path, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + cairo_clip_t *clip) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; + cairo_status_t status; + cairo_clip_t target_clip; + + status = _cairo_clip_rectangle (_cairo_clip_init_copy (&target_clip, clip), &rect); + if (unlikely (status)) + goto CLEANUP; + + status = _cairo_surface_offset_stroke (surface->target, + -surface->extents.x, -surface->extents.y, + op, source, path, stroke_style, ctm, ctm_inverse, + tolerance, antialias, + &target_clip); + CLEANUP: + _cairo_clip_fini (&target_clip); + return status; +} + +static cairo_int_status_t +_cairo_surface_subsurface_glyphs (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + cairo_clip_t *clip, + int *remaining_glyphs) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; + cairo_status_t status; + cairo_clip_t target_clip; + + status = _cairo_clip_rectangle (_cairo_clip_init_copy (&target_clip, clip), &rect); + if (unlikely (status)) + goto CLEANUP; + + status = _cairo_surface_offset_glyphs (surface->target, + -surface->extents.x, -surface->extents.y, + op, source, + scaled_font, glyphs, num_glyphs, + &target_clip); + *remaining_glyphs = 0; + CLEANUP: + _cairo_clip_fini (&target_clip); + return status; +} + +static cairo_status_t +_cairo_surface_subsurface_flush (void *abstract_surface) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_status_t status; + + status = CAIRO_STATUS_SUCCESS; + if (surface->target->backend->flush != NULL) + status = surface->target->backend->flush (surface->target); + + return status; +} + +static cairo_status_t +_cairo_surface_subsurface_mark_dirty (void *abstract_surface, + int x, int y, + int width, int height) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_status_t status; + + status = CAIRO_STATUS_SUCCESS; + if (surface->target->backend->mark_dirty_rectangle != NULL) { + cairo_rectangle_int_t rect, extents; + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + + extents.x = extents.y = 0; + extents.width = surface->extents.width; + extents.height = surface->extents.height; + + if (_cairo_rectangle_intersect (&rect, &extents)) { + status = surface->target->backend->mark_dirty_rectangle (surface->target, + rect.x + surface->extents.x, + rect.y + surface->extents.y, + rect.width, rect.height); + } + } + + return status; +} + +static cairo_bool_t +_cairo_surface_subsurface_get_extents (void *abstract_surface, + cairo_rectangle_int_t *extents) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + + extents->x = 0; + extents->y = 0; + extents->width = surface->extents.width; + extents->height = surface->extents.height; + + return TRUE; +} + +static void +_cairo_surface_subsurface_get_font_options (void *abstract_surface, + cairo_font_options_t *options) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + + if (surface->target->backend->get_font_options != NULL) + surface->target->backend->get_font_options (surface->target, options); +} + +struct extra { + cairo_image_surface_t *image; + void *image_extra; +}; + +static cairo_status_t +_cairo_surface_subsurface_acquire_source_image (void *abstract_surface, + cairo_image_surface_t **image_out, + void **extra_out) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_image_surface_t *image; + cairo_status_t status; + struct extra *extra; + uint8_t *data; + + extra = malloc (sizeof (struct extra)); + if (unlikely (extra == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_surface_acquire_source_image (surface->target, &extra->image, &extra->image_extra); + if (unlikely (status)) + goto CLEANUP; + + /* only copy if we need to perform sub-byte manipulation */ + if (PIXMAN_FORMAT_BPP (extra->image->pixman_format) > 8) { + assert ((PIXMAN_FORMAT_BPP (extra->image->pixman_format) % 8) == 0); + + data = extra->image->data + surface->extents.y * extra->image->stride; + data += PIXMAN_FORMAT_BPP (extra->image->pixman_format) / 8 * surface->extents.x; + + image = (cairo_image_surface_t *) + _cairo_image_surface_create_with_pixman_format (data, + extra->image->pixman_format, + surface->extents.width, + surface->extents.height, + extra->image->stride); + if (unlikely ((status = image->base.status))) + goto CLEANUP_IMAGE; + } else { + image = (cairo_image_surface_t *) + _cairo_image_surface_create_with_pixman_format (NULL, + extra->image->pixman_format, + surface->extents.width, + surface->extents.height, + 0); + if (unlikely ((status = image->base.status))) + goto CLEANUP_IMAGE; + + pixman_image_composite (PIXMAN_OP_SRC, + image->pixman_image, NULL, extra->image->pixman_image, + surface->extents.x, surface->extents.y, + 0, 0, + 0, 0, + surface->extents.width, surface->extents.height); + } + + *image_out = image; + *extra_out = extra; + return CAIRO_STATUS_SUCCESS; + +CLEANUP_IMAGE: + _cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra); +CLEANUP: + free (extra); + return status; +} + +static void +_cairo_surface_subsurface_release_source_image (void *abstract_surface, + cairo_image_surface_t *image, + void *abstract_extra) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + struct extra *extra = abstract_extra; + + _cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra); + free (extra); + + cairo_surface_destroy (&image->base); +} + +static cairo_surface_t * +_cairo_surface_subsurface_snapshot (void *abstract_surface) +{ + cairo_surface_subsurface_t *surface = abstract_surface; + cairo_image_surface_t *image, *clone; + void *image_extra; + cairo_status_t status; + + /* XXX Alternatively we could snapshot the target and return a subsurface + * of that. + */ + + status = _cairo_surface_acquire_source_image (surface->target, &image, &image_extra); + if (unlikely (status)) + return _cairo_surface_create_in_error (status); + + clone = (cairo_image_surface_t *) + _cairo_image_surface_create_with_pixman_format (NULL, + image->pixman_format, + surface->extents.width, + surface->extents.height, + 0); + if (unlikely (clone->base.status)) + return &clone->base; + + pixman_image_composite (PIXMAN_OP_SRC, + image->pixman_image, NULL, clone->pixman_image, + surface->extents.x, surface->extents.y, + 0, 0, + 0, 0, + surface->extents.width, surface->extents.height); + + _cairo_surface_release_source_image (surface->target, image, image_extra); + + return &clone->base; +} + +static const cairo_surface_backend_t _cairo_surface_subsurface_backend = { + CAIRO_INTERNAL_SURFACE_TYPE_SUBSURFACE, + _cairo_surface_subsurface_create_similar, + _cairo_surface_subsurface_finish, + + _cairo_surface_subsurface_acquire_source_image, + _cairo_surface_subsurface_release_source_image, + NULL, NULL, /* acquire, release dest */ + NULL, /* clone similar */ + NULL, /* composite */ + NULL, /* fill rectangles */ + NULL, /* composite trapezoids */ + NULL, /* create span renderer */ + NULL, /* check span renderer */ + NULL, /* copy_page */ + NULL, /* show_page */ + _cairo_surface_subsurface_get_extents, + NULL, /* old_show_glyphs */ + _cairo_surface_subsurface_get_font_options, + _cairo_surface_subsurface_flush, + _cairo_surface_subsurface_mark_dirty, + NULL, /* font_fini */ + NULL, /* glyph_fini */ + + _cairo_surface_subsurface_paint, + _cairo_surface_subsurface_mask, + _cairo_surface_subsurface_stroke, + _cairo_surface_subsurface_fill, + _cairo_surface_subsurface_glyphs, + + _cairo_surface_subsurface_snapshot, +}; + +cairo_surface_t * +cairo_surface_create_for_region (cairo_surface_t *target, + int x, int y, + int width, int height) +{ + cairo_surface_subsurface_t *surface; + + if (unlikely (target->status)) + return _cairo_surface_create_in_error (target->status); + + if (target->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SUBSURFACE) { + /* Maintain subsurfaces as 1-depth */ + cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) target; + cairo_rectangle_int_t r; + cairo_bool_t is_empty; + + r.x = x; + r.y = y; + r.width = width; + r.height = height; + + is_empty = _cairo_rectangle_intersect (&r, &sub->extents); + + x = r.x; + y = r.y; + width = r.width; + height = r.height; + target = sub->target; + } + + surface = malloc (sizeof (cairo_surface_subsurface_t)); + if (unlikely (surface == NULL)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + + _cairo_surface_init (&surface->base, + &_cairo_surface_subsurface_backend, + target->content); + surface->base.type = target->type; + + surface->target = cairo_surface_reference (target); + surface->extents.x = x; + surface->extents.y = y; + surface->extents.width = width; + surface->extents.height = height; + + return &surface->base; +} diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h index 3a3b8496..125874bd 100644 --- a/src/cairo-types-private.h +++ b/src/cairo-types-private.h @@ -64,6 +64,7 @@ typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t; typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t; typedef struct _cairo_solid_pattern cairo_solid_pattern_t; typedef struct _cairo_surface_backend cairo_surface_backend_t; +typedef struct _cairo_surface_subsurface cairo_surface_subsurface_t; typedef struct _cairo_surface_wrapper cairo_surface_wrapper_t; typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t; typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t; @@ -164,7 +165,8 @@ typedef enum _cairo_int_status { } cairo_int_status_t; typedef enum _cairo_internal_surface_type { - CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED = 0x1000, + CAIRO_INTERNAL_SURFACE_TYPE_SUBSURFACE = 0x1000, + CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED, CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, diff --git a/src/cairo.h b/src/cairo.h index 8be80439..4b6c5a68 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -1921,6 +1921,13 @@ cairo_surface_create_similar (cairo_surface_t *other, int height); cairo_public cairo_surface_t * +cairo_surface_create_for_region (cairo_surface_t *target, + int x, + int y, + int width, + int height); + +cairo_public cairo_surface_t * cairo_surface_reference (cairo_surface_t *surface); cairo_public void diff --git a/test/Makefile.am b/test/Makefile.am index 6dbf6bf4..b820dd5b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -933,6 +933,9 @@ REFERENCE_IMAGES = \ stroke-image.quartz.ref.png \ stroke-image.ref.png \ stroke-image.xlib.ref.png \ + subsurface.ref.png \ + subsurface-repeat.ref.png \ + subsurface-similar-repeat.ref.png \ surface-pattern-big-scale-down.ref.png \ surface-pattern-big-scale-down.ps.xfail.png \ surface-pattern-operator.argb32.ref.png \ diff --git a/test/Makefile.sources b/test/Makefile.sources index 52d4f85b..d90f04a1 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -210,6 +210,9 @@ test_sources = \ source-clip-scale.c \ source-surface-scale-paint.c \ spline-decomposition.c \ + subsurface.c \ + subsurface-repeat.c \ + subsurface-similar-repeat.c \ surface-finish-twice.c \ surface-pattern.c \ surface-pattern-big-scale-down.c \ diff --git a/test/subsurface-repeat.c b/test/subsurface-repeat.c new file mode 100644 index 00000000..59c3c544 --- /dev/null +++ b/test/subsurface-repeat.c @@ -0,0 +1,72 @@ +/* + * Copyright 2009 Intel Corporation + * + * 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 + * Intel not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Intel makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * INTEL CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL INTEL CORPORATION 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@chris-wilson.co.uk> + */ + +#include "cairo-test.h" + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + cairo_surface_t *region; + cairo_t *cr_region; + + cairo_set_source_rgb (cr, .5, .5, .5); + cairo_paint (cr); + + /* fill the centre */ + region = cairo_surface_create_for_region (cairo_get_target (cr), + 0, 0, 20, 20); + cr_region = cairo_create (region); + cairo_surface_destroy (region); + + cairo_set_source_rgb (cr_region, 1, 1, 1); + cairo_rectangle (cr_region, 0, 0, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_rgb (cr_region, 1, 0, 0); + cairo_rectangle (cr_region, 10, 0, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_rgb (cr_region, 0, 1, 0); + cairo_rectangle (cr_region, 0, 10, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_rgb (cr_region, 0, 0, 1); + cairo_rectangle (cr_region, 10, 10, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_surface (cr, cairo_get_target (cr_region), 20, 20); + cairo_destroy (cr_region); + cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT); + cairo_paint (cr); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (subsurface_repeat, + "Tests source clipping with repeat", + "subsurface, repeat", /* keywords */ + NULL, /* requirements */ + 60, 60, + NULL, draw) diff --git a/test/subsurface-repeat.ref.png b/test/subsurface-repeat.ref.png Binary files differnew file mode 100644 index 00000000..c37e22e3 --- /dev/null +++ b/test/subsurface-repeat.ref.png diff --git a/test/subsurface-similar-repeat.c b/test/subsurface-similar-repeat.c new file mode 100644 index 00000000..ad63cc8d --- /dev/null +++ b/test/subsurface-similar-repeat.c @@ -0,0 +1,83 @@ +/* + * Copyright 2009 Intel Corporation + * + * 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 + * Intel not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Intel makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * INTEL CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL INTEL CORPORATION 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@chris-wilson.co.uk> + */ + +#include "cairo-test.h" + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + cairo_surface_t *similar; + cairo_surface_t *region; + cairo_t *cr_region; + + cairo_set_source_rgb (cr, .5, .5, .5); + cairo_paint (cr); + + similar = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_COLOR, + 60, 60); + cr_region = cairo_create (similar); + cairo_surface_destroy (similar); + cairo_set_source_rgb (cr_region, .5, .5, .0); + cairo_paint (cr_region); + similar = cairo_surface_reference (cairo_get_target (cr_region)); + cairo_destroy (cr_region); + + /* fill the centre */ + region = cairo_surface_create_for_region (similar, 20, 20, 20, 20); + cairo_surface_destroy (similar); + cr_region = cairo_create (region); + cairo_surface_destroy (region); + + cairo_set_source_rgb (cr_region, 1, 1, 1); + cairo_rectangle (cr_region, 0, 0, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_rgb (cr_region, 1, 0, 0); + cairo_rectangle (cr_region, 10, 0, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_rgb (cr_region, 0, 1, 0); + cairo_rectangle (cr_region, 0, 10, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_rgb (cr_region, 0, 0, 1); + cairo_rectangle (cr_region, 10, 10, 10, 10); + cairo_fill (cr_region); + + cairo_set_source_surface (cr, cairo_get_target (cr_region), 20, 20); + cairo_destroy (cr_region); + cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT); + cairo_paint (cr); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (subsurface_similar_repeat, + "Tests source clipping through an intermediate with repeat", + "subsurface, repeat", /* keywords */ + NULL, /* requirements */ + 60, 60, + NULL, draw) diff --git a/test/subsurface-similar-repeat.ref.png b/test/subsurface-similar-repeat.ref.png Binary files differnew file mode 100644 index 00000000..c37e22e3 --- /dev/null +++ b/test/subsurface-similar-repeat.ref.png diff --git a/test/subsurface.c b/test/subsurface.c new file mode 100644 index 00000000..f3258885 --- /dev/null +++ b/test/subsurface.c @@ -0,0 +1,80 @@ +/* + * Copyright 2009 Intel Corporation + * + * 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 + * Intel not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Intel makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * INTEL CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL INTEL CORPORATION 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@chris-wilson.co.uk> + */ + +#include "cairo-test.h" + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + cairo_surface_t *region[5]; + const char *text = "Cairo"; + int i; + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + cairo_set_source_rgb (cr, 0, 0, 0); + + for (i = 0; i < 5; i++) { + cairo_t *cr_region; + cairo_text_extents_t extents; + char buf[2] = { text[i], '\0' }; + + region[i] = cairo_surface_create_for_region (cairo_get_target (cr), + 20 * i, 0, 20, 20); + + cr_region = cairo_create (region[i]); + cairo_surface_destroy (region[i]); + + cairo_select_font_face (cr_region, "@cairo:", + CAIRO_FONT_WEIGHT_NORMAL, + CAIRO_FONT_SLANT_NORMAL); + cairo_set_font_size (cr_region, 20); + cairo_text_extents (cr_region, buf, &extents); + cairo_move_to (cr_region, + 10 - (extents.width/2 + extents.x_bearing), + 10 - (extents.height/2 + extents.y_bearing)); + cairo_show_text (cr_region, buf); + + region[i] = cairo_surface_reference (cairo_get_target (cr_region)); + cairo_destroy (cr_region); + } + + for (i = 0; i < 5; i++) { + cairo_set_source_surface (cr, region[5-i-1], 20 * i, 20); + cairo_paint_with_alpha (cr, .5); + } + + for (i = 0; i < 5; i++) + cairo_surface_destroy (region[i]); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (subsurface, + "Tests clipping of both source and destination using subsurfaces", + "subsurface", /* keywords */ + NULL, /* requirements */ + 100, 40, + NULL, draw) diff --git a/test/subsurface.ref.png b/test/subsurface.ref.png Binary files differnew file mode 100644 index 00000000..54fc0d01 --- /dev/null +++ b/test/subsurface.ref.png |