diff options
author | Carl Worth <cworth@cworth.org> | 2005-12-19 22:01:39 +0000 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2005-12-19 22:01:39 +0000 |
commit | 75b2fe93f09324b509630d86e0b01de830d853cf (patch) | |
tree | 02decfa71d780dae0c5921db6c9e87fab59adff6 /src | |
parent | 606d23b2874288c18f7373ffa47b0fb6b63b3451 (diff) |
Use _cairo_surface_paint rather than _cairo_surface_fill_rectangle as only the former is guaranteed to work with all backends.
Refine the comment describing this test surface.
Add new test surface for exercising cairo_meta_surface.
Simplify the image and test_fallback targets by not using create_for_data. Allow for NULL cleanup target functions. Add support for the test_meta_surface.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/cairo-surface.c | 15 | ||||
-rw-r--r-- | src/test-fallback-surface.c | 8 | ||||
-rw-r--r-- | src/test-meta-surface.c | 375 |
4 files changed, 395 insertions, 6 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 158751c2..ce3cd43f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,8 @@ libcairo_svg_sources = cairo-svg-surface.c endif if CAIRO_HAS_TEST_SURFACES -libcairo_test_sources = test-fallback-surface.c test-fallback-surface.h +libcairo_test_sources = test-fallback-surface.c test-fallback-surface.h \ + test-meta-surface.c test-meta-surface.h endif if CAIRO_HAS_XLIB_SURFACE diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 9062544c..e34cb6c1 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -223,6 +223,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other, { cairo_status_t status; cairo_surface_t *surface; + cairo_pattern_t *source; surface = _cairo_surface_create_similar_scratch (other, content, width, height); @@ -230,10 +231,18 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other, _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } + + source = _cairo_pattern_create_solid (color); + if (source->status) { + cairo_surface_destroy (surface); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t*) &_cairo_surface_nil; + } + + status = _cairo_surface_paint (surface, CAIRO_OPERATOR_SOURCE, source); + + cairo_pattern_destroy (source); - status = _cairo_surface_fill_rectangle (surface, - CAIRO_OPERATOR_SOURCE, color, - 0, 0, width, height); if (status) { cairo_surface_destroy (surface); _cairo_error (status); diff --git a/src/test-fallback-surface.c b/src/test-fallback-surface.c index b538668c..0d3f7412 100644 --- a/src/test-fallback-surface.c +++ b/src/test-fallback-surface.c @@ -38,8 +38,12 @@ * fallbacks. * * The defining feature of this backend is that it has as many NULL - * backend function entries as possible, (and it might be worth - * working to try to allow one or two more to be NULL as well). + * backend function entries as possible. The ones that aren't NULL are + * simply those that must be implemented to have working fallbacks. + * (Except for create_similar---fallbacks would work fine without + * that---I implemented it here in order to create as many surfaces as + * possible of type test_fallback_surface_t during the test suite + * run). * * It's possible that this code might serve as a good starting point * for someone working on bringing up a new backend, starting with the diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c new file mode 100644 index 00000000..3b1eabf6 --- /dev/null +++ b/src/test-meta-surface.c @@ -0,0 +1,375 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2005 Red Hat, Inc + * + * 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 Red Hat, Inc. + * + * Contributor(s): + * Carl Worth <cworth@cworth.org> + */ + +/* This isn't a "real" surface, but just something to be used by the + * test suite to help exercise the meta-surface paths in cairo. + * + * The defining feature of this backend is that it uses a meta surface + * to record all operations, and then replays everything to an image + * surface. + * + * It's possible that this code might serve as a good starting point + * for someone working on bringing up a new meta-surface-based + * backend. + */ + +#include "test-meta-surface.h" + +#include "cairoint.h" +#include "cairo-meta-surface-private.h" + +typedef struct _test_meta_surface { + cairo_surface_t base; + + /* This is a cairo_meta_surface to record all operations. */ + cairo_surface_t *meta; + + /* And this is a cairo_image_surface to hold the final result. */ + cairo_surface_t *image; + + cairo_bool_t image_reflects_meta; +} test_meta_surface_t; + +const cairo_private cairo_surface_backend_t test_meta_surface_backend; + +static cairo_int_status_t +_test_meta_surface_show_page (void *abstract_surface); + +cairo_surface_t * +_test_meta_surface_create (cairo_format_t format, + int width, + int height) +{ + test_meta_surface_t *surface; + + surface = malloc (sizeof (test_meta_surface_t)); + if (surface == NULL) + goto FAIL; + + _cairo_surface_init (&surface->base, &test_meta_surface_backend); + + surface->meta = _cairo_meta_surface_create (width, height); + if (cairo_surface_status (surface->meta)) + goto FAIL_CLEANUP_SURFACE; + + surface->image = cairo_image_surface_create (format, width, height); + if (cairo_surface_status (surface->image)) + goto FAIL_CLEANUP_META; + + surface->image_reflects_meta = FALSE; + + return &surface->base; + + FAIL_CLEANUP_META: + cairo_surface_destroy (surface->meta); + FAIL_CLEANUP_SURFACE: + free (surface); + FAIL: + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t*) &_cairo_surface_nil; +} + +cairo_surface_t * +_test_meta_surface_create_for_data (unsigned char *data, + cairo_format_t format, + int width, + int height, + int stride) +{ + test_meta_surface_t *surface; + cairo_surface_t *meta, *image; + + meta = _cairo_meta_surface_create (width, height); + if (cairo_surface_status (meta)) + return (cairo_surface_t*) &_cairo_surface_nil; + + image = cairo_image_surface_create_for_data (data, format, + width, height, stride); + if (cairo_surface_status (image)) { + cairo_surface_destroy (meta); + return (cairo_surface_t*) &_cairo_surface_nil; + } + + surface = malloc (sizeof (test_meta_surface_t)); + if (surface == NULL) { + cairo_surface_destroy (meta); + cairo_surface_destroy (image); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t*) &_cairo_surface_nil; + } + + _cairo_surface_init (&surface->base, &test_meta_surface_backend); + + surface->meta = meta; + surface->image = image; + surface->image_reflects_meta = FALSE; + + return &surface->base; +} + +static cairo_surface_t * +_test_meta_surface_create_similar (void *abstract_surface, + cairo_content_t content, + int width, + int height) +{ + assert (CAIRO_CONTENT_VALID (content)); + + return _test_meta_surface_create (_cairo_format_from_content (content), + width, height); +} + +static cairo_status_t +_test_meta_surface_finish (void *abstract_surface) +{ + test_meta_surface_t *surface = abstract_surface; + + cairo_surface_destroy (surface->meta); + cairo_surface_destroy (surface->image); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_test_meta_surface_acquire_source_image (void *abstract_surface, + cairo_image_surface_t **image_out, + void **image_extra) +{ + test_meta_surface_t *surface = abstract_surface; + + if (! surface->image_reflects_meta) + _test_meta_surface_show_page (abstract_surface); + + return _cairo_surface_acquire_source_image (surface->image, + image_out, image_extra); +} + +static void +_test_meta_surface_release_source_image (void *abstract_surface, + cairo_image_surface_t *image, + void *image_extra) +{ + test_meta_surface_t *surface = abstract_surface; + + _cairo_surface_release_source_image (surface->image, + image, image_extra); +} + +static cairo_int_status_t +_test_meta_surface_show_page (void *abstract_surface) +{ + test_meta_surface_t *surface = abstract_surface; + + if (surface->image_reflects_meta) + return CAIRO_STATUS_SUCCESS; + + _cairo_meta_surface_replay (surface->meta, surface->image); + + surface->image_reflects_meta = TRUE; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +_test_meta_surface_intersect_clip_path (void *abstract_surface, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) +{ + test_meta_surface_t *surface = abstract_surface; + + return _cairo_surface_intersect_clip_path (surface->meta, + path, fill_rule, + tolerance, antialias); +} + +static cairo_int_status_t +_test_meta_surface_get_extents (void *abstract_surface, + cairo_rectangle_t *rectangle) +{ + test_meta_surface_t *surface = abstract_surface; + + surface->image_reflects_meta = FALSE; + + return _cairo_surface_get_extents (surface->image, rectangle); +} + +static cairo_int_status_t +_test_meta_surface_paint (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source) +{ + test_meta_surface_t *surface = abstract_surface; + + surface->image_reflects_meta = FALSE; + + return _cairo_surface_paint (surface->meta, op, source); +} + +static cairo_int_status_t +_test_meta_surface_mask (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_pattern_t *mask) +{ + test_meta_surface_t *surface = abstract_surface; + + surface->image_reflects_meta = FALSE; + + return _cairo_surface_mask (surface->meta, op, source, mask); +} + +static cairo_int_status_t +_test_meta_surface_stroke (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) +{ + test_meta_surface_t *surface = abstract_surface; + + surface->image_reflects_meta = FALSE; + + return _cairo_surface_stroke (surface->meta, op, source, + path, style, + ctm, ctm_inverse, + tolerance, antialias); +} + +static cairo_int_status_t +_test_meta_surface_fill (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) +{ + test_meta_surface_t *surface = abstract_surface; + + surface->image_reflects_meta = FALSE; + + return _cairo_surface_fill (surface->meta, op, source, + path, fill_rule, + tolerance, antialias); +} + +static cairo_int_status_t +_test_meta_surface_show_glyphs (void *abstract_surface, + cairo_operator_t op, + cairo_pattern_t *source, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + test_meta_surface_t *surface = abstract_surface; + + surface->image_reflects_meta = FALSE; + + return _cairo_surface_show_glyphs (surface->meta, op, source, + glyphs, num_glyphs, + scaled_font); +} + +static cairo_surface_t * +_test_meta_surface_snapshot (void *abstract_other) +{ + test_meta_surface_t *other = abstract_other; + + /* XXX: Just making a snapshot of other->meta is what we really + * want. But this currently triggers a bug somewhere (the "mask" + * test from the test suite segfaults). + * + * For now, we'll create a new image surface and replay onto + * that. It would be tempting to replay into other->image and then + * return a snapshot of that, but that will cause the self-copy + * test to fail, (since our replay will be affected by a clip that + * should not have any effect on the use of the resulting snapshot + * as a source). + */ + +#if 0 + return _cairo_surface_snapshot (other->meta); +#else + cairo_rectangle_t extents; + cairo_surface_t *surface; + + _cairo_surface_get_extents (other->image, &extents); + + surface = cairo_surface_create_similar (other->image, + CAIRO_CONTENT_COLOR_ALPHA, + extents.width, + extents.height); + + _cairo_meta_surface_replay (other->meta, surface); + + return surface; +#endif +} + +const cairo_surface_backend_t test_meta_surface_backend = { + _test_meta_surface_create_similar, + _test_meta_surface_finish, + _test_meta_surface_acquire_source_image, + _test_meta_surface_release_source_image, + NULL, /* acquire_dest_image */ + NULL, /* release_dest_image */ + NULL, /* clone_similar */ + NULL, /* composite */ + NULL, /* fill_rectangles */ + NULL, /* composite_trapezoids */ + NULL, /* copy_page */ + _test_meta_surface_show_page, + NULL, /* set_clip_region */ + _test_meta_surface_intersect_clip_path, + _test_meta_surface_get_extents, + NULL, /* old_show_glyphs */ + NULL, /* get_font_options */ + NULL, /* flush */ + NULL, /* mark_dirty_rectangle */ + NULL, /* scaled_font_fini */ + NULL, /* scaled_glyph_fini */ + _test_meta_surface_paint, + _test_meta_surface_mask, + _test_meta_surface_stroke, + _test_meta_surface_fill, + _test_meta_surface_show_glyphs, + _test_meta_surface_snapshot +}; |