[cairo-commit] cairo/src cairo-font.c, 1.69, 1.70 cairo-ft-font.c, 1.102, 1.103 cairo-gstate.c, 1.164, 1.165 cairo-image-surface.c, 1.58, 1.59 cairo-surface.c, 1.92, 1.93 cairo-xlib-surface.c, 1.109, 1.110

Owen Taylor commit at pdx.freedesktop.org
Thu Aug 18 15:50:39 PDT 2005


Committed by: otaylor

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

Modified Files:
	cairo-font.c cairo-ft-font.c cairo-gstate.c 
	cairo-image-surface.c cairo-surface.c cairo-xlib-surface.c 
Log Message:
2005-08-17  Owen Taylor  <otaylor at redhat.com>
	
	* src/cairo-gstate.c: Implement new equations for CLEAR and SOURCE
	CLEAR: (mask IN clip) ? 0 : dest
	SOURCE: (mask IN clip) ? src : dest
	That behave more like what people expect.

	* src/cairo-gstate.c (_cairo_operator_bounded): CLEAR and SOURCE are 
	now bounded.

	* src/cairo-font.c (_cairo_ft_scaled_font_show_glyphs)
	* src/cairo-surface.c (_cairo_surface_composite_trapezoids):
	Assert that SOURCE and CLEAR aren't passed to these functions.

	* src/cairo-surface.c (_cairo_surface_composite):
	Assert that SOURCE and CLEAR aren't passed to these functions
	when there is a mask.

	* src/cairo-xlib-surface.c (_cairo_xlib_surface_composite)
	* src/cairo-image-surface.c (_cairo_image_surface_composite): 
	Do fixups for SOURCE and CLEAR as well as unbounded operators,
	since in the absence of a mask, we need SOURCE to work 
	correctly (don't care about CLEAR)

	* src/cairo-ft-font.c (_transform_glyph_bitmap, _cairo_ft_font_show_glyphs)
	Consistently use CLEAR/TRANSPARENT (source doesn't matter)
	rather than SOURCE/TRANSPARENT when clearing rectangles.

	* src/cairo-xlib-surface.c src/cairo-surface.c: Use 
	IN rather than SOURCE as an example of an unbounded operator in
	docs.

	* test/unbounded-operator.c: Remove CLEAR/SOURCE columns since
	they are no longer unbounded.

	* test/operator-clear.c test/operator-source Makefile.am: Add
	targetted tests of CLEAR/SOURCE.

Index: cairo-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-font.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- cairo-font.c	13 Aug 2005 08:38:55 -0000	1.69
+++ cairo-font.c	18 Aug 2005 22:50:36 -0000	1.70
@@ -890,6 +890,11 @@
 {
     cairo_status_t status;
 
+    /* These operators aren't interpreted the same way by the backends;
+     * they are implemented in terms of other operators in cairo-gstate.c
+     */
+    assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR);
+    
     if (scaled_font->status)
 	return scaled_font->status;
 

Index: cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.102
retrieving revision 1.103
diff -u -d -r1.102 -r1.103
--- cairo-ft-font.c	17 Aug 2005 16:51:09 -0000	1.102
+++ cairo-ft-font.c	18 Aug 2005 22:50:36 -0000	1.103
@@ -1133,7 +1133,7 @@
 
     /* Initialize it to empty
      */
-    _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_SOURCE,
+    _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
 				   CAIRO_COLOR_TRANSPARENT,
 				   0, 0,
 				   width, height);
@@ -1960,7 +1960,7 @@
     if (!mask)
 	goto CLEANUP_ENTRIES;
 
-    status = _cairo_surface_fill_rectangle (mask, CAIRO_OPERATOR_SOURCE,
+    status = _cairo_surface_fill_rectangle (mask, CAIRO_OPERATOR_CLEAR,
 					    CAIRO_COLOR_TRANSPARENT,
 					    0, 0, width, height);
     if (status)

Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.164
retrieving revision 1.165
diff -u -d -r1.164 -r1.165
--- cairo-gstate.c	17 Aug 2005 01:22:16 -0000	1.164
+++ cairo-gstate.c	18 Aug 2005 22:50:36 -0000	1.165
@@ -258,8 +258,8 @@
     _cairo_surface_set_drawableWH (gstate->target, pix, width, height);
 
     status = _cairo_surface_fill_rectangle (gstate->target,
-                                   CAIRO_OPERATOR_SOURCE,
-				   &CAIRO_COLOR_TRANSPARENT,
+                                   CAIRO_OPERATOR_CLEAR,
+				   CAIRO_COLOR_TRANSPARENT,
 				   0, 0,
 			           _cairo_surface_get_width (gstate->target),
 				   _cairo_surface_get_height (gstate->target));
@@ -723,6 +723,8 @@
 _cairo_operator_bounded (cairo_operator_t operator)
 {
     switch (operator) {
+    case CAIRO_OPERATOR_CLEAR:
+    case CAIRO_OPERATOR_SOURCE:
     case CAIRO_OPERATOR_OVER:
     case CAIRO_OPERATOR_ATOP:
     case CAIRO_OPERATOR_DEST:
@@ -732,8 +734,6 @@
     case CAIRO_OPERATOR_ADD:
     case CAIRO_OPERATOR_SATURATE:
 	return TRUE;
-    case CAIRO_OPERATOR_CLEAR:
-    case CAIRO_OPERATOR_SOURCE:
     case CAIRO_OPERATOR_OUT:
     case CAIRO_OPERATOR_IN:
     case CAIRO_OPERATOR_DEST_IN:
@@ -753,6 +753,47 @@
 					     int                      dst_y,
 					     const cairo_rectangle_t *extents);
 
+static cairo_status_t
+_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
+				cairo_clip_t            *clip,
+				cairo_draw_func_t        draw_func,
+				void                    *draw_closure,
+				cairo_surface_t         *dst,
+				const cairo_rectangle_t *extents)
+{
+    cairo_surface_t *mask;
+    cairo_status_t status;
+    
+    mask = cairo_surface_create_similar (dst,
+					 CAIRO_CONTENT_ALPHA,
+					 extents->width,
+					 extents->height);
+    if (mask->status)
+	return CAIRO_STATUS_NO_MEMORY;
+    
+    status = (*draw_func) (draw_closure, CAIRO_OPERATOR_ADD,
+			   NULL, mask,
+			   extents->x, extents->y,
+			   extents);
+    if (status)
+	goto CLEANUP_SURFACE;
+
+    if (clip->surface)
+	status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
+						 mask,
+						 extents->x, extents->y,
+						 extents);
+    if (status)
+	goto CLEANUP_SURFACE;
+    
+    _cairo_pattern_init_for_surface (mask_pattern, mask);
+
+ CLEANUP_SURFACE:
+    cairo_surface_destroy (mask);
+
+    return status;
+}
+
 /* Handles compositing with a clip surface when the operator allows
  * us to combine the clip with the mask
  */
@@ -765,50 +806,30 @@
 					    cairo_surface_t         *dst,
 					    const cairo_rectangle_t *extents)
 {
-    cairo_surface_t *intermediate;
-    cairo_surface_pattern_t intermediate_pattern;
+    cairo_surface_pattern_t mask_pattern;
     cairo_status_t status;
 
-    intermediate = cairo_surface_create_similar (clip->surface,
-						 CAIRO_CONTENT_ALPHA,
-						 extents->width,
-						 extents->height);
-    if (intermediate->status)
-	return CAIRO_STATUS_NO_MEMORY;
-
-    status = (*draw_func) (draw_closure, CAIRO_OPERATOR_SOURCE,
-			   NULL, intermediate,
-			   extents->x, extents->y,
-			   extents);
-    if (status)
-	goto CLEANUP_SURFACE;
-    
-    status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
-					     intermediate,
-					     extents->x, extents->y,
-					     extents);
+    status = _create_composite_mask_pattern (&mask_pattern,
+					     clip,
+					     draw_func, draw_closure,
+					     dst, extents);
     if (status)
