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.
This commit is contained in:
Behdad Esfahbod 2007-02-21 18:16:34 -05:00
parent 81935bb131
commit 5562050bcf
4 changed files with 59 additions and 5 deletions

View file

@ -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;

View file

@ -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 \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 KiB

After

Width:  |  Height:  |  Size: 281 KiB

View file

@ -3,15 +3,13 @@
#include <stdio.h>
#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
};