summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2010-11-21 23:25:21 +1030
committerAdrian Johnson <ajohnson@redneon.com>2010-11-28 03:38:29 +1030
commit59661f8af428b88125db033867d662e9393d0a41 (patch)
tree6b9318821d561e50a53ed1203b5220ed7dd889ef
parent063a3894d7ed98ba36f416a285acc88c50d3bb34 (diff)
Fix fallback-resolution test
The recording surface source image painted onto fallback images always had the resolution 72ppi instead of the fallback resolution of the target surface. Fix this by passing adding a new acquire_source_image_transformed backend function for the recording surface to use and passing the target device transform through to the recording surface when the image is acquired. Based on Carl Worth's experimental acquired_source_image_transformed branch. https://bugs.freedesktop.org/show_bug.cgi?id=24692
-rw-r--r--src/cairo-image-surface.c57
-rw-r--r--src/cairo-recording-surface.c32
-rw-r--r--src/cairo-surface.c27
-rw-r--r--src/cairoint.h12
4 files changed, 106 insertions, 22 deletions
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 09248f89e..9c35d7d24 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1368,6 +1368,7 @@ 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_image_t *pixman_image;
@@ -1375,6 +1376,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
cairo_extend_t extend;
cairo_filter_t filter;
double tx, ty;
+ cairo_bool_t undo_src_transform = FALSE;
tx = pattern->base.matrix.x0;
ty = pattern->base.matrix.y0;
@@ -1490,7 +1492,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
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,6 +1538,7 @@ _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) ||
@@ -1545,6 +1548,15 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
cairo_matrix_t m;
m = pattern->base.matrix;
+ if (undo_src_transform) {
+ cairo_matrix_t sm;
+
+ cairo_matrix_init_scale (&sm,
+ dst_device_transform->xx,
+ dst_device_transform->yy);
+ cairo_matrix_multiply (&m, &m, &sm);
+ }
+
if (m.x0 != 0. || m.y0 != 0.) {
cairo_matrix_t inv;
cairo_status_t status;
@@ -1649,6 +1661,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 +1682,7 @@ _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);
}
}
@@ -1907,6 +1920,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 +1972,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 +2049,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 +2097,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 +2114,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 +2198,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 +2214,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 +2335,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 +2453,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 +2479,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);
@@ -2860,7 +2880,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;
@@ -2977,7 +2997,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 {
@@ -3314,6 +3334,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)
{
@@ -3323,11 +3344,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);
@@ -3336,7 +3357,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);
}
@@ -3412,6 +3433,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)
{
@@ -3495,7 +3517,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;
@@ -3786,6 +3808,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)
{
@@ -3801,7 +3824,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);
@@ -3922,6 +3945,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)
{
@@ -3934,7 +3958,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 {
@@ -4201,7 +4225,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);
@@ -4210,7 +4234,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);
@@ -4375,6 +4399,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
op,
&source_pattern.base,
0, 0,
+ &dst->base.device_transform,
&extents.bounded,
clip_region);
@@ -4479,7 +4504,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);
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 0ac938b64..3e4dd0cce 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -249,13 +249,16 @@ _cairo_recording_surface_finish (void *abstract_surface)
}
static cairo_status_t
-_cairo_recording_surface_acquire_source_image (void *abstract_surface,
- cairo_image_surface_t **image_out,
- void **image_extra)
+_cairo_recording_surface_acquire_source_image_transformed (void *abstract_surface,
+ cairo_matrix_t *device_transform,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
{
cairo_status_t status;
cairo_recording_surface_t *surface = abstract_surface;
cairo_surface_t *image;
+ double width;
+ double height;
image = _cairo_surface_has_snapshot (&surface->base,
&_cairo_image_surface_backend);
@@ -265,9 +268,10 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+ width = surface->extents.width * device_transform->xx;
+ height = surface->extents.height * device_transform->yy;
image = _cairo_image_surface_create_with_content (surface->content,
- surface->extents.width,
- surface->extents.height);
+ width, height);
if (unlikely (image->status))
return image->status;
@@ -275,6 +279,8 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface,
-surface->extents.x,
-surface->extents.y);
+ _cairo_surface_set_device_scale (image,
+ device_transform->xx, device_transform->yy);
status = _cairo_recording_surface_replay (&surface->base, image);
if (unlikely (status)) {
cairo_surface_destroy (image);
@@ -288,6 +294,19 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_status_t
+_cairo_recording_surface_acquire_source_image (void *abstract_surface,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
+{
+ cairo_matrix_t identity;
+
+ cairo_matrix_init_identity (&identity);
+
+ return _cairo_recording_surface_acquire_source_image_transformed (
+ abstract_surface, &identity, image_out, image_extra);
+}
+
static void
_cairo_recording_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
@@ -729,7 +748,8 @@ static const cairo_surface_backend_t cairo_recording_surface_backend = {
NULL, /* can_repaint_solid_pattern_surface */
_cairo_recording_surface_has_show_text_glyphs,
- _cairo_recording_surface_show_text_glyphs
+ _cairo_recording_surface_show_text_glyphs,
+ _cairo_recording_surface_acquire_source_image_transformed
};
cairo_int_status_t
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 76f644716..ea9b0fe41 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1458,6 +1458,33 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+cairo_status_t
+_cairo_surface_acquire_source_image_transformed (cairo_surface_t *surface,
+ cairo_matrix_t *device_transform,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
+{
+ cairo_status_t status;
+
+ if (surface->status)
+ return surface->status;
+
+ assert (!surface->finished);
+
+ if (surface->backend->acquire_source_image_transformed == NULL)
+ return _cairo_surface_acquire_source_image (surface,
+ image_out, image_extra);
+
+ status = surface->backend->acquire_source_image_transformed (surface, device_transform,
+ image_out, image_extra);
+ if (unlikely (status))
+ return _cairo_surface_set_error (surface, status);
+
+ _cairo_debug_check_image_surface_is_defined (&(*image_out)->base);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
/**
* _cairo_surface_release_source_image:
* @surface: a #cairo_surface_t
diff --git a/src/cairoint.h b/src/cairoint.h
index cf0d459a9..f2c2e0f32 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -856,6 +856,12 @@ struct _cairo_surface_backend {
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
cairo_clip_t *clip);
+
+ cairo_warn cairo_status_t
+ (*acquire_source_image_transformed) (void *abstract_surface,
+ cairo_matrix_t *device_transform,
+ cairo_image_surface_t **image_out,
+ void **image_extra);
};
#include "cairo-surface-private.h"
@@ -1760,6 +1766,12 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
cairo_image_surface_t **image_out,
void **image_extra);
+cairo_private cairo_status_t
+_cairo_surface_acquire_source_image_transformed (cairo_surface_t *surface,
+ cairo_matrix_t *device_trasnform,
+ cairo_image_surface_t **image_out,
+ void **image_extra);
+
cairo_private void
_cairo_surface_release_source_image (cairo_surface_t *surface,
cairo_image_surface_t *image,