diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 08f23218f..9589b34c7 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -1159,29 +1159,43 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, } else { - /* Before we can clone, we must transform the rectangle to the - * coordinate space of the source surface. */ - if (! _cairo_matrix_is_identity (&attr->matrix)) { - double src_x = x; - double src_y = y; - double src_width = width; - double src_height = height; - double x2, y2; - cairo_bool_t is_tight; + /* If we're repeating, we just play it safe and clone the entire surface. */ + if (attr->extend == CAIRO_EXTEND_REPEAT) { + cairo_rectangle_int16_t extents; + status = _cairo_surface_get_extents (pattern->surface, &extents); + x = extents.x; + y = extents.y; + width = extents.width; + height = extents.height; + } else { + /* Otherwise, we first transform the rectangle to the + * coordinate space of the source surface so that we can + * clone only that portion of the surface that will be + * read. */ + if (! _cairo_matrix_is_identity (&attr->matrix)) { + double src_x = x; + double src_y = y; + double src_width = width; + double src_height = height; + double x2, y2; + cairo_bool_t is_tight; - _cairo_matrix_transform_bounding_box (&attr->matrix, &src_x, &src_y, - &src_width, &src_height, - &is_tight); - x2 = src_x + src_width; - y2 = src_y + src_height; - x = floor (src_x); - y = floor (src_y); - width = ceil (x2) - x; - height = ceil (y2) - y; + _cairo_matrix_transform_bounding_box (&attr->matrix, &src_x, &src_y, + &src_width, &src_height, + &is_tight); + x2 = src_x + src_width; + y2 = src_y + src_height; + x = floor (src_x); + y = floor (src_y); + width = ceil (x2) - x; + height = ceil (y2) - y; + } + x += tx; + y += ty; } status = _cairo_surface_clone_similar (dst, pattern->surface, - x+tx, y+ty, width, height, out); + x, y, width, height, out); } return status; diff --git a/src/cairoint.h b/src/cairoint.h index 2c5856d77..06fc8d40d 100755 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -720,6 +720,16 @@ struct _cairo_surface_backend { cairo_rectangle_int16_t *image_rect, void *image_extra); + /* Create a new surface (@clone_out) with the following + * characteristics: + * + * 1. It is as compatible as possible with @surface (in terms of + * efficiency) + * + * 2. It has the same size as @src + * + * 3. It has the same contents as @src within the given rectangle. + */ cairo_status_t (*clone_similar) (void *surface, cairo_surface_t *src,