[cairo-commit] cairo/src Makefile.am, 1.60, 1.61 cairo-clip.c, 1.3, 1.4 cairo-gstate.c, 1.163, 1.164 cairo-image-surface.c, 1.57, 1.58 cairo-region.c, NONE, 1.1 cairo-surface.c, 1.91, 1.92 cairo-xlib-surface.c, 1.108, 1.109 cairoint.h, 1.197, 1.198

Owen Taylor commit at pdx.freedesktop.org
Tue Aug 16 18:22:18 PDT 2005


Committed by: otaylor

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv23851/src

Modified Files:
	Makefile.am cairo-clip.c cairo-gstate.c cairo-image-surface.c 
	cairo-surface.c cairo-xlib-surface.c cairoint.h 
Added Files:
	cairo-region.c 
Log Message:
2005-08-16  Owen Taylor  <otaylor at redhat.com>

	* src/cairo-region.c (_cairo_region_rectangle_extents) 
	(_cairo_region_create_from_rectangle) src/cairoint.h: Split out
	a couple of useful utility functions.

	* src/cairo-clip.c src/cairo-gstate.c: Use them.

	* src/cairo-surface.c (_cairo_surface_fill_region): Move code to
	fill a pixman_region16_t to here.

	* src/cairo-surface.c (_cairo_surface_fill_rectangle)
	* src/cairo-surface.c (_cairo_surface_fill_rectangles): Document.

	* src/cairo-gstate.c (_cairo_surface_clip_and_composite_trapezoids):
	Use _cairo_surface_fill_region().

	* src/cairo-surface.c (_cairo_surface_composite_fixup_unbounded):
	Add a return status, use regions to simplify.

	* src/cairoint.h
	* src/cairo-image-surface.c (_cairo_image_surface_composite)
	* src/cairo-xlib-surface.c (_cairo_xlib_surface_composite)
	(_show_glyphs_fixup_unbounded): Handle the return value from
	_cairo_surface_composite_fixup_unbounded().

	* src/cairo-surface.c src/cairoint.h
	(_cairo_surface_composite_shape_fixup_unbounded): Add a variant
	of _cairo_surface_composite_fixup_unbounded() to avoid creating
	a dummy cairo_surface_attributes_t.

	* src/cairo-xlib-surface (_show_glyphs_fixup_unbounded):
	Use _cairo_surface_composite_shape_fixup_unbounded().

	* src/cairo-image-surface.c (_cairo_image_surface_composite_trapezoids)
	* src/cairo-xlib-surface.c (_cairo_xlib_surface_composite_trapezoids):
	Call _cairo_surface_composite_shape_fixup_unbounded(), since the source
	might still be restricted, even though the mask is unbounded.

	* src/cairo-gstate.c (_cairo_surface_clip_and_composite_trapezoids): 
	Restore the rectangle optizations when drawing with unbounded 
	operators by adding a clear for the extra area after drawing
	the rectangles.

Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/cairo/src/Makefile.am,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- Makefile.am	10 Aug 2005 19:36:51 -0000	1.60
+++ Makefile.am	17 Aug 2005 01:22:16 -0000	1.61
@@ -109,6 +109,7 @@
 	cairo-path-stroke.c			\
 	cairo-pen.c				\
 	cairo-polygon.c				\
+	cairo-region.c				\
 	cairo-slope.c				\
 	cairo-spline.c				\
 	cairo-surface.c				\

Index: cairo-clip.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-clip.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cairo-clip.c	9 Aug 2005 01:35:22 -0000	1.3
+++ cairo-clip.c	17 Aug 2005 01:22:16 -0000	1.4
@@ -45,35 +45,6 @@
 static void
 _cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
 
