[cairo] [PATCH] *updated* add extents to clone_similar

Christopher "Monty" Montgomery xiphmont at gmail.com
Thu Oct 5 11:47:01 PDT 2006


Oops, I found a trivial bug in the necessary extent change to gradients.

Here is a corrected patch.  Summary of correction: the src_x and src_y
to the _clone_similar call in
_cairo_pattern_acquire_surface_for_gradient should be 0, 0.

Monty

---
 src/cairo-clip.c             |   11 ++++++++++-
 src/cairo-directfb-surface.c |   17 +++++++++++++----
 src/cairo-glitz-surface.c    |   30 ++++++++++++++++++++++--------
 src/cairo-image-surface.c    |    4 ++++
 src/cairo-nquartz-surface.c  |    9 +++++++--
 src/cairo-pattern.c          |   38 ++++++++++++++++++++------------------
 src/cairo-surface.c          |   14 ++++++++++++--
 src/cairo-xcb-surface.c      |    9 +++++++++
 src/cairo-xlib-surface.c     |   18 ++++++++++++++----
 src/cairoint.h               |    8 ++++++++
 10 files changed, 119 insertions(+), 39 deletions(-)

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 3f7c0c0..fcb96a6 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -563,7 +563,16 @@ _cairo_clip_init_deep_copy (cairo_clip_t
         }

         if (other->surface) {
-            _cairo_surface_clone_similar (target, clip->surface,
&clip->surface);
+            _cairo_surface_clone_similar (target, clip->surface,
+					  // is this more or less
+					  // correct than just cloning
+					  // the entire surface
+					  // rectangle? --Monty
+					  clip->surface_rect.x,
+					  clip->surface_rect.y,
+					  clip->surface_rect.width,
+					  clip->surface_rect.height,
+					  &clip->surface);
             clip->surface_rect = other->surface_rect;
         }

diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index fdff40a..ef5954c 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -548,6 +548,10 @@ _cairo_directfb_surface_release_dest_ima
 static cairo_status_t
 _cairo_directfb_surface_clone_similar (void             *abstract_surface,
                                        cairo_surface_t  *src,
+				       int               src_x,
+				       int               src_y,
+				       int               width,
+				       int               height,
                                        cairo_surface_t **clone_out)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
@@ -584,18 +588,23 @@ _cairo_directfb_surface_clone_similar (v
             return CAIRO_STATUS_NO_MEMORY;
         }

