[cairo] Bug with fallback resolution of groups

Carl Worth cworth at cworth.org
Wed May 21 12:19:30 PDT 2008


On Wed, 21 May 2008 10:50:32 -0700, Carl Worth wrote:
> So we just need to get a single scale factor set somewhere. The trick
> is finding out exactly where to set it. Getting it from the
> destination surface to the intermediate surface in
> _acquire_source_image looks hard. Maybe we can do something at the
> time of the creation of the meta-surface for the group.

Meta-surface creation time is no good. We don't have the desired
fallback resolution value until replay time.

I started with an attempt to get a scale value to
_acquire_source_image. To avoid the pain of updating all backends that
implement this, I first did just a new
_acquire_source_image_transformed. It's currently accepting an entire
matrix, but it really should just be accepting a couple of scale
values.

I've only implemented this in the meta-surface so far. Perhaps it's
the only place needed, but I haven't thought hard yet to convince
myself that other backends couldn't have similar bugs. Hopefully this
bug really is unique to recording.

Also, I've only fixed up one call site to call the new
_acquire_source_image_transformed. It's possible there are similar
bugs that should be fixed at other call sites.

So that should be plenty of disclaimers to let you know this patch is
totally inadequate. If you're not still convinced, let me also point
out that this patch doesn't even work. The intermediate group's image
is rendered at the correct resolution now, but it's then being scaled
up again, (apparently when composited with the final image surface
that also has the appropriate device_transform set).

So this is all quite messy. I'm not even sure I'm on the right path
for fixing this yet, but I thought I'd at least share what I've got so
far.

Patch attached and in the acquire_source_image_transformed branch of
my personal repository.

-Carl

-------------- next part --------------
From ddcd6781a24463df5a1f25cd5ffdbce47f35cf2f Mon Sep 17 00:00:00 2001
From: Carl Worth <cworth at cworth.org>
Date: Wed, 21 May 2008 12:06:37 -0700
Subject: [PATCH] BUGGY: Add surface_backend->acquire_source_image_transformed

This is an initial attempt at addressing the recently noticed
fallback-resolution bug. It isn't working correctly yet.

I'm just committing so that behdad can see what I'm up to.
---
 src/cairo-meta-surface.c |   40 ++++++++++++++++++++++++++++++++++------
 src/cairo-pattern.c      |    9 ++++++---
 src/cairo-surface.c      |   20 ++++++++++++++++++++
 src/cairoint.h           |   12 ++++++++++++
 4 files changed, 72 insertions(+), 9 deletions(-)

diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 6abb29a..f652de7 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -182,17 +182,26 @@ _cairo_meta_surface_finish (void *abstract_surface)
 }
 
 static cairo_status_t
-_cairo_meta_surface_acquire_source_image (void			 *abstract_surface,
-					  cairo_image_surface_t	**image_out,
-					  void			**image_extra)
+_cairo_meta_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_meta_surface_t *surface = abstract_surface;
     cairo_surface_t *image;
+    double width = surface->width_pixels;
+    double height = surface->height_pixels;
+
+    cairo_matrix_transform_distance (device_transform, &width, &height);
 
     image = _cairo_image_surface_create_with_content (surface->content,
-						      surface->width_pixels,
-						      surface->height_pixels);
+						      ceil (width),
+						      ceil (height));
+
+    _cairo_surface_set_device_scale (image,
+				     device_transform->xx, device_transform->yy);
 
     status = _cairo_meta_surface_replay (&surface->base, image);
     if (status) {
@@ -206,6 +215,19 @@ _cairo_meta_surface_acquire_source_image (void			 *abstract_surface,
     return status;
 }
 
+static cairo_status_t
+_cairo_meta_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_meta_surface_acquire_source_image_transformed (
+	abstract_surface, &identity, image_out, image_extra);
+}
+
 static void
 _cairo_meta_surface_release_source_image (void			*abstract_surface,
 					  cairo_image_surface_t	*image,
@@ -629,7 +651,13 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
     _cairo_meta_surface_fill,
     _cairo_meta_surface_show_glyphs,
 
-    _cairo_meta_surface_snapshot
+    _cairo_meta_surface_snapshot,
+
+    NULL, /* is_similar */
+    NULL, /* reset */
+    NULL, /* fill_stroke */
+
+    _cairo_meta_surface_acquire_source_image_transformed
 };
 
 static cairo_path_fixed_t *
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index c0bfbaf..1975daf 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1702,9 +1702,12 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
     {
 	cairo_image_surface_t *image;
 
-	status = _cairo_surface_acquire_source_image (pattern->surface,
-						      &image,
-						      &attr->extra);
+	status = _cairo_surface_acquire_source_image_transformed (
+	    pattern->surface,
+	    &dst->device_transform,
+	    &image,
+	    &attr->extra);
+
 	if (status)
 	    return status;
 
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index ba39b9b..833737c 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -968,6 +968,26 @@ _cairo_surface_acquire_source_image (cairo_surface_t         *surface,
 						    image_out, image_extra));
 }
 
+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)
+{
+    assert (!surface->finished);
+
+    if (surface->status)
+	return surface->status;
+
+    if (surface->backend->acquire_source_image_transformed == NULL)
+	return _cairo_surface_acquire_source_image (surface,
+						    image_out, image_extra);
+
+    return _cairo_surface_set_error (surface,
+	    surface->backend->acquire_source_image_transformed (
+		surface, device_transform, image_out, image_extra));
+}
+
 /**
  * _cairo_surface_release_source_image:
  * @surface: a #cairo_surface_t
diff --git a/src/cairoint.h b/src/cairoint.h
index 8716bd4..f930b51 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -738,6 +738,12 @@ struct _cairo_surface_backend {
 				 cairo_matrix_t		*stroke_ctm_inverse,
 				 double			 stroke_tolerance,
 				 cairo_antialias_t	 stroke_antialias);
+
+    cairo_warn cairo_status_t
+    (*acquire_source_image_transformed)	(void                    *abstract_surface,
+					 cairo_matrix_t		 *device_trasnform,
+					 cairo_image_surface_t  **image_out,
+					 void                   **image_extra);
 };
 
 #include "cairo-surface-private.h"
@@ -1721,6 +1727,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,
-- 
1.5.5.rc0.24.g86c30

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.cairographics.org/archives/cairo/attachments/20080521/f7d59202/attachment.pgp 


More information about the cairo mailing list