-	goto CLEANUP_SURFACE;
-    
-    _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
-    
+	return status;
+	
     status = _cairo_surface_composite (operator,
-				       src, &intermediate_pattern.base, dst,
+				       src, &mask_pattern.base, dst,
 				       extents->x,     extents->y,
 				       0,              0,
 				       extents->x,     extents->y,
 				       extents->width, extents->height);
 
-    _cairo_pattern_fini (&intermediate_pattern.base);
-
- CLEANUP_SURFACE:
-    cairo_surface_destroy (intermediate);
+    _cairo_pattern_fini (&mask_pattern.base);
 
     return status;
 }
 
-/* Handles compositing with a clip surface when the operator allows
- * us to combine the clip with the mask
+/* Handles compositing with a clip surface when we have to do the operation
+ * in two pieces and combine them together.
  */
 static cairo_status_t
 _cairo_gstate_clip_and_composite_combine (cairo_clip_t            *clip,
@@ -827,6 +848,7 @@
     /* We'd be better off here creating a surface identical in format
      * to dst, but we have no way of getting that information.
      * A CAIRO_CONTENT_CLONE or something might be useful.
+     * cairo_surface_create_similar() also unnecessarily clears the surface.
      */
     intermediate = cairo_surface_create_similar (dst,
 						 CAIRO_CONTENT_COLOR_ALPHA,
@@ -895,6 +917,55 @@
     return status;
 }
 
+/* Handles compositing for CAIRO_OPERATOR_SOURCE, which is special; it's
+ * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
+ */
+static cairo_status_t
+_cairo_gstate_clip_and_composite_source (cairo_clip_t            *clip,
+					 cairo_pattern_t         *src,
+					 cairo_draw_func_t        draw_func,
+					 void                    *draw_closure,
+					 cairo_surface_t         *dst,
+					 const cairo_rectangle_t *extents)
+{
+    cairo_surface_pattern_t mask_pattern;
+    cairo_status_t status;
+
+    /* Create a surface that is mask IN clip
+     */
+    status = _create_composite_mask_pattern (&mask_pattern,
+					     clip,
+					     draw_func, draw_closure,
+					     dst, extents);
+    if (status)
+	return status;
+    
+    /* Compute dest' = dest OUT (mask IN clip)
+     */
+    status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
+				       &mask_pattern.base, NULL, dst,
+				       0,              0,
+				       0,              0,
+				       extents->x,     extents->y,
+				       extents->width, extents->height);
+
+    if (status)
+	goto CLEANUP_MASK_PATTERN;
+
+    /* Now compute (src IN (mask IN clip)) ADD dest'
+     */
+    status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+				       src, &mask_pattern.base, dst,
+				       extents->x,     extents->y,
+				       0,              0,
+				       extents->x,     extents->y,
+				       extents->width, extents->height);
+
+ CLEANUP_MASK_PATTERN:
+    _cairo_pattern_fini (&mask_pattern.base);
+    return status;
+}
+
 static int
 _cairo_rectangle_empty (const cairo_rectangle_t *rect)
 {
@@ -931,30 +1002,49 @@
 				  cairo_surface_t         *dst,
 				  const cairo_rectangle_t *extents)
 {
+    cairo_pattern_union_t solid_pattern;
+    cairo_status_t status;
+
     if (_cairo_rectangle_empty (extents))
 	/* Nothing to do */
 	return CAIRO_STATUS_SUCCESS;
 
-    if (clip->surface)
+    if (operator == CAIRO_OPERATOR_CLEAR) {
+	_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
+	src = &solid_pattern.base;
+	operator = CAIRO_OPERATOR_DEST_OUT;
+    }
+
+    if (clip->surface || operator == CAIRO_OPERATOR_SOURCE)
     {
-	if (_cairo_operator_bounded (operator))
-	    return _cairo_gstate_clip_and_composite_with_mask (clip, operator,
+	if (operator == CAIRO_OPERATOR_SOURCE)
+	    status = _cairo_gstate_clip_and_composite_source (clip,
+							      src,
+							      draw_func, draw_closure,
+							      dst, extents);
+	else if (_cairo_operator_bounded (operator))
+	    status = _cairo_gstate_clip_and_composite_with_mask (clip, operator,
+								 src,
+								 draw_func, draw_closure,
+								 dst, extents);
+	else
+	    status = _cairo_gstate_clip_and_composite_combine (clip, operator,
 							       src,
 							       draw_func, draw_closure,
 							       dst, extents);
-	else
-	    return _cairo_gstate_clip_and_composite_combine (clip, operator,
-							     src,
-							     draw_func, draw_closure,
-							     dst, extents);
     }
     else
     {
-	return (*draw_func) (draw_closure, operator,
-			     src, dst,
-			     0, 0,
-			     extents);
+	status = (*draw_func) (draw_closure, operator,
+			       src, dst,
+			       0, 0,
+			       extents);
     }
+
+    if (src == &solid_pattern.base)
+	_cairo_pattern_fini (&solid_pattern.base);
+
+    return status;
 }
 			       
 
@@ -1158,10 +1248,17 @@
 			cairo_rectangle_t *extents)
 {
     cairo_status_t status;
+    cairo_pattern_union_t solid_pattern;
     cairo_pattern_union_t mask;
     int num_rects = pixman_region_num_rects (trap_region);
     unsigned int clip_serial;
 
+    if (clip->surface && operator == CAIRO_OPERATOR_CLEAR) {
+	_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
+	src = &solid_pattern.base;
+	operator = CAIRO_OPERATOR_DEST_OUT;
+    }
+
     if (num_rects == 0)
 	return CAIRO_STATUS_SUCCESS;
     
@@ -1193,6 +1290,9 @@
     if (clip->surface)
       _cairo_pattern_fini (&mask.base);
 
+    if (src == &solid_pattern.base)
+	_cairo_pattern_fini (&solid_pattern.base);
+
     return status;
 }
 
