[cairo-commit] cairo/src cairo_glitz_surface.c, 1.22, 1.23 cairo_pattern.c, 1.25, 1.26 cairo_win32_surface.c, 1.7, 1.8 cairoint.h, 1.102, 1.103

Owen Taylor commit at pdx.freedesktop.org
Fri Mar 4 09:41:36 PST 2005


Committed by: otaylor

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

Modified Files:
	cairo_glitz_surface.c cairo_pattern.c cairo_win32_surface.c 
	cairoint.h 
Log Message:
2005-03-04  Owen Taylor  <otaylor at redhat.com>

	* src/cairoint.h src/cairo_pattern.c src/cairo_glitz_surface.c:
	Add _cairo_pattern_is_opaque, use it rather than 
	pattern->alpha == 1.0.

Index: cairo_glitz_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_glitz_surface.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- cairo_glitz_surface.c	4 Mar 2005 02:55:28 -0000	1.22
+++ cairo_glitz_surface.c	4 Mar 2005 17:41:34 -0000	1.23
@@ -556,7 +556,7 @@
 
 	/* can't do alpha as gradient color interpolation must be done to
 	   unpremultiplied colors. */
-	if (pattern->alpha != 1.0)
+	if (_cairo_pattern_is_opaque (pattern))
 	    break;
 
 	/* glitz doesn't support inner and outer circle with different
@@ -730,28 +730,46 @@
 {
     cairo_int_status_t	  status;
     cairo_pattern_union_t tmp;
+    cairo_bool_t          src_opaque, mask_opaque;
     double		  src_alpha, mask_alpha;
 
-    if (src->type != CAIRO_PATTERN_SOLID)
+    src_opaque = _cairo_pattern_is_opaque (src);
+    mask_opaque = !mask || _cairo_pattern_is_opaque (mask);
+    
+    /* For surface patterns, we move any translucency from src->alpha
+     * to mask->alpha so we can use the source unchanged. Otherwise we
+     * move the translucency from mask->alpha to src->alpha so that
+     * we can drop the mask if possible.
+     */
+    if (src->type == CAIRO_PATTERN_SURFACE)
     {
-	if (mask)
+	if (mask) {
+	    mask_opaque = mask_opaque && src_opaque;
 	    mask_alpha = mask->alpha * src->alpha;
-	else
+	} else {
+	    mask_opaque = src_opaque;
 	    mask_alpha = src->alpha;
+	}
 	
 	src_alpha = 1.0;
+	src_opaque = TRUE;
     }
     else
     {
 	if (mask)
 	{
+	    src_opaque = mask_opaque && src_opaque;
 	    src_alpha = mask->alpha * src->alpha;
+	    /* FIXME: This needs changing when we support RENDER
+	     * style 4-channel masks.
+	     */
 	    if (mask->type == CAIRO_PATTERN_SOLID)
 		mask = NULL;
 	} else
 	    src_alpha = src->alpha;
 
 	mask_alpha = 1.0;
+	mask_opaque = TRUE;
     }
 
     _cairo_pattern_init_copy (&tmp.base, src);
@@ -767,7 +785,7 @@
     if (status)
 	return status;
 
