diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c index 4b79db965..3e3ca2814 100644 --- a/src/cairo-image-source.c +++ b/src/cairo-image-source.c @@ -1113,10 +1113,12 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, { cairo_surface_t *source, *clone, *proxy; cairo_rectangle_int_t limit; + cairo_rectangle_int_t src_limit; pixman_image_t *pixman_image; cairo_status_t status; cairo_extend_t extend; cairo_matrix_t *m, matrix; + double sx = 1.0, sy = 1.0; int tx = 0, ty = 0; TRACE ((stderr, "%s\n", __FUNCTION__)); @@ -1124,34 +1126,38 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, *ix = *iy = 0; source = _cairo_pattern_get_source (pattern, &limit); + src_limit = limit; extend = pattern->base.extend; if (_cairo_rectangle_contains_rectangle (&limit, sample)) extend = CAIRO_EXTEND_NONE; + if (extend == CAIRO_EXTEND_NONE) { if (! _cairo_rectangle_intersect (&limit, sample)) return _pixman_transparent_image (); + } - if (! _cairo_matrix_is_identity (&pattern->base.matrix)) { - double x1, y1, x2, y2; + if (! _cairo_matrix_is_identity (&pattern->base.matrix)) { + double x1, y1, x2, y2; - matrix = pattern->base.matrix; - status = cairo_matrix_invert (&matrix); - assert (status == CAIRO_STATUS_SUCCESS); + matrix = pattern->base.matrix; + status = cairo_matrix_invert (&matrix); + assert (status == CAIRO_STATUS_SUCCESS); - x1 = limit.x; - y1 = limit.y; - x2 = limit.x + limit.width; - y2 = limit.y + limit.height; + x1 = limit.x; + y1 = limit.y; + x2 = limit.x + limit.width; + y2 = limit.y + limit.height; - _cairo_matrix_transform_bounding_box (&matrix, - &x1, &y1, &x2, &y2, NULL); + _cairo_matrix_transform_bounding_box (&matrix, + &x1, &y1, &x2, &y2, NULL); - limit.x = floor (x1); - limit.y = floor (y1); - limit.width = ceil (x2) - limit.x; - limit.height = ceil (y2) - limit.y; - } + limit.x = floor (x1); + limit.y = floor (y1); + limit.width = ceil (x2) - limit.x; + limit.height = ceil (y2) - limit.y; + sx = (double)src_limit.width / limit.width; + sy = (double)src_limit.height / limit.height; } tx = limit.x; ty = limit.y; @@ -1183,7 +1189,9 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, cairo_matrix_translate (&matrix, tx, ty); m = &matrix; } else { - /* XXX extract scale factor for repeating patterns */ + cairo_matrix_init_scale (&matrix, sx, sy); + cairo_matrix_translate (&matrix, src_limit.x/sx, src_limit.y/sy); + m = &matrix; } /* Handle recursion by returning future reads from the current image */ @@ -1199,11 +1207,22 @@ done: pixman_image = pixman_image_ref (((cairo_image_surface_t *)clone)->pixman_image); cairo_surface_destroy (clone); - *ix = -limit.x; - *iy = -limit.y; - if (extend != CAIRO_EXTEND_NONE) { + if (extend == CAIRO_EXTEND_NONE) { + *ix = -limit.x; + *iy = -limit.y; + } else { + cairo_pattern_union_t tmp_pattern; + _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base); + matrix = pattern->base.matrix; + status = cairo_matrix_invert(&matrix); + assert (status == CAIRO_STATUS_SUCCESS); + cairo_matrix_translate (&matrix, src_limit.x, src_limit.y); + cairo_matrix_scale (&matrix, sx, sy); + status = cairo_matrix_invert(&matrix); + assert (status == CAIRO_STATUS_SUCCESS); + cairo_pattern_set_matrix (&tmp_pattern.base, &matrix); if (! _pixman_image_set_properties (pixman_image, - &pattern->base, extents, + &tmp_pattern.base, extents, ix, iy)) { pixman_image_unref (pixman_image); pixman_image= NULL; diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 9cb89e99f..3aafcb214 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -357,6 +357,7 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, /* The reference count and user_data array are unique to the copy. */ CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0); _cairo_user_data_array_init (&pattern->user_data); + cairo_list_init (&pattern->observers); return CAIRO_STATUS_SUCCESS; } @@ -396,6 +397,7 @@ _cairo_pattern_init_static_copy (cairo_pattern_t *pattern, CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0); _cairo_user_data_array_init (&pattern->user_data); + cairo_list_init (&pattern->observers); } cairo_status_t diff --git a/test/reference/record-replay-extend-pad.ref.png b/test/reference/record-replay-extend-pad.ref.png new file mode 100644 index 000000000..7acd8af49 Binary files /dev/null and b/test/reference/record-replay-extend-pad.ref.png differ diff --git a/test/reference/record-replay-extend-reflect.ref.png b/test/reference/record-replay-extend-reflect.ref.png new file mode 100644 index 000000000..de53e5ca4 Binary files /dev/null and b/test/reference/record-replay-extend-reflect.ref.png differ diff --git a/test/reference/record-replay-extend-repeat.ref.png b/test/reference/record-replay-extend-repeat.ref.png new file mode 100644 index 000000000..5a95d86f5 Binary files /dev/null and b/test/reference/record-replay-extend-repeat.ref.png differ