@@ -1308,21 +1408,28 @@
     
     if (trap_region)
     {
-	if (src->type == CAIRO_PATTERN_SOLID && !clip->surface)
+	if ((src->type == CAIRO_PATTERN_SOLID || operator == CAIRO_OPERATOR_CLEAR) &&
+	    !clip->surface)
 	{
+	    const cairo_color_t *color;
+
+	    if (operator == CAIRO_OPERATOR_CLEAR)
+		color = CAIRO_COLOR_TRANSPARENT;
+	    else
+		color = &((cairo_solid_pattern_t *)src)->color;
+	  
 	    /* Solid rectangles special case */
-	    status = _cairo_surface_fill_region (dst, operator,
-						 &((cairo_solid_pattern_t *)src)->color,
-						 trap_region);
+	    status = _cairo_surface_fill_region (dst, operator, color, trap_region);
 	    if (!status && clear_region)
-		status = _cairo_surface_fill_region (dst, operator,
+		status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
 						     CAIRO_COLOR_TRANSPARENT,
 						     clear_region);
 
 	    goto out;
 	}
 
-	if (_cairo_operator_bounded (operator) || !clip->surface)
+	if ((_cairo_operator_bounded (operator) && operator != CAIRO_OPERATOR_SOURCE) ||
+	    !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
@@ -1330,8 +1437,10 @@
 	     * 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.
+	     * for bounded operators other than SOURCE; for unbounded operators,
+	     * clip and mask cannot be interchanged. For SOURCE, the operator
+	     * as implemented by the backends is different in it's handling
+	     * of the mask then what we want.
 	     *
 	     * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
 	     * more than rectangle and the destination doesn't support clip

Index: cairo-image-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-image-surface.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -d -r1.58 -r1.59
--- cairo-image-surface.c	17 Aug 2005 01:22:16 -0000	1.58
+++ cairo-image-surface.c	18 Aug 2005 22:50:36 -0000	1.59
@@ -616,7 +616,9 @@
 			  width, height);
     }
     
