diff options
Diffstat (limited to 'src/cairo-image-surface.c')
-rw-r--r-- | src/cairo-image-surface.c | 318 |
1 files changed, 130 insertions, 188 deletions
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index fcc832e..6082215 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -524,6 +524,11 @@ slim_hidden_def (cairo_image_surface_create_for_data); * Get a pointer to the data of the image surface, for direct * inspection or modification. * + * A call to cairo_surface_flush() is required before accessing the + * pixel data to ensure that all pending drawing operations are + * finished. A call to cairo_surface_mark_dirty() is required after + * the data is modified. + * * Return value: a pointer to the image data of this surface or %NULL * if @surface is not an image surface, or if cairo_surface_finish() * has been called. @@ -856,25 +861,6 @@ _cairo_image_surface_unset_clip_region (cairo_image_surface_t *surface) pixman_image_set_clip_region32 (surface->pixman_image, NULL); } -static double -_pixman_nearest_sample (double d) -{ - return ceil (d - .5); -} - -static cairo_bool_t -_nearest_sample (cairo_filter_t filter, double *tx, double *ty) -{ - if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST) { - *tx = _pixman_nearest_sample (*tx); - *ty = _pixman_nearest_sample (*ty); - } else { - if (*tx != floor (*tx) || *ty != floor (*ty)) - return FALSE; - } - return fabs (*tx) < PIXMAN_MAX_INT && fabs (*ty) < PIXMAN_MAX_INT; -} - #if HAS_ATOMIC_OPS static pixman_image_t *__pixman_transparent_image; static pixman_image_t *__pixman_black_image; @@ -1093,9 +1079,12 @@ _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern, pixman_image_t *pixman_image; pixman_gradient_stop_t pixman_stops_static[2]; pixman_gradient_stop_t *pixman_stops = pixman_stops_static; - cairo_matrix_t matrix = pattern->base.matrix; - double tx, ty; + pixman_transform_t pixman_transform; + cairo_matrix_t matrix; + cairo_circle_double_t extremes[2]; + pixman_point_fixed_t p1, p2; unsigned int i; + cairo_status_t status; if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) { pixman_stops = _cairo_malloc_ab (pattern->n_stops, @@ -1112,66 +1101,24 @@ _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern, pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short; } - if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern; - pixman_point_fixed_t p1, p2; - cairo_fixed_t xdim, ydim; - - xdim = fabs (linear->p2.x - linear->p1.x); - ydim = fabs (linear->p2.y - linear->p1.y); - - /* - * Transform the matrix to avoid overflow when converting between - * cairo_fixed_t and pixman_fixed_t (without incurring performance - * loss when the transformation is unnecessary). - * - * XXX: Consider converting out-of-range co-ordinates and transforms. - * Having a function to compute the required transformation to - * "normalize" a given bounding box would be generally useful - - * cf linear patterns, gradient patterns, surface patterns... - */ - if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT || - _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT) - { - double sf; + _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes); - if (xdim > ydim) - sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim); - else - sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim); - - p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf); - p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf); - p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf); - p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf); - - cairo_matrix_scale (&matrix, sf, sf); - } - else - { - p1.x = _cairo_fixed_to_16_16 (linear->p1.x); - p1.y = _cairo_fixed_to_16_16 (linear->p1.y); - p2.x = _cairo_fixed_to_16_16 (linear->p2.x); - p2.y = _cairo_fixed_to_16_16 (linear->p2.y); - } + p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x); + p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y); + p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x); + p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y); + if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) { pixman_image = pixman_image_create_linear_gradient (&p1, &p2, pixman_stops, pattern->n_stops); } else { - cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern; - pixman_point_fixed_t c1, c2; pixman_fixed_t r1, r2; - c1.x = _cairo_fixed_to_16_16 (radial->c1.x); - c1.y = _cairo_fixed_to_16_16 (radial->c1.y); - r1 = _cairo_fixed_to_16_16 (radial->r1); - - c2.x = _cairo_fixed_to_16_16 (radial->c2.x); - c2.y = _cairo_fixed_to_16_16 (radial->c2.y); - r2 = _cairo_fixed_to_16_16 (radial->r2); + r1 = _cairo_fixed_16_16_from_double (extremes[0].radius); + r2 = _cairo_fixed_16_16_from_double (extremes[1].radius); - pixman_image = pixman_image_create_radial_gradient (&c1, &c2, r1, r2, + pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2, pixman_stops, pattern->n_stops); } @@ -1182,49 +1129,19 @@ _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern, if (unlikely (pixman_image == NULL)) return NULL; - tx = pattern->base.matrix.x0; - ty = pattern->base.matrix.y0; - if (! _cairo_matrix_is_translation (&pattern->base.matrix) || - ! _nearest_sample (pattern->base.filter, &tx, &ty)) - { - pixman_transform_t pixman_transform; - - if (tx != 0. || ty != 0.) { - cairo_matrix_t m, inv; - cairo_status_t status; - double x, y; - - /* pixman also limits the [xy]_offset to 16 bits so evenly - * spread the bits between the two. - */ - inv = pattern->base.matrix; - status = cairo_matrix_invert (&inv); - assert (status == CAIRO_STATUS_SUCCESS); - - x = floor (inv.x0 / 2); - y = floor (inv.y0 / 2); - tx = -x; - ty = -y; - cairo_matrix_init_translate (&inv, x, y); - cairo_matrix_multiply (&m, &inv, &pattern->base.matrix); - _cairo_matrix_to_pixman_matrix (&m, &pixman_transform, - extents->x + extents->width/2., - extents->y + extents->height/2.); - } else { - tx = ty = 0; - _cairo_matrix_to_pixman_matrix (&pattern->base.matrix, - &pixman_transform, - extents->x + extents->width/2., - extents->y + extents->height/2.); - } - - if (! pixman_image_set_transform (pixman_image, &pixman_transform)) { + *ix = *iy = 0; + status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter, + extents->x + extents->width/2., + extents->y + extents->height/2., + &pixman_transform, ix, iy); + if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) { + if (unlikely (status != CAIRO_STATUS_SUCCESS) || + ! pixman_image_set_transform (pixman_image, &pixman_transform)) + { pixman_image_unref (pixman_image); return NULL; } } - *ix = tx; - *iy = ty; { pixman_repeat_t pixman_repeat; @@ -1322,13 +1239,15 @@ _pixel_to_solid (cairo_image_surface_t *image, int x, int y) case CAIRO_FORMAT_A1: pixel = *(uint8_t *) (image->data + y * image->stride + x/8); - return pixel & (1 << (x&7)) ? _pixman_white_image () : _pixman_transparent_image (); + return pixel & (1 << (x&7)) ? _pixman_black_image () : _pixman_transparent_image (); case CAIRO_FORMAT_A8: color.alpha = *(uint8_t *) (image->data + y * image->stride + x); color.alpha |= color.alpha << 8; if (color.alpha == 0) return _pixman_transparent_image (); + if (color.alpha == 0xffff) + return _pixman_black_image (); color.red = color.green = color.blue = 0; return pixman_image_create_solid_fill (&color); @@ -1368,16 +1287,17 @@ static pixman_image_t * _pixman_image_for_surface (const cairo_surface_pattern_t *pattern, cairo_bool_t is_mask, const cairo_rectangle_int_t *extents, + cairo_matrix_t *dst_device_transform, int *ix, int *iy) { + pixman_transform_t pixman_transform; pixman_image_t *pixman_image; + cairo_matrix_t m; cairo_rectangle_int_t sample; cairo_extend_t extend; cairo_filter_t filter; - double tx, ty; - - tx = pattern->base.matrix.x0; - ty = pattern->base.matrix.y0; + cairo_status_t status; + cairo_bool_t undo_src_transform = FALSE; extend = pattern->base.extend; filter = sampled_area (pattern, extents, &sample); @@ -1420,12 +1340,11 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern, } /* avoid allocating a 'pattern' image if we can reuse the original */ + *ix = *iy = 0; if (extend == CAIRO_EXTEND_NONE && - _cairo_matrix_is_translation (&pattern->base.matrix) && - _nearest_sample (filter, &tx, &ty)) + _cairo_matrix_is_pixman_translation (&pattern->base.matrix, + filter, ix, iy)) { - *ix = tx; - *iy = ty; return pixman_image_ref (source->pixman_image); } @@ -1462,12 +1381,12 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern, } } + *ix = sub->extents.x; + *iy = sub->extents.y; if (is_contained && - _cairo_matrix_is_translation (&pattern->base.matrix) && - _nearest_sample (filter, &tx, &ty)) + _cairo_matrix_is_pixman_translation (&pattern->base.matrix, + filter, ix, iy)) { - *ix = tx + sub->extents.x; - *iy = ty + sub->extents.y; return pixman_image_ref (source->pixman_image); } @@ -1484,13 +1403,15 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern, } } + *ix = *iy = 0; + if (pixman_image == NULL) { struct acquire_source_cleanup *cleanup; cairo_image_surface_t *image; void *extra; cairo_status_t status; - status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra); + status = _cairo_surface_acquire_source_image_transformed (pattern->surface, dst_device_transform, &image, &extra); if (unlikely (status)) return NULL; @@ -1536,54 +1457,36 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern, cleanup->image_extra = extra; pixman_image_set_destroy_function (pixman_image, _acquire_source_cleanup, cleanup); + undo_src_transform = TRUE; } - if (! _cairo_matrix_is_translation (&pattern->base.matrix) || - ! _nearest_sample (filter, &tx, &ty)) - { - pixman_transform_t pixman_transform; - cairo_matrix_t m; - - m = pattern->base.matrix; - if (m.x0 != 0. || m.y0 != 0.) { - cairo_matrix_t inv; - cairo_status_t status; - double x, y; - - /* pixman also limits the [xy]_offset to 16 bits so evenly - * spread the bits between the two. - */ - inv = m; - status = cairo_matrix_invert (&inv); - assert (status == CAIRO_STATUS_SUCCESS); - - x = floor (inv.x0 / 2); - y = floor (inv.y0 / 2); - tx = -x; - ty = -y; - cairo_matrix_init_translate (&inv, x, y); - cairo_matrix_multiply (&m, &inv, &m); - } else { - tx = ty = 0; - } + m = pattern->base.matrix; + if (undo_src_transform) { + cairo_matrix_t sm; - _cairo_matrix_to_pixman_matrix (&m, &pixman_transform, - extents->x + extents->width/2., - extents->y + extents->height/2.); - if (! pixman_image_set_transform (pixman_image, &pixman_transform)) { - pixman_image_unref (pixman_image); - return NULL; - } + cairo_matrix_init_scale (&sm, + dst_device_transform->xx, + dst_device_transform->yy); + cairo_matrix_multiply (&m, &m, &sm); } - *ix = tx; - *iy = ty; - if (_cairo_matrix_has_unity_scale (&pattern->base.matrix) && - tx == pattern->base.matrix.x0 && - ty == pattern->base.matrix.y0) + status = _cairo_matrix_to_pixman_matrix_offset (&m, filter, + extents->x + extents->width/2., + extents->y + extents->height/2., + &pixman_transform, ix, iy); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + /* If the transform is an identity, we don't need to set it + * and we can use any filtering, so choose the fastest one. */ pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0); } + else if (unlikely (status != CAIRO_STATUS_SUCCESS || + ! pixman_image_set_transform (pixman_image, + &pixman_transform))) + { + pixman_image_unref (pixman_image); + return NULL; + } else { pixman_filter_t pixman_filter; @@ -1649,6 +1552,7 @@ static pixman_image_t * _pixman_image_for_pattern (const cairo_pattern_t *pattern, cairo_bool_t is_mask, const cairo_rectangle_int_t *extents, + cairo_matrix_t *dst_device_transform, int *tx, int *ty) { *tx = *ty = 0; @@ -1669,7 +1573,32 @@ _pixman_image_for_pattern (const cairo_pattern_t *pattern, case CAIRO_PATTERN_TYPE_SURFACE: return _pixman_image_for_surface ((const cairo_surface_pattern_t *) pattern, - is_mask, extents, tx, ty); + is_mask, extents, dst_device_transform, tx, ty); + + case CAIRO_PATTERN_TYPE_MESH: { + cairo_surface_t *image; + pixman_image_t *r; + void * data; + int width, height, stride; + + *tx = -extents->x; + *ty = -extents->y; + width = extents->width; + height = extents->height; + + image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); + if (unlikely (image->status)) + return NULL; + + stride = cairo_image_surface_get_stride (image); + data = cairo_image_surface_get_data (image); + + _cairo_mesh_pattern_rasterize ((cairo_mesh_pattern_t *) pattern, + data, width, height, stride, *tx, *ty); + r = pixman_image_ref (((cairo_image_surface_t *)image)->pixman_image); + cairo_surface_destroy (image); + return r; + } } } @@ -1907,6 +1836,7 @@ typedef cairo_status_t const cairo_pattern_t *src, int dst_x, int dst_y, + cairo_matrix_t *dst_device_transform, const cairo_rectangle_int_t *extents, cairo_region_t *clip_region); @@ -1958,6 +1888,7 @@ _create_composite_mask_pattern (cairo_clip_t *clip, mask, PIXMAN_a8, CAIRO_OPERATOR_ADD, NULL, extents->x, extents->y, + &dst->base.device_transform, extents, NULL); if (unlikely (status)) { pixman_image_unref (mask); @@ -2034,7 +1965,7 @@ _clip_and_composite_with_mask (cairo_clip_t *clip, pixman_image_t *src; int src_x, src_y; - src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, extents, &dst->base.device_transform, &src_x, &src_y); if (unlikely (src == NULL)) { pixman_image_unref (mask); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2082,6 +2013,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, tmp, dst->pixman_format, CAIRO_OPERATOR_ADD, NULL, extents->x, extents->y, + &dst->base.device_transform, extents, NULL); } else { /* Initialize the temporary surface from the destination surface */ @@ -2098,6 +2030,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, tmp, dst->pixman_format, op, src, extents->x, extents->y, + &dst->base.device_transform, extents, NULL); } if (unlikely (status)) @@ -2181,6 +2114,7 @@ _clip_and_composite_source (cairo_clip_t *clip, dst->pixman_image, dst->pixman_format, CAIRO_OPERATOR_SOURCE, NULL, extents->x, extents->y, + &dst->base.device_transform, extents, NULL); if (unlikely (status)) return status; @@ -2196,7 +2130,7 @@ _clip_and_composite_source (cairo_clip_t *clip, if (unlikely (mask == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, extents, &dst->base.device_transform, &src_x, &src_y); if (unlikely (src == NULL)) { pixman_image_unref (mask); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2317,6 +2251,7 @@ _clip_and_composite (cairo_image_surface_t *dst, dst->pixman_image, dst->pixman_format, op, src, 0, 0, + &dst->base.device_transform, &extents->bounded, clip_region); } @@ -2434,6 +2369,7 @@ _composite_traps (void *closure, const cairo_pattern_t *pattern, int dst_x, int dst_y, + cairo_matrix_t *dst_device_transform, const cairo_rectangle_int_t *extents, cairo_region_t *clip_region) { @@ -2459,7 +2395,7 @@ _composite_traps (void *closure, return CAIRO_STATUS_SUCCESS; } - src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2866,7 +2802,7 @@ _composite_unaligned_boxes (cairo_image_surface_t *dst, if (unlikely (status)) goto CLEANUP; - src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &dst->base.device_transform, &src_x, &src_y); if (unlikely (src == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP; @@ -2983,7 +2919,7 @@ _composite_boxes (cairo_image_surface_t *dst, } if (pattern != NULL) { - src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &dst->base.device_transform, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } else { @@ -3320,6 +3256,7 @@ _composite_mask (void *closure, const cairo_pattern_t *src_pattern, int dst_x, int dst_y, + cairo_matrix_t *dst_device_transform, const cairo_rectangle_int_t *extents, cairo_region_t *clip_region) { @@ -3329,11 +3266,11 @@ _composite_mask (void *closure, int mask_x = 0, mask_y = 0; if (src_pattern != NULL) { - src = _pixman_image_for_pattern (src_pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (src_pattern, FALSE, extents, dst_device_transform, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - mask = _pixman_image_for_pattern (mask_pattern, TRUE, extents, &mask_x, &mask_y); + mask = _pixman_image_for_pattern (mask_pattern, TRUE, extents, dst_device_transform, &mask_x, &mask_y); if (unlikely (mask == NULL)) { pixman_image_unref (src); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3342,7 +3279,7 @@ _composite_mask (void *closure, if (mask_pattern->has_component_alpha) pixman_image_set_component_alpha (mask, TRUE); } else { - src = _pixman_image_for_pattern (mask_pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (mask_pattern, FALSE, extents, dst_device_transform, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -3418,6 +3355,7 @@ _composite_spans (void *closure, const cairo_pattern_t *pattern, int dst_x, int dst_y, + cairo_matrix_t *dst_device_transform, const cairo_rectangle_int_t *extents, cairo_region_t *clip_region) { @@ -3501,7 +3439,7 @@ _composite_spans (void *closure, pixman_image_t *src; int src_x, src_y; - src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y); if (unlikely (src == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_RENDERER; @@ -3635,7 +3573,7 @@ _cairo_image_surface_stroke (void *abstract_surface, } status = CAIRO_INT_STATUS_UNSUPPORTED; - if (path->is_rectilinear) { + if (_cairo_path_fixed_stroke_is_rectilinear (path)) { cairo_boxes_t boxes; _cairo_boxes_init (&boxes); @@ -3657,8 +3595,7 @@ _cairo_image_surface_stroke (void *abstract_surface, if (status == CAIRO_INT_STATUS_UNSUPPORTED) { cairo_polygon_t polygon; - _cairo_polygon_init (&polygon); - _cairo_polygon_limit (&polygon, clip_boxes, num_boxes); + _cairo_polygon_init (&polygon, clip_boxes, num_boxes); status = _cairo_path_fixed_stroke_to_polygon (path, style, @@ -3735,7 +3672,7 @@ _cairo_image_surface_fill (void *abstract_surface, return status; } - if (_cairo_path_fixed_is_rectilinear_fill (path)) { + if (_cairo_path_fixed_fill_is_rectilinear (path)) { cairo_boxes_t boxes; _cairo_boxes_init (&boxes); @@ -3754,10 +3691,9 @@ _cairo_image_surface_fill (void *abstract_surface, } else { cairo_polygon_t polygon; - assert (! path->is_empty_fill); + assert (! _cairo_path_fixed_fill_is_empty (path)); - _cairo_polygon_init (&polygon); - _cairo_polygon_limit (&polygon, clip_boxes, num_boxes); + _cairo_polygon_init (&polygon, clip_boxes, num_boxes); status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon); if (likely (status == CAIRO_STATUS_SUCCESS)) { @@ -3792,6 +3728,7 @@ _composite_glyphs_via_mask (void *closure, const cairo_pattern_t *pattern, int dst_x, int dst_y, + cairo_matrix_t *dst_device_transform, const cairo_rectangle_int_t *extents, cairo_region_t *clip_region) { @@ -3807,7 +3744,7 @@ _composite_glyphs_via_mask (void *closure, int src_x, src_y; int i; - src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3928,6 +3865,7 @@ _composite_glyphs (void *closure, const cairo_pattern_t *pattern, int dst_x, int dst_y, + cairo_matrix_t *dst_device_transform, const cairo_rectangle_int_t *extents, cairo_region_t *clip_region) { @@ -3940,7 +3878,7 @@ _composite_glyphs (void *closure, int i; if (pattern != NULL) { - src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y); + src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y); src_x -= dst_x; src_y -= dst_y; } else { @@ -4049,8 +3987,10 @@ _cairo_image_surface_glyphs (void *abstract_surface, if (clip != NULL && extents.is_bounded) { clip = _cairo_clip_init_copy (&local_clip, clip); status = _cairo_clip_rectangle (clip, &extents.bounded); - if (unlikely (status)) + if (unlikely (status)) { + _cairo_clip_fini (&local_clip); return status; + } have_clip = TRUE; } @@ -4092,6 +4032,7 @@ _cairo_image_surface_get_font_options (void *abstract_surface, _cairo_font_options_init_default (options); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); + _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON); } /* legacy interface kept for compatibility until surface-fallback is removed */ @@ -4204,7 +4145,7 @@ _cairo_image_surface_composite (cairo_operator_t op, extents.is_bounded = _cairo_operator_bounded_by_either (op); - src = _pixman_image_for_pattern (src_pattern, FALSE, &extents.source, &src_offset_x, &src_offset_y); + src = _pixman_image_for_pattern (src_pattern, FALSE, &extents.source, &dst->base.device_transform, &src_offset_x, &src_offset_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -4213,7 +4154,7 @@ _cairo_image_surface_composite (cairo_operator_t op, pixman_image_t *mask; int mask_offset_x, mask_offset_y; - mask = _pixman_image_for_pattern (mask_pattern, TRUE, &extents.mask, &mask_offset_x, &mask_offset_y); + mask = _pixman_image_for_pattern (mask_pattern, TRUE, &extents.mask, &dst->base.device_transform, &mask_offset_x, &mask_offset_y); if (unlikely (mask == NULL)) { pixman_image_unref (src); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -4378,6 +4319,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, op, &source_pattern.base, 0, 0, + &dst->base.device_transform, &extents.bounded, clip_region); @@ -4482,7 +4424,7 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer) return status; } - src = _pixman_image_for_pattern (renderer->pattern, FALSE, &rects->bounded, &src_x, &src_y); + src = _pixman_image_for_pattern (renderer->pattern, FALSE, &rects->bounded, &renderer->dst->base.device_transform, &src_x, &src_y); if (src == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); |