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 7645362dd..6e22d5d1a 100644 Binary files a/test/extend-reflect-ref.png and b/test/extend-reflect-ref.png differ diff --git a/test/extend-reflect.c b/test/extend-reflect.c index 297c475f6..3d36bb25d 100644 --- a/test/extend-reflect.c +++ b/test/extend-reflect.c @@ -3,15 +3,13 @@ #include #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 };