+	
+	dst += pitch * src_y;
+	src += image_src->stride * src_y;
+
         if (image_src->format == CAIRO_FORMAT_A1) {
             /* A1 -> A8 */
-            for (i = 0; i < image_src->height; i++) {
-                for (j = 0; j < image_src->width; j++)
+            for (i = 0; i < height; i++) {
+                for (j = src_x; j < src_x + width; j++)
                     dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
                 dst += pitch;
                 src += image_src->stride;
             }
         }
         else {
-            for (i = 0; i < image_src->height; i++) {
-                direct_memcpy( dst, src, image_src->stride );
+            /* A8 -> A8 */
+            for (i = 0; i < height; i++) {
+	        direct_memcpy( dst+src_x, src+src_x, sizeof(*dst)*width );
                 dst += pitch;
                 src += image_src->stride;
             }
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index c7d6aa3..713270c 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -243,8 +243,12 @@ _cairo_glitz_surface_get_image (cairo_gl
 static cairo_status_t
 _cairo_glitz_surface_set_image (void		      *abstract_surface,
 				cairo_image_surface_t *image,
-				int		      x_dst,
-				int		      y_dst)
+				int                    src_x,
+				int                    src_y,
+				int                    width,
+				int                    height,
+				int		       x_dst,
+				int		       y_dst)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
     glitz_buffer_t	  *buffer;
@@ -264,8 +268,8 @@ _cairo_glitz_surface_set_image (void		
     pf.masks.red_mask = rm;
     pf.masks.green_mask = gm;
     pf.masks.blue_mask = bm;
-    pf.xoffset = 0;
-    pf.skip_lines = 0;
+    pf.xoffset = src_x;
+    pf.skip_lines = src_y;

     /* check for negative stride */
     if (image->stride < 0)
@@ -287,7 +291,7 @@ _cairo_glitz_surface_set_image (void		

     glitz_set_pixels (surface->surface,
 		      x_dst, y_dst,
-		      image->width, image->height,
+		      width, height,
 		      &pf,
 		      buffer);

@@ -347,7 +351,8 @@ _cairo_glitz_surface_release_dest_image
 {
     cairo_glitz_surface_t *surface = abstract_surface;

-    _cairo_glitz_surface_set_image (surface, image,
+    _cairo_glitz_surface_set_image (surface, image, 0, 0,
+				    image->width, image->height,
 				    image_rect->x, image_rect->y);

     cairo_surface_destroy (&image->base);
@@ -356,6 +361,10 @@ _cairo_glitz_surface_release_dest_image
 static cairo_status_t
 _cairo_glitz_surface_clone_similar (void	    *abstract_surface,
 				    cairo_surface_t *src,
+				    int              src_x,
+				    int              src_y,
+				    int              width,
+				    int              height,
 				    cairo_surface_t **clone_out)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
@@ -384,7 +393,8 @@ _cairo_glitz_surface_clone_similar (void
 	if (clone->base.status)
 	    return CAIRO_STATUS_NO_MEMORY;

-	_cairo_glitz_surface_set_image (clone, image_src, 0, 0);
+	_cairo_glitz_surface_set_image (clone, image_src, src_x, src_y,
+					width, height, src_x, src_y);

 	*clone_out = &clone->base;

@@ -1183,7 +1193,7 @@ _cairo_glitz_surface_composite_trapezoid
 	    return CAIRO_STATUS_NO_MEMORY;
 	}

-	_cairo_glitz_surface_set_image (mask, image, 0, 0);
+	_cairo_glitz_surface_set_image (mask, image, src_x, src_y, width,
height, 0, 0);
     }

     _cairo_glitz_surface_set_attributes (src, &attributes);
@@ -2024,6 +2034,10 @@ _cairo_glitz_surface_old_show_glyphs (ca
 		status =
 		    _cairo_glitz_surface_clone_similar (abstract_surface,
 							image,
+							src_x,
+							src_y,
+							width,
+							height,
 							(cairo_surface_t **)
 							&clone);
 		if (status)
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 62040d8..74fccdb 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -617,6 +617,10 @@ _cairo_image_surface_release_dest_image
 static cairo_status_t
 _cairo_image_surface_clone_similar (void		*abstract_surface,
 				    cairo_surface_t	*src,
+				    int                  src_x,
+				    int                  src_y,
+				    int                  width,
+				    int                  height,
 				    cairo_surface_t    **clone_out)
 {
     cairo_image_surface_t *surface = abstract_surface;
diff --git a/src/cairo-nquartz-surface.c b/src/cairo-nquartz-surface.c
index 1c300b1..aef5a62 100644
--- a/src/cairo-nquartz-surface.c
+++ b/src/cairo-nquartz-surface.c
@@ -498,7 +498,8 @@ SurfacePatternDrawFunc (void *info, CGCo

 	cairo_surface_t *new_surf = NULL;

-	_cairo_surface_clone_similar (dummy, pat_surf, &new_surf);
+	_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
+				      rect.width, rect.height, &new_surf);

 	cairo_surface_destroy(dummy);

@@ -1025,6 +1026,10 @@ _cairo_nquartz_surface_create_similar (v
 static cairo_status_t
 _cairo_nquartz_surface_clone_similar (void *abstract_surface,
 				      cairo_surface_t *src,
+				      int              src_x,
+				      int              src_y,
+				      int              width,
+				      int              height,
 				      cairo_surface_t **clone_out)
 {
     cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *)
abstract_surface;
@@ -1104,7 +1109,7 @@ _cairo_nquartz_surface_clone_similar (vo
     nquartz_image_to_png (quartz_image, NULL);

     CGContextDrawImage (new_surface->cgContext,
-			CGRectMake (0, 0, CGImageGetWidth (quartz_image), CGImageGetHeight
(quartz_image)),
+			CGRectMake (src_x, src_y, width, height),
 			quartz_image);
     CGImageRelease (quartz_image);

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index a2a08e0..db5d297 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1024,7 +1024,8 @@ _cairo_pattern_acquire_surface_for_gradi

     pixman_image_destroy (pixman_image);

-    status = _cairo_surface_clone_similar (dst, &image->base, out);
+    status = _cairo_surface_clone_similar (dst, &image->base,
+					   0, 0, width, height, out);

     cairo_surface_destroy (&image->base);

@@ -1144,6 +1145,22 @@ _cairo_pattern_acquire_surface_for_surfa

     attr->acquired = FALSE;

+    attr->extend = pattern->base.extend;
+    attr->filter = pattern->base.filter;
+    if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
+					      &tx, &ty))
+    {
+	cairo_matrix_init_identity (&attr->matrix);
+	attr->x_offset = tx;
+	attr->y_offset = ty;
+	attr->filter = CAIRO_FILTER_NEAREST;
+    }
+    else
+    {
+	attr->matrix = pattern->base.matrix;
+	attr->x_offset = attr->y_offset = 0;
+    }
+
     if (_cairo_surface_is_image (dst))
     {
 	cairo_image_surface_t *image;
@@ -1159,23 +1176,8 @@ _cairo_pattern_acquire_surface_for_surfa
     }
     else
     {
-	status = _cairo_surface_clone_similar (dst, pattern->surface, out);
-    }
-
-    attr->extend = pattern->base.extend;
-    attr->filter = pattern->base.filter;
-    if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
-					      &tx, &ty))
-    {
-	cairo_matrix_init_identity (&attr->matrix);
-	attr->x_offset = tx;
-	attr->y_offset = ty;
-	attr->filter = CAIRO_FILTER_NEAREST;
-    }
-    else
-    {
-	attr->matrix = pattern->base.matrix;
-	attr->x_offset = attr->y_offset = 0;
+	status = _cairo_surface_clone_similar (dst, pattern->surface,
+					       x+tx, y+ty, width, height, out);
     }

     return status;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index cbbe89a..b6e92f2 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -987,6 +987,10 @@ _cairo_surface_release_dest_image (cairo
  * _cairo_surface_clone_similar:
  * @surface: a #cairo_surface_t
  * @src: the source image
+ * @src_x: extent for the rectangle in src we actually care about
+ * @src_y: extent for the rectangle in src we actually care about
+ * @width: extent for the rectangle in src we actually care about
+ * @height: extent for the rectangle in src we actually care about
  * @clone_out: location to store a surface compatible with @surface
  *   and with contents identical to @src. The caller must call
  *   cairo_surface_destroy() on the result.
@@ -1002,6 +1006,10 @@ _cairo_surface_release_dest_image (cairo
 cairo_status_t
 _cairo_surface_clone_similar (cairo_surface_t  *surface,
 			      cairo_surface_t  *src,
+			      int               src_x,
+			      int               src_y,
+			      int               width,
+			      int               height,
 			      cairo_surface_t **clone_out)
 {
     cairo_status_t status;
@@ -1014,7 +1022,8 @@ _cairo_surface_clone_similar (cairo_surf
     if (surface->backend->clone_similar == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;

-    status = surface->backend->clone_similar (surface, src, clone_out);
+    status = surface->backend->clone_similar (surface, src, src_x, src_y,
+					      width, height, clone_out);
     if (status == CAIRO_STATUS_SUCCESS)
         (*clone_out)->device_transform = src->device_transform;

@@ -1025,7 +1034,8 @@ _cairo_surface_clone_similar (cairo_surf
     if (status != CAIRO_STATUS_SUCCESS)
 	return status;

-    status = surface->backend->clone_similar (surface, &image->base,
clone_out);
+    status = surface->backend->clone_similar (surface, &image->base, src_x,
+					      src_y, width, height, clone_out);
     if (status == CAIRO_STATUS_SUCCESS)
         (*clone_out)->device_transform = src->device_transform;

diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index f60bc3b..4bdf837 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -588,6 +588,10 @@ _cairo_xcb_surface_same_screen (cairo_xc
 static cairo_status_t
 _cairo_xcb_surface_clone_similar (void			*abstract_surface,
 				  cairo_surface_t	*src,
+				  int                    src_x,
+				  int                    src_y,
+				  int                    width,
+				  int                    height,
 				  cairo_surface_t     **clone_out)
 {
     cairo_xcb_surface_t *surface = abstract_surface;
@@ -614,6 +618,11 @@ _cairo_xcb_surface_clone_similar (void		
 	if (clone->base.status)
 	    return CAIRO_STATUS_NO_MEMORY;

+	/* can't apply extents; no manpages for XCBPutImage and xcb
+	source from freedesktop currently won't build.  XCBPutImage is not
+	referenced in the XCB source from xcb.freedesktop.org/dist
+	anywhere. */
+
 	_draw_image_surface (clone, image_src, 0, 0);

 	*clone_out = &clone->base;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index d0f9158..aaf43e4 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -744,6 +744,10 @@ _cairo_xlib_surface_ensure_gc (cairo_xli
 static cairo_status_t
 _draw_image_surface (cairo_xlib_surface_t   *surface,
 		     cairo_image_surface_t  *image,
+		     int                    src_x,
+		     int                    src_y,
+		     int                    width,
+		     int                    height,
 		     int                    dst_x,
 		     int                    dst_y)
 {
@@ -774,8 +778,8 @@ _draw_image_surface (cairo_xlib_surface_

     _cairo_xlib_surface_ensure_gc (surface);
     XPutImage(surface->dpy, surface->drawable, surface->gc,
-	      &ximage, 0, 0, dst_x, dst_y,
-	      image->width, image->height);
+	      &ximage, src_x, src_y, dst_x, dst_y,
+	      width, height);

     return CAIRO_STATUS_SUCCESS;

@@ -839,7 +843,8 @@ _cairo_xlib_surface_release_dest_image (
     cairo_xlib_surface_t *surface = abstract_surface;

     /* ignore errors */
-    _draw_image_surface (surface, image, image_rect->x, image_rect->y);
+    _draw_image_surface (surface, image, 0, 0, image->width, image->height,
+			 image_rect->x, image_rect->y);

     cairo_surface_destroy (&image->base);
 }
@@ -859,6 +864,10 @@ _cairo_xlib_surface_same_screen (cairo_x
 static cairo_status_t
 _cairo_xlib_surface_clone_similar (void			*abstract_surface,
 				   cairo_surface_t	*src,
+				   int                   src_x,
+				   int                   src_y,
+				   int                   width,
+				   int                   height,
 				   cairo_surface_t     **clone_out)
 {
     cairo_xlib_surface_t *surface = abstract_surface;
@@ -884,7 +893,8 @@ _cairo_xlib_surface_clone_similar (void	
 	if (clone->base.status)
 	    return CAIRO_STATUS_NO_MEMORY;

-	_draw_image_surface (clone, image_src, 0, 0);
+	_draw_image_surface (clone, image_src, src_x, src_y,
+			     width, height, src_x, src_y);

 	*clone_out = &clone->base;

diff --git a/src/cairoint.h b/src/cairoint.h
index 6a3bc31..8781774 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -723,6 +723,10 @@ struct _cairo_surface_backend {
     cairo_status_t
     (*clone_similar)            (void                   *surface,
 				 cairo_surface_t        *src,
+				 int                     src_x,
+				 int                     src_y,
+				 int                     width,
+				 int                     height,
 				 cairo_surface_t       **clone_out);

     /* XXX: dst should be the first argument for consistency */
@@ -1885,6 +1889,10 @@ _cairo_surface_release_dest_image (cairo
 cairo_private cairo_status_t
 _cairo_surface_clone_similar (cairo_surface_t  *surface,
 			      cairo_surface_t  *src,
+			      int               src_x,
+			      int               src_y,
+			      int               width,
+			      int               height,
 			      cairo_surface_t **clone_out);

 cairo_private cairo_surface_t *
-- 
1.4.1.1


More information about the cairo mailing list