-/* Creates a region from a cairo_rectangle_t */
-static cairo_status_t
-_region_new_from_rect (cairo_rectangle_t  *rect,
-		       pixman_region16_t **region)
-{
-    *region = pixman_region_create ();
-    if (pixman_region_union_rect (*region, *region,
-				  rect->x, rect->y,
-				  rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
-	pixman_region_destroy (*region);
-	return CAIRO_STATUS_NO_MEMORY;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* Gets the bounding box of a region as a cairo_rectangle_t */
-static void
-_region_rect_extents (pixman_region16_t *region,
-		      cairo_rectangle_t *rect)
-{
-    pixman_box16_t *region_extents = pixman_region_extents (region);
-
-    rect->x = region_extents->x1;
-    rect->y = region_extents->y1;
-    rect->width = region_extents->x2 - region_extents->x1;
-    rect->height = region_extents->y2 - region_extents->y1;
-}
-
 void
 _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
 {
@@ -146,18 +117,18 @@
 
     if (clip->region) {
 	pixman_region16_t *intersection;
-	cairo_status_t status;
+	cairo_status_t status = CAIRO_STATUS_SUCCESS;
 	pixman_region_status_t pixman_status;
 	
-	status = _region_new_from_rect (rectangle, &intersection);
-	if (status)
-	    return status;
+	intersection = _cairo_region_create_from_rectangle (rectangle);
+	if (intersection == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
 	
 	pixman_status = pixman_region_intersect (intersection,
 					  clip->region,
 					  intersection);
 	if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
-	    _region_rect_extents (intersection, rectangle);
+	    _cairo_region_extents_rectangle (intersection, rectangle);
 	else
 	    status = CAIRO_STATUS_NO_MEMORY;
 
@@ -187,11 +158,11 @@
     if (clip->surface) {
 	pixman_region16_t *clip_rect;
 	pixman_region_status_t pixman_status;
-	cairo_status_t status;
+	cairo_status_t status = CAIRO_STATUS_SUCCESS;
     
-	status = _region_new_from_rect (&clip->surface_rect, &clip_rect);
-	if (status)
-	    return status;
+	clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
+	if (clip_rect == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
 	
 	pixman_status = pixman_region_intersect (region,
 						 clip_rect,

Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.163
retrieving revision 1.164
diff -u -d -r1.163 -r1.164
--- cairo-gstate.c	9 Aug 2005 01:35:22 -0000	1.163
+++ cairo-gstate.c	17 Aug 2005 01:22:16 -0000	1.164
@@ -1196,45 +1196,6 @@
     return status;
 }
 
-/* Composites a region representing a set of trapezoids in the
- * case of a solid source (so we can use
- * _cairo_surface_fill_rectangles).
- */
-static cairo_status_t
-_composite_trap_region_solid (cairo_clip_t          *clip,
-			      cairo_solid_pattern_t *src,
-			      cairo_operator_t       operator,
-			      cairo_surface_t       *dst,
-			      pixman_region16_t     *region)
-{
-    int num_rects = pixman_region_num_rects (region);
-    pixman_box16_t *boxes = pixman_region_rects (region);
-    cairo_rectangle_t *rects;
-    cairo_status_t status;
-    int i;
-
-    if (!num_rects)
-	return CAIRO_STATUS_SUCCESS;
-    
-    rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
-    if (!rects)
-	return CAIRO_STATUS_NO_MEMORY;
-
-    for (i = 0; i < num_rects; i++) {
-	rects[i].x = boxes[i].x1;
-	rects[i].y = boxes[i].y1;
-	rects[i].width = boxes[i].x2 - boxes[i].x1;
-	rects[i].height = boxes[i].y2 - boxes[i].y1;
-    }
-
-    status =  _cairo_surface_fill_rectangles (dst, operator,
-					      &src->color, rects, num_rects);
-    
-    free (rects);
-
-    return status;
-}
-
 typedef struct {
     cairo_traps_t *traps;
     cairo_antialias_t antialias;
@@ -1272,19 +1233,6 @@
     return status;
 }
 
-/* Gets the bounding box of a region as a cairo_rectangle_t */
-static void
-_region_rect_extents (pixman_region16_t *region,
-		      cairo_rectangle_t *rect)
-{
-    pixman_box16_t *region_extents = pixman_region_extents (region);
-
-    rect->x = region_extents->x1;
-    rect->y = region_extents->y1;
-    rect->width = region_extents->x2 - region_extents->x1;
-    rect->height = region_extents->y2 - region_extents->y1;
-}
-
 /* Warning: This call modifies the coordinates of traps */
 cairo_status_t
 _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
@@ -1296,6 +1244,7 @@
 {
     cairo_status_t status;
     pixman_region16_t *trap_region;
+    pixman_region16_t *clear_region = NULL;
     cairo_rectangle_t extents;
     cairo_composite_traps_info_t traps_info;
     
@@ -1310,7 +1259,7 @@
     {
 	if (trap_region) {
 	    status = _cairo_clip_intersect_to_region (clip, trap_region);
-	    _region_rect_extents (trap_region, &extents);
+	    _cairo_region_extents_rectangle (trap_region, &extents);
 	} else {
 	    cairo_box_t trap_extents;
 	    _cairo_traps_extents (traps, &trap_extents);
@@ -1323,39 +1272,82 @@
 	status = _cairo_surface_get_extents (dst, &extents);
 	if (status)
 	    return status;
-	status = _cairo_clip_intersect_to_rectangle (clip, &extents);
-	if (status)
-	    return status;
+	
+	if (trap_region && !clip->surface) {
+	    /* If we optimize drawing with an unbounded operator to
+	     * _cairo_surface_fill_rectangles() or to drawing with a
+	     * clip region, then we have an additional region to clear.
+	     */
+	    status = _cairo_surface_get_extents (dst, &extents);
+	    if (status)
+		return status;
+	    
+	    clear_region = _cairo_region_create_from_rectangle (&extents);
+	    status = _cairo_clip_intersect_to_region (clip, clear_region);
+	    if (status)
+		return status;
+	    
+	    _cairo_region_extents_rectangle (clear_region,  &extents);
+	    
+	    if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
+		return CAIRO_STATUS_NO_MEMORY;
+	    
+	    if (!pixman_region_not_empty (clear_region)) {
+		pixman_region_destroy (clear_region);
+		clear_region = NULL;
+	    }
+	} else {
+	    status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+	    if (status)
+		return status;
+	}
     }
 	
     if (status)
 	goto out;
     
-    if (trap_region && _cairo_operator_bounded (operator))
+    if (trap_region)
     {
 	if (src->type == CAIRO_PATTERN_SOLID && !clip->surface)
 	{
 	    /* Solid rectangles special case */
-	    status = _composite_trap_region_solid (clip, (cairo_solid_pattern_t *)src,
-						   operator, dst, trap_region);
+	    status = _cairo_surface_fill_region (dst, operator,
+						 &((cairo_solid_pattern_t *)src)->color,
+						 trap_region);
+	    if (!status && clear_region)
+		status = _cairo_surface_fill_region (dst, operator,
+						     CAIRO_COLOR_TRANSPARENT,
+						     clear_region);
+
 	    goto out;
 	}
-	
-	/* For a simple rectangle, we can just use composite(), for more
-	 * rectangles, we have to set a clip region. The cost of rasterizing
-	 * trapezoids is pretty high for most backends currently, so it's
-	 * worthwhile even if a region is needed.
-	 *
-	 * If we have a clip surface, we set it as the mask.
-	 *
-	 * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
-	 * more than rectangle and the destination doesn't support clip
-	 * regions. In that case, we fall through.
-	 */
-	status = _composite_trap_region (clip, src, operator, dst,
-					 trap_region, &extents);
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    goto out;
+
+	if (_cairo_operator_bounded (operator) || !clip->surface)
+	{
+	    /* For a simple rectangle, we can just use composite(), for more
+	     * rectangles, we have to set a clip region. The cost of rasterizing
+	     * trapezoids is pretty high for most backends currently, so it's
+	     * worthwhile even if a region is needed.
+	     *
+	     * If we have a clip surface, we set it as the mask; this only works
+	     * for bounded operators; for unbounded operators, clip and mask
+	     * cannot be interchanged.
+	     *
+	     * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
+	     * more than rectangle and the destination doesn't support clip
+	     * regions. In that case, we fall through.
+	     */
+	    status = _composite_trap_region (clip, src, operator, dst,
+					     trap_region, &extents);
+	    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    {
+		if (!status && clear_region)
+		    status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
+							 CAIRO_COLOR_TRANSPARENT,
+							 clear_region);
+		goto out;
+	    }
+	}
     }
 
     traps_info.traps = traps;
@@ -1368,6 +1360,8 @@
  out:
     if (trap_region)
 	pixman_region_destroy (trap_region);
+    if (clear_region)
+	pixman_region_destroy (clear_region);
     
     return status;
 }

Index: cairo-image-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-image-surface.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- cairo-image-surface.c	9 Aug 2005 01:35:22 -0000	1.57
+++ cairo-image-surface.c	17 Aug 2005 01:22:16 -0000	1.58
@@ -583,47 +583,50 @@
 	return status;
     
     status = _cairo_image_surface_set_attributes (src, &src_attr);
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (status)
+      goto CLEANUP_SURFACES;
+
+    if (mask)
     {
-	if (mask)
-	{
-	    status = _cairo_image_surface_set_attributes (mask, &mask_attr);
-	    if (status == CAIRO_STATUS_SUCCESS)
-		pixman_composite (_pixman_operator (operator),
-				  src->pixman_image,
-				  mask->pixman_image,
-				  dst->pixman_image,
-				  src_x + src_attr.x_offset,
-				  src_y + src_attr.y_offset,
-				  mask_x + mask_attr.x_offset,
-				  mask_y + mask_attr.y_offset,
-				  dst_x, dst_y,
-				  width, height);
-	}
-	else
-	{
-	    pixman_composite (_pixman_operator (operator),
-			      src->pixman_image,
-			      NULL,
-			      dst->pixman_image,
-			      src_x + src_attr.x_offset,
-			      src_y + src_attr.y_offset,
-			      0, 0,
-			      dst_x, dst_y,
-			      width, height);
-	}
+	status = _cairo_image_surface_set_attributes (mask, &mask_attr);
+	if (status)
+	    goto CLEANUP_SURFACES;
+	
+	pixman_composite (_pixman_operator (operator),
+			  src->pixman_image,
+			  mask->pixman_image,
+			  dst->pixman_image,
+			  src_x + src_attr.x_offset,
+			  src_y + src_attr.y_offset,
+			  mask_x + mask_attr.x_offset,
+			  mask_y + mask_attr.y_offset,
+			  dst_x, dst_y,
+			  width, height);
+    }
+    else
+    {
+	pixman_composite (_pixman_operator (operator),
+			  src->pixman_image,
+			  NULL,
+			  dst->pixman_image,
+			  src_x + src_attr.x_offset,
+			  src_y + src_attr.y_offset,
+			  0, 0,
+			  dst_x, dst_y,
+			  width, height);
     }
-
-    if (!_cairo_operator_bounded (operator))
-	_cairo_surface_composite_fixup_unbounded (&dst->base,
-						  &src_attr, src->width, src->height,
-						  mask ? &mask_attr : NULL,
-						  mask ? mask->width : 0,
-						  mask ? mask->height : 0,
-						  src_x, src_y,
-						  mask_x, mask_y,
-						  dst_x, dst_y, width, height);
     
+    if (!_cairo_operator_bounded (operator))
+	status = _cairo_surface_composite_fixup_unbounded (&dst->base,
+							   &src_attr, src->width, src->height,
+							   mask ? &mask_attr : NULL,
+							   mask ? mask->width : 0,
+							   mask ? mask->height : 0,
+							   src_x, src_y,
+							   mask_x, mask_y,
+							   dst_x, dst_y, width, height);
+
+ CLEANUP_SURFACES:
     if (mask)
 	_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
     
@@ -765,7 +768,7 @@
      * somehow. */
     pixman_add_trapezoids (mask, - dst_x, - dst_y,
 			   (pixman_trapezoid_t *) traps, num_traps);
-    
+
     pixman_composite (_pixman_operator (operator),
 		      src->pixman_image,
 		      mask,
@@ -775,7 +778,14 @@
 		      0, 0,
 		      dst_x, dst_y,
 		      width, height);
-	
+
+    if (!_cairo_operator_bounded (operator))
+	status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
+								 &attributes, src->width, src->height,
+								 width, height,
+								 src_x, src_y,
+								 0, 0,
+								 dst_x, dst_y, width, height);
     pixman_image_destroy (mask);
 
  CLEANUP_IMAGE_DATA:

--- NEW FILE: cairo-region.c ---
(This appears to be a binary file; contents omitted.)

Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- cairo-surface.c	9 Aug 2005 01:35:22 -0000	1.91
+++ cairo-surface.c	17 Aug 2005 01:22:16 -0000	1.92
@@ -842,6 +842,21 @@
 				width, height);
 }
 
+/**
+ * _cairo_surface_fill_rectangle:
+ * @surface: a #cairo_surface_t
+ * @operator: the operator to apply to the rectangle
+ * @color: the source color
+ * @x: X coordinate of rectangle, in backend coordinates
+ * @y: Y coordinate of rectangle, in backend coordinates
+ * @width: width of rectangle, in backend coordinates
+ * @height: height of rectangle, in backend coordinates
+ * 
+ * Applies an operator to a rectangle using a solid color as the source.
+ * See _cairo_surface_fill_rectangles() for full details.
+ * 
+ * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
+ **/
 cairo_status_t
 _cairo_surface_fill_rectangle (cairo_surface_t	   *surface,
 			       cairo_operator_t	    operator,
@@ -867,6 +882,53 @@
     return _cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
 }
 
+/**
+ * _cairo_surface_fill_region:
+ * @surface: a #cairo_surface_t
+ * @operator: the operator to apply to the region
+ * @color: the source color
+ * @region: the region to modify, in backend coordinates
+ * 
+ * Applies an operator to a set of rectangles specified as a
+ * #pixman_region16_t using a solid color as the source.
+ * See _cairo_surface_fill_rectangles() for full details.
+ * 
+ * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
+ **/
+cairo_status_t
+_cairo_surface_fill_region (cairo_surface_t	   *surface,
+			    cairo_operator_t	    operator,
+			    const cairo_color_t    *color,
+			    pixman_region16_t      *region)
+{
+    int num_rects = pixman_region_num_rects (region);
+    pixman_box16_t *boxes = pixman_region_rects (region);
+    cairo_rectangle_t *rects;
+    cairo_status_t status;
+    int i;
+
+    if (!num_rects)
+	return CAIRO_STATUS_SUCCESS;
+    
+    rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
+    if (!rects)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    for (i = 0; i < num_rects; i++) {
+	rects[i].x = boxes[i].x1;
+	rects[i].y = boxes[i].y1;
+	rects[i].width = boxes[i].x2 - boxes[i].x1;
+	rects[i].height = boxes[i].y2 - boxes[i].y1;
+    }
+
+    status =  _cairo_surface_fill_rectangles (surface, operator,
+					      color, rects, num_rects);
+    
+    free (rects);
+
+    return status;
+}
+
 static cairo_status_t
 _fallback_fill_rectangles (cairo_surface_t	*surface,
 			   cairo_operator_t	operator,
@@ -941,6 +1003,22 @@
     return status;
 }
 
+/**
+ * _cairo_surface_fill_rectangles:
+ * @surface: a #cairo_surface_t
+ * @operator: the operator to apply to the region
+ * @color: the source color
+ * @rects: the rectangles to modify, in backend coordinates
+ * @num_rects: the number of rectangles in @rects
+ * 
+ * Applies an operator to a set of rectangles using a solid color
+ * as the source. Note that even if the operator is an unbounded operator
+ * such as %CAIRO_OPERATOR_CLEAR, only the given set of rectangles
+ * is affected. This differs from _cairo_surface_composite_trapezoids()
+ * where the entire destination rectangle is cleared.
+ * 
+ * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
+ **/
 cairo_status_t
 _cairo_surface_fill_rectangles (cairo_surface_t		*surface,
 				cairo_operator_t	operator,
@@ -1405,6 +1483,64 @@
     return status;
 }
 
+static cairo_status_t
+_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t            *dst,
+						   cairo_rectangle_t          *src_rectangle,
+						   cairo_rectangle_t          *mask_rectangle,
+						   int			       dst_x,
+						   int			       dst_y,
+						   unsigned int		       width,
+						   unsigned int		       height)
+{
+    cairo_rectangle_t dst_rectangle;
+    cairo_rectangle_t drawn_rectangle;
+    pixman_region16_t *drawn_region;
+    pixman_region16_t *clear_region;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    /* The area that was drawn is the area in the destination rectangle but not within
+     * the source or the mask.
+     */
+    dst_rectangle.x = dst_x;
+    dst_rectangle.y = dst_y;
+    dst_rectangle.width = width;
+    dst_rectangle.height = height;
+
+    drawn_rectangle = dst_rectangle;
+
+    if (src_rectangle)
+	_cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
+
+    if (mask_rectangle)
+	_cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
+
+    /* Now compute the area that is in dst_rectangle but not in drawn_rectangle
+     */
+    drawn_region = _cairo_region_create_from_rectangle (&drawn_rectangle);
+    clear_region = _cairo_region_create_from_rectangle (&dst_rectangle);
+    if (!drawn_region || !clear_region) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP_REGIONS;
+    }
+
+    if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP_REGIONS;
+    }
+
+    status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
+					 CAIRO_COLOR_TRANSPARENT,
+					 clear_region);
+
+ CLEANUP_REGIONS:
+    if (drawn_region)
+	pixman_region_destroy (drawn_region);
+    if (clear_region)
+	pixman_region_destroy (clear_region);
+
+    return status;
+}
+
 /**
  * _cairo_surface_composite_fixup_unbounded:
  * @dst: the destination surface
@@ -1429,7 +1565,7 @@
  * only the region inside both the source and the mask is affected.
  * This function clears the region that should have been drawn but was wasn't.
  **/
-void
+cairo_status_t
 _cairo_surface_composite_fixup_unbounded (cairo_surface_t            *dst,
 					  cairo_surface_attributes_t *src_attr,
 					  int                         src_width,
@@ -1446,112 +1582,104 @@
 					  unsigned int		      width,
 					  unsigned int		      height)
 {
-    cairo_bool_t have_src = TRUE;
-    cairo_bool_t have_mask = mask_attr != NULL;
-    cairo_rectangle_t dst_rectangle;
-    cairo_rectangle_t drawn_rectangle;
-    cairo_rectangle_t rects[4];
-    int num_rects = 0;
-
+    cairo_rectangle_t src_tmp, mask_tmp;
+    cairo_rectangle_t *src_rectangle = NULL;
+    cairo_rectangle_t *mask_rectangle = NULL;
+  
     /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
      * non-repeating sources and masks. Other sources and masks can be ignored.
      */
-    if (!_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) ||
-	src_attr->extend != CAIRO_EXTEND_NONE)
-	have_src = FALSE;
-    
-    if (have_mask &&
-	(!_cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) ||
-	 mask_attr->extend != CAIRO_EXTEND_NONE))
-	have_mask = FALSE;
-
-    /* The area that was drawn is the area in the destination rectangle but not within
-     * the source or the mask.
-     */
-    dst_rectangle.x = dst_x;
-    dst_rectangle.y = dst_y;
-    dst_rectangle.width = width;
-    dst_rectangle.height = height;
-
-    drawn_rectangle = dst_rectangle;
+    if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
+	src_attr->extend == CAIRO_EXTEND_NONE)
+    {
+	src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
+	src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
+	src_tmp.width = src_width;
+	src_tmp.height = src_height;
 
-    if (have_src) {
-	cairo_rectangle_t src_rectangle;
-	
-	src_rectangle.x = (dst_x - (src_x + src_attr->x_offset));
-	src_rectangle.y = (dst_y - (src_y + src_attr->y_offset));
-	src_rectangle.width = src_width;
-	src_rectangle.height = src_height;
-	
-	_cairo_rectangle_intersect (&drawn_rectangle, &src_rectangle);
+	src_rectangle = &src_tmp;
     }
 
-    if (have_mask) {
-	cairo_rectangle_t mask_rectangle;
-	
-	mask_rectangle.x = (dst_x - (mask_x + mask_attr->x_offset));
-	mask_rectangle.y = (dst_y - (mask_y + mask_attr->y_offset));
-	mask_rectangle.width = mask_width;
-	mask_rectangle.height = mask_height;
+    if (mask_attr &&
+	_cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) &&
+	mask_attr->extend == CAIRO_EXTEND_NONE)
+    {
+	mask_tmp.x = (dst_x - (mask_x + mask_attr->x_offset));
+	mask_tmp.y = (dst_y - (mask_y + mask_attr->y_offset));
+	mask_tmp.width = mask_width;
+	mask_tmp.height = mask_height;
 
-	_cairo_rectangle_intersect (&drawn_rectangle, &mask_rectangle);
+	mask_rectangle = &mask_tmp;
     }
 
-    /* Now compute the area that is in dst_rectangle but not in drawn_rectangle;
-     * this is the area we must clear; This computation could be done with
-     * regions, but the clumsiness of the libpixman API makes this easier.
+    return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
+							      dst_x, dst_y, width, height);
+}
+
+/**
+ * _cairo_surface_composite_shape_fixup_unbounded:
+ * @dst: the destination surface
+ * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface())
+ * @src_width: width of source surface
+ * @src_height: height of source surface
+ * @mask_width: width of mask surface
+ * @mask_height: height of mask surface
+ * @src_x: @src_x from _cairo_surface_composite()
+ * @src_y: @src_y from _cairo_surface_composite()
+ * @mask_x: @mask_x from _cairo_surface_composite()
+ * @mask_y: @mask_y from _cairo_surface_composite()
+ * @dst_x: @dst_x from _cairo_surface_composite()
+ * @dst_y: @dst_y from _cairo_surface_composite()
+ * @width: @width from _cairo_surface_composite()
+ * @height: @height_x from _cairo_surface_composite()
+ * 
+ * Like _cairo_surface_composite_fixup_unbounded(), but instead of
+ * handling the case where we have a source pattern and a mask
+ * pattern, handle the case where we are compositing a source pattern
+ * using a mask we create ourselves, as in
+ * _cairo_surface_composite_glyphs() or _cairo_surface_composite_trapezoids()
+ **/
+cairo_status_t
+_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t            *dst,
+						cairo_surface_attributes_t *src_attr,
+						int                         src_width,
+						int                         src_height,
+						int                         mask_width,
+						int                         mask_height,
+						int			    src_x,
+						int			    src_y,
+						int			    mask_x,
+						int			    mask_y,
+						int			    dst_x,
+						int			    dst_y,
+						unsigned int		    width,
+						unsigned int		    height)
+{
+    cairo_rectangle_t src_tmp, mask_tmp;
+    cairo_rectangle_t *src_rectangle = NULL;
+    cairo_rectangle_t *mask_rectangle = NULL;
+  
+    /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
+     * non-repeating sources and masks. Other sources and masks can be ignored.
      */
-    if (drawn_rectangle.width == 0 || drawn_rectangle.height == 0)
-    {
-	    rects[num_rects].x = dst_rectangle.x;
-	    rects[num_rects].y = dst_rectangle.y;
-	    rects[num_rects].width = dst_rectangle.width;
-	    rects[num_rects].height = dst_rectangle.height;
-	    
-	    num_rects++;
-    }
-    else
+    if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
+	src_attr->extend == CAIRO_EXTEND_NONE)
     {
-	if (dst_rectangle.y < drawn_rectangle.y) {
-	    rects[num_rects].x = dst_rectangle.x;
-	    rects[num_rects].y = dst_rectangle.y;
-	    rects[num_rects].width = dst_rectangle.width;
-	    rects[num_rects].height = drawn_rectangle.y - dst_rectangle.y;
-	    
-	    num_rects++;
-	}
-	
-	if (dst_rectangle.x < drawn_rectangle.x) {
-	    rects[num_rects].x = dst_rectangle.x;
-	    rects[num_rects].y = drawn_rectangle.y;
-	    rects[num_rects].width = drawn_rectangle.x - dst_rectangle.x;
-	    rects[num_rects].height = drawn_rectangle.height;
-	    
-	    num_rects++;
-	}
-	
-	if (dst_rectangle.x + dst_rectangle.width > drawn_rectangle.x + drawn_rectangle.width) {
-	    rects[num_rects].x = drawn_rectangle.x + drawn_rectangle.width;
-	    rects[num_rects].y = drawn_rectangle.y;
-	    rects[num_rects].width = (dst_rectangle.x + dst_rectangle.width) - (drawn_rectangle.x + drawn_rectangle.width);
-	    rects[num_rects].height = drawn_rectangle.height;
-	    
-	    num_rects++;
-	}
-	
-	if (dst_rectangle.y + dst_rectangle.height > drawn_rectangle.y + drawn_rectangle.height) {
-	    rects[num_rects].x = dst_rectangle.x;
-	    rects[num_rects].y = drawn_rectangle.y + drawn_rectangle.height;
-	    rects[num_rects].width = dst_rectangle.width;
-	    rects[num_rects].height = (dst_rectangle.y + dst_rectangle.height) - (drawn_rectangle.y + drawn_rectangle.height);
-	    
-	    num_rects++;
-	}
-    }
-	
-    if (num_rects > 0) {
-	_cairo_surface_fill_rectangles (dst, CAIRO_OPERATOR_SOURCE, CAIRO_COLOR_TRANSPARENT,
-					rects, num_rects);
+	src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
+	src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
+	src_tmp.width = src_width;
+	src_tmp.height = src_height;
+
+	src_rectangle = &src_tmp;
     }
-}
 
+    mask_tmp.x = dst_x - mask_x;
+    mask_tmp.y = dst_y - mask_y;
+    mask_tmp.width = mask_width;
+    mask_tmp.height = mask_height;
+    
+    mask_rectangle = &mask_tmp;
+
+    return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
+							      dst_x, dst_y, width, height);
+}

Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -d -r1.108 -r1.109
--- cairo-xlib-surface.c	9 Aug 2005 20:42:54 -0000	1.108
+++ cairo-xlib-surface.c	17 Aug 2005 01:22:16 -0000	1.109
@@ -1113,18 +1113,20 @@
 	_cairo_xlib_surface_ensure_dst_picture (dst);
 	if (mask) {
 	    status = _cairo_xlib_surface_set_attributes (mask, &mask_attr);
-	    if (status == CAIRO_STATUS_SUCCESS)
-		XRenderComposite (dst->dpy,
-				  _render_operator (operator),
-				  src->src_picture,
-				  mask->src_picture,
-				  dst->dst_picture,
-				  src_x + src_attr.x_offset,
-				  src_y + src_attr.y_offset,
-				  mask_x + mask_attr.x_offset,
-				  mask_y + mask_attr.y_offset,
-				  dst_x, dst_y,
-				  width, height);
+	    if (status)
+		goto FAIL;
+	    
+	    XRenderComposite (dst->dpy,
+			      _render_operator (operator),
+			      src->src_picture,
+			      mask->src_picture,
+			      dst->dst_picture,
+			      src_x + src_attr.x_offset,
+			      src_y + src_attr.y_offset,
+			      mask_x + mask_attr.x_offset,
+			      mask_y + mask_attr.y_offset,
+			      dst_x, dst_y,
+			      width, height);
 	} else {
 	    XRenderComposite (dst->dpy,
 			      _render_operator (operator),
@@ -1139,14 +1141,14 @@
 	}
 
 	if (!_cairo_operator_bounded (operator))
-	    _cairo_surface_composite_fixup_unbounded (&dst->base,
-						      &src_attr, src->width, src->height,
-						      mask ? &mask_attr : NULL,
-						      mask ? mask->width : 0,
-						      mask ? mask->height : 0,
-						      src_x, src_y,
-						      mask_x, mask_y,
-						      dst_x, dst_y, width, height);
+	    status = _cairo_surface_composite_fixup_unbounded (&dst->base,
+							       &src_attr, src->width, src->height,
+							       mask ? &mask_attr : NULL,
+							       mask ? mask->width : 0,
+							       mask ? mask->height : 0,
+							       src_x, src_y,
+							       mask_x, mask_y,
+							       dst_x, dst_y, width, height);
 	break;
 
     case DO_XCOPYAREA:
@@ -1413,6 +1415,14 @@
 	
 	XRenderFreePicture (dst->dpy, mask_picture);
 	
+	status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
+								 &attributes, src->width, src->height,
+								 width, height,
+								 src_x, src_y,
+								 0, 0,
+								 dst_x, dst_y, width, height);
+
+	
     } else {
 	/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
 	XRenderCompositeTrapezoids (dst->dpy,
@@ -2509,7 +2519,7 @@
  * mask created by XRenderCompositeText[N] but should be affected
  * by an unbounded operator like CAIRO_OPERATOR_SOURCE.
  */
-static void
+static cairo_status_t
 _show_glyphs_fixup_unbounded (cairo_xlib_surface_t       *self,
 			      cairo_surface_attributes_t *src_attr,
 			      cairo_xlib_surface_t       *src,
@@ -2523,7 +2533,6 @@
 			      int                         width,
 			      int                         height)
 {
-    cairo_surface_attributes_t mask_attr;
     int x1 = INT_MAX;
     int x2 = INT_MIN;
     int y1 = INT_MAX;
@@ -2555,18 +2564,12 @@
     if (x1 >= x2 || y1 >= y2)
 	x1 = x2 = y1 = y2 = 0;
 
-    cairo_matrix_init_identity (&mask_attr.matrix);
-    mask_attr.extend = CAIRO_EXTEND_NONE;
-    mask_attr.filter = CAIRO_FILTER_NEAREST;
-    mask_attr.x_offset = 0;
-    mask_attr.y_offset = 0;
-
-    _cairo_surface_composite_fixup_unbounded (&self->base,
-					      src_attr, src->width, src->height,
-					      &mask_attr, x2 - x1, y2 - y1,
-					      src_x, src_y,
-					      dst_x - x1, dst_y - y1,
-					      dst_x, dst_y, width, height);
+    return _cairo_surface_composite_shape_fixup_unbounded (&self->base,
+							   src_attr, src->width, src->height,
+							   x2 - x1, y2 - y1,
+							   src_x, src_y,
+							   dst_x - x1, dst_y - y1,
+							   dst_x, dst_y, width, height);
 }
     
 static cairo_int_status_t
@@ -2679,12 +2682,13 @@
 						    glyphs, entries, num_glyphs);
     }
 
-    if (!_cairo_operator_bounded (operator))
-	_show_glyphs_fixup_unbounded (self,
-				      &attributes, src,
-				      glyphs, entries, num_glyphs,
-				      source_x, source_y,
-				      dest_x, dest_y, width, height);
+    if (status == CAIRO_STATUS_SUCCESS &&
+	!_cairo_operator_bounded (operator))
+	status = _show_glyphs_fixup_unbounded (self,
+					       &attributes, src,
+					       glyphs, entries, num_glyphs,
+					       source_x, source_y,
+					       dest_x, dest_y, width, height);
 
  UNLOCK:
     _unlock_xlib_glyphset_caches (cache);

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.197
retrieving revision 1.198
diff -u -d -r1.197 -r1.198
--- cairoint.h	16 Aug 2005 23:41:10 -0000	1.197
+++ cairoint.h	17 Aug 2005 01:22:16 -0000	1.198
@@ -1560,15 +1560,6 @@
 _cairo_surface_get_clip_mode (cairo_surface_t *surface);
 
 cairo_private cairo_status_t
-_cairo_surface_fill_rectangle (cairo_surface_t	   *surface,
-			       cairo_operator_t	    operator,
-			       const cairo_color_t *color,
-			       int		    x,
-			       int		    y,
-			       int		    width,
-			       int		    height);
-
-cairo_private cairo_status_t
 _cairo_surface_composite (cairo_operator_t	operator,
 			  cairo_pattern_t	*src,
 			  cairo_pattern_t	*mask,
@@ -1583,6 +1574,21 @@
 			  unsigned int		height);
 
 cairo_private cairo_status_t
