From 5562050bcf68923986b597f3aca1e285a466fa6c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 21 Feb 2007 18:16:34 -0500 Subject: [PATCH] Support CAIRO_EXTEND_REFLECT on surface patterns We do this through a hack, that is, we make _cairo_pattern_acquire_surface to return a surface that has four copies of the original surface painted such that this image can be simply repeated to get the effect of reflecting the original surface. This fixes the formerly XFAIL test extend-reflect. --- src/cairo-pattern.c | 58 +++++++++++++++++++++++++++++++++++- test/Makefile.am | 2 +- test/extend-reflect-ref.png | Bin 287611 -> 287611 bytes test/extend-reflect.c | 4 +-- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 0c428ba9d..c69528369 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -1300,6 +1300,60 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, ty = 0; } + /* XXX: Hack: + * + * The way we currently support CAIRO_EXTEND_REFLECT is to create + * an image twice bigger on each side, and create a pattern of four + * images such that the new image, when repeated, has the same effect + * of reflecting the original pattern. + * + * This is because the reflect support in pixman is broken and we + * pass repeat instead of reflect to pixman. See + * _cairo_image_surface_set_attributes() for that. + */ + if (attr->extend == CAIRO_EXTEND_REFLECT) { + cairo_t *cr; + int w,h; + + cairo_rectangle_int16_t extents; + status = _cairo_surface_get_extents (pattern->surface, &extents); + if (status) + return status; + + attr->extend = CAIRO_EXTEND_REPEAT; + + x = extents.x; + y = extents.y; + w = 2 * extents.width; + h = 2 * extents.height; + + *out = cairo_surface_create_similar (dst, dst->content, w, h); + if (!*out) + return CAIRO_STATUS_NO_MEMORY; + + cr = cairo_create (*out); + + cairo_set_source_surface (cr, pattern->surface, -x, -y); + cairo_paint (cr); + + cairo_scale (cr, -1, +1); + cairo_set_source_surface (cr, pattern->surface, x-w, -y); + cairo_paint (cr); + + cairo_scale (cr, +1, -1); + cairo_set_source_surface (cr, pattern->surface, x-w, y-h); + cairo_paint (cr); + + cairo_scale (cr, -1, +1); + cairo_set_source_surface (cr, pattern->surface, -x, y-h); + cairo_paint (cr); + + status = cairo_status (cr); + cairo_destroy (cr); + + return status; + } + if (_cairo_surface_is_image (dst)) { cairo_image_surface_t *image; @@ -1321,7 +1375,9 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, return status; /* If we're repeating, we just play it safe and clone the entire surface. */ - if (attr->extend == CAIRO_EXTEND_REPEAT) { + /* If requested width and height are -1, clone the entire surface. + * This is relied on in the svg backend. */ + if (attr->extend == CAIRO_EXTEND_REPEAT || (width == -1 && height == -1)) { x = extents.x; y = extents.y; width = extents.width; diff --git a/test/Makefile.am b/test/Makefile.am index 3382cf4fb..0ce55aa00 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -220,6 +220,7 @@ device-offset-ref.png \ device-offset-rgb24-ref.png \ device-offset-positive-ref.png \ device-offset-positive-rgb24-ref.png \ +extend-reflect-ref.png \ fill-and-stroke-ref.png \ fill-and-stroke-rgb24-ref.png \ fill-and-stroke-ps-argb32-ref.png \ @@ -358,7 +359,6 @@ zero-alpha-ref.png XFAIL_TESTS = \ a8-mask \ big-trap \ -extend-reflect \ filter-nearest-offset \ long-lines \ self-intersecting \ diff --git a/test/extend-reflect-ref.png b/test/extend-reflect-ref.png index 7645362dd636ec9ce5ca21b52332de3b6905b599..6e22d5d1a7846c34df86c55e9517262c7766874e 100644 GIT binary patch delta 32 ocmex;Oz`(H!3p;4qOxq4xNdngy0yA7wz@I3x-oBcV=+wz0N57`b^rhX delta 32 ocmex;Oz`(H!3p;4BAR-!;jfDt-CErkTiuvi-I%w!v6v #define SIZE 400 -#define OFFSET 50 const char png_filename[] = "romedalen.png"; static cairo_test_draw_function_t draw; cairo_test_t test = { "extend-reflect", - "Test CAIRO_EXTEND_REFLECT for surface patterns" - "\nCAIRO_EXTEND_REFLECT code is broken and corrupts memory", + "Test CAIRO_EXTEND_REFLECT for surface patterns", SIZE, SIZE, draw };