-    if (!_cairo_operator_bounded (operator))
+    if (!_cairo_operator_bounded (operator) ||
+	operator == CAIRO_OPERATOR_SOURCE ||
+	operator == CAIRO_OPERATOR_CLEAR)
 	status = _cairo_surface_composite_fixup_unbounded (&dst->base,
 							   &src_attr, src->width, src->height,
 							   mask ? &mask_attr : NULL,

Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -d -r1.92 -r1.93
--- cairo-surface.c	17 Aug 2005 01:22:16 -0000	1.92
+++ cairo-surface.c	18 Aug 2005 22:50:36 -0000	1.93
@@ -817,6 +817,13 @@
 {
     cairo_int_status_t status;
 
+    if (mask) {
+	/* These operators aren't interpreted the same way by the backends;
+	 * they are implemented in terms of other operators in cairo-gstate.c
+	 */
+	assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR);
+    }
+
     if (dst->status)
 	return dst->status;
 	
@@ -1013,7 +1020,7 @@
  * 
  * 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
+ * such as %CAIRO_OPERATOR_IN, only the given set of rectangles
  * is affected. This differs from _cairo_surface_composite_trapezoids()
  * where the entire destination rectangle is cleared.
  * 
@@ -1152,6 +1159,11 @@
 {
     cairo_int_status_t status;
 
+    /* These operators aren't interpreted the same way by the backends;
+     * they are implemented in terms of other operators in cairo-gstate.c
+     */
+    assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR);
+
     if (dst->status)
 	return dst->status;
 

Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -d -r1.109 -r1.110
--- cairo-xlib-surface.c	17 Aug 2005 01:22:16 -0000	1.109
+++ cairo-xlib-surface.c	18 Aug 2005 22:50:36 -0000	1.110
@@ -1140,7 +1140,9 @@
 			      width, height);
 	}
 
-	if (!_cairo_operator_bounded (operator))
+	if (!_cairo_operator_bounded (operator) ||
+	    operator == CAIRO_OPERATOR_SOURCE ||
+	    operator == CAIRO_OPERATOR_CLEAR)
 	    status = _cairo_surface_composite_fixup_unbounded (&dst->base,
 							       &src_attr, src->width, src->height,
 							       mask ? &mask_attr : NULL,
@@ -2517,7 +2519,7 @@
 
 /* Handles clearing the regions that are outside of the temporary
  * mask created by XRenderCompositeText[N] but should be affected
- * by an unbounded operator like CAIRO_OPERATOR_SOURCE.
+ * by an unbounded operator like CAIRO_OPERATOR_IN
  */
 static cairo_status_t
 _show_glyphs_fixup_unbounded (cairo_xlib_surface_t       *self,



More information about the cairo-commit mailing list