+_cairo_surface_fill_rectangle (cairo_surface_t	   *surface,
+			       cairo_operator_t	    operator,
+			       const cairo_color_t *color,
+			       int		    x,
+			       int		    y,
+			       int		    width,
+			       int		    height);
+
+cairo_private cairo_status_t
+_cairo_surface_fill_region (cairo_surface_t	   *surface,
+			    cairo_operator_t	    operator,
+			    const cairo_color_t    *color,
+			    pixman_region16_t      *region);
+
+cairo_private cairo_status_t
 _cairo_surface_fill_rectangles (cairo_surface_t		*surface,
 				cairo_operator_t	operator,
 				const cairo_color_t	*color,
@@ -1696,7 +1702,7 @@
 			    const cairo_glyph_t		*glyphs,
 			    int				num_glyphs);
 
-cairo_private void
+cairo_private cairo_status_t
 _cairo_surface_composite_fixup_unbounded (cairo_surface_t            *dst,
 					  cairo_surface_attributes_t *src_attr,
 					  int                         src_width,
@@ -1713,6 +1719,22 @@
 					  unsigned int		      width,
 					  unsigned int		      height);
 
+cairo_private cairo_status_t
+_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t            *dst,
+						cairo_surface_attributes_t *src_attr,
+						int                         src_width,
+						int                         src_height,
+						int                         mask_width,
+						int                         mask_height,
+						int			    src_x,
+						int			    src_y,
+						int			    mask_x,
+						int			    mask_y,
+						int			    dst_x,
+						int			    dst_y,
+						unsigned int		    width,
+						unsigned int		    height);
+
 /* cairo_image_surface.c */
 
 cairo_private cairo_format_t
@@ -1958,6 +1980,14 @@
 cairo_private cairo_antialias_t
 _cairo_gstate_get_antialias (cairo_gstate_t *gstate);
 
+/* cairo-region.c */
+
+cairo_private pixman_region16_t *
+_cairo_region_create_from_rectangle (cairo_rectangle_t *rect);
+
+cairo_private void
+_cairo_region_extents_rectangle (pixman_region16_t *region,
+				 cairo_rectangle_t *rect);
 
 /* cairo_unicode.c */
 



More information about the cairo-commit mailing list