-    if (mask || mask_alpha != 1.0)
+    if (mask || !mask_opaque)
     {
 	if (mask)
 	    _cairo_pattern_init_copy (&tmp.base, mask);

Index: cairo_pattern.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_pattern.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- cairo_pattern.c	4 Mar 2005 02:46:49 -0000	1.25
+++ cairo_pattern.c	4 Mar 2005 17:41:34 -0000	1.26
@@ -913,6 +913,32 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+
+/**
+ * _cairo_pattern_is_opaque
+ *
+ * Convenience function to determine whether a pattern has an opaque
+ * alpha value. This is done by testing whether the pattern's alpha
+ * value when converted to a byte is 255, so if a backend actually
+ * supported deep alpha channels this function might not do the right
+ * thing.
+ *
+ * Note that for a gradient or surface pattern, the overall resulting
+ * alpha for the pattern can be non-opaque even this function returns
+ * %TRUE, since the resulting alpha is the multiplication of the
+ * alpha of the gradient or surface with the pattern's alpha. In
+ * the future, alpha will be moved from the base pattern to the
+ * solid pattern subtype, at which point this function should
+ * probably be renamed to _cairo_pattern_is_opaque_solid()
+ *
+ * Return value: %TRUE if the pattern is opaque
+ **/
+cairo_bool_t 
+_cairo_pattern_is_opaque (cairo_pattern_t *pattern)
+{
+  return (pattern->alpha >= ((double)0xff00 / (double)0xffff));
+}
+
 static cairo_int_status_t
 _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 					    cairo_surface_t	       *dst,
@@ -928,7 +954,7 @@
     attr->acquired = FALSE;
     
     /* handle pattern opacity */
-    if (pattern->base.alpha != 1.0)
+    if (!_cairo_pattern_is_opaque (&pattern->base))
     {
 	cairo_surface_pattern_t tmp;
 	cairo_color_t		color;
@@ -1130,29 +1156,48 @@
 				 cairo_surface_attributes_t *mask_attributes)
 {
     cairo_int_status_t	  status;
+
     cairo_pattern_union_t tmp;
+    cairo_bool_t          src_opaque, mask_opaque;
     double		  src_alpha, mask_alpha;
 
+    src_opaque = _cairo_pattern_is_opaque (src);
+    mask_opaque = !mask || _cairo_pattern_is_opaque (mask);
+    
+    /* For surface patterns, we move any translucency from src->alpha
+     * to mask->alpha so we can use the source unchanged. Otherwise we
+     * move the translucency from mask->alpha to src->alpha so that
+     * we can drop the mask if possible.
+     */
     if (src->type == CAIRO_PATTERN_SURFACE)
     {
-	if (mask)
+	if (mask) {
+	    mask_opaque = mask_opaque && src_opaque;
 	    mask_alpha = mask->alpha * src->alpha;
-	else
+	} else {
+	    mask_opaque = src_opaque;
 	    mask_alpha = src->alpha;
+	}
 	
 	src_alpha = 1.0;
+	src_opaque = TRUE;
     }
     else
     {
 	if (mask)
 	{
+	    src_opaque = mask_opaque && src_opaque;
 	    src_alpha = mask->alpha * src->alpha;
+	    /* FIXME: This needs changing when we support RENDER
+	     * style 4-channel masks.
+	     */
 	    if (mask->type == CAIRO_PATTERN_SOLID)
 		mask = NULL;
 	} else
 	    src_alpha = src->alpha;
 
 	mask_alpha = 1.0;
+	mask_opaque = TRUE;
     }
 
     _cairo_pattern_init_copy (&tmp.base, src);
@@ -1168,7 +1213,7 @@
     if (status)
 	return status;
 
-    if (mask || mask_alpha != 1.0)
+    if (mask || !mask_opaque)
     {
 	if (mask)
 	    _cairo_pattern_init_copy (&tmp.base, mask);

Index: cairo_win32_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_win32_surface.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cairo_win32_surface.c	24 Feb 2005 23:48:07 -0000	1.7
+++ cairo_win32_surface.c	4 Mar 2005 17:41:34 -0000	1.8
@@ -591,7 +591,7 @@
 static cairo_int_status_t
 _cairo_win32_surface_composite (cairo_operator_t	operator,
 				cairo_pattern_t       	*pattern,
-				cairo_surface_t	        *generic_mask,
+			       cairo_pattern_t		*mask_pattern,
 				void			*abstract_dst,
 				int			src_x,
 				int			src_y,
@@ -604,7 +604,7 @@
 {
     cairo_win32_surface_t *dst = abstract_dst;
     cairo_win32_surface_t *src;
-    cairo_win32_surface_t *mask = (cairo_win32_surface_t *)generic_mask;
+    cairo_win32_surface_t *mask;
     int alpha;
     int integer_transform;
     int itx, ity;

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.102
retrieving revision 1.103
diff -u -d -r1.102 -r1.103
--- cairoint.h	4 Mar 2005 02:39:06 -0000	1.102
+++ cairoint.h	4 Mar 2005 17:41:34 -0000	1.103
@@ -1715,6 +1715,9 @@
 _cairo_pattern_transform (cairo_pattern_t *pattern,
 			  cairo_matrix_t *ctm_inverse);
 
+cairo_private cairo_bool_t 
+_cairo_pattern_is_opaque (cairo_pattern_t *pattern);
+
 cairo_private cairo_int_status_t
 _cairo_pattern_acquire_surface (cairo_pattern_t		   *pattern,
 				cairo_surface_t		   *dst,




More information about the cairo-commit mailing list