DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (31ec81b5d7bb)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
changeset:   106848:28db6dbdd9ea
tag:         gdi-patch
tag:         qbase
tag:         qtip
tag:         tip
user:        Jeff Muizelaar <jmuizelaar@mozilla.com>
date:        Wed Sep 12 22:52:06 2012 -0400
summary:     Bug 788794. Use BitBlt to do SOURCE and OVER from RGB24 to ARGB32. r=nical

diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
+++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
@@ -884,16 +884,28 @@ static cairo_int_status_t
 		      src_x, src_y,
 		      src_w, src_h,
 		      blend_function))
 	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+/* makes the alpha channel in a RGB24 surface 0xff */
+static void
+make_opaque (cairo_image_surface_t *image, cairo_rectangle_int_t src_r)
+{
+    int x; int y;
+    for (y = src_r.y; y < src_r.height; y++) {
+        for (x = src_r.x; x < src_r.width; x++) {
+            image->data[y * image->stride + x*4 + 3] = 0xff;
+        }
+    }
+}
+
 static cairo_int_status_t
 _cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
 				      cairo_image_surface_t *src_image,
 				      cairo_win32_surface_t *dst,
 				      cairo_rectangle_int_t src_extents,
 				      cairo_rectangle_int_t src_r,
 				      cairo_rectangle_int_t dst_r,
 				      int alpha,
@@ -935,16 +947,24 @@ static cairo_int_status_t
 				src_r.width, - (int) src_r.height,
 				src_image->data,
 				&bi,
 				DIB_RGB_COLORS,
 				SRCCOPY))
 		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
 	}
     } else if (!needs_alpha) {
+	if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32) {
+	    /* Because we store RGB24 & ARGB32 in the same way GDI has no way
+	     * to ignore the alpha channel from a RGB24 source. Therefore, we set
+	     * the alpha channel in our RGB24 source to opaque so that we can treat
+	     * it like ARGB32. */
+	    GdiFlush();
+	    make_opaque(src->image, src_r);
+	}
 	/* BitBlt or StretchBlt? */
 	if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
             if (!BitBlt (dst->dc,
 			 dst_r.x, dst_r.y,
 			 dst_r.width, dst_r.height,
 			 src->dc,
 			 src_r.x, src_r.y,
 			 SRCCOPY))
@@ -1184,28 +1204,36 @@ static cairo_int_status_t
 	}
     } else {
 	needs_repeat = TRUE;
     }
 
     /*
      * Operations that we can do:
      *
+     * AlphaBlend uses the following formula for alpha when not use the per-pixel alpha (AlphaFormat = 0)
+     *   Dst.Alpha = Src.Alpha * (SCA/255.0) + Dst.Alpha * (1.0 - (SCA/255.0))
+     * This turns into Dst.Alpha = Src.Alpha when SCA = 255.
+     * (http://msdn.microsoft.com/en-us/library/aa921335.aspx)
+     *
      *  RGB OVER  RGB -> BitBlt (same as SOURCE)
-     *  RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
+     *  RGB OVER ARGB -> Partially supported, We convert this operation into a ARGB SOURCE ARGB
+     *                   by setting the alpha values of the source to 255.
      * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA
      * ARGB OVER  RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte
      * 
      *  RGB OVER  RGB + mask -> AlphaBlend, no AC_SRC_ALPHA
-     *  RGB OVER ARGB + mask -> UNSUPPORTED
+     *  RGB OVER ARGB + mask -> Partially supported, We convert this operation into a ARGB OVER ARGB + mask
+     *                          by setting the alpha values of the source to 255.
      * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA
      * ARGB OVER  RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte
      * 
      *  RGB SOURCE  RGB -> BitBlt
-     *  RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
+     *  RGB SOURCE ARGB -> Partially supported, We convert this operation into a ARGB SOURCE ARGB
+     *                     by setting the alpha values of the source to 255.
      * ARGB SOURCE ARGB -> BitBlt
      * ARGB SOURCE  RGB -> BitBlt
      * 
      *  RGB SOURCE  RGB + mask -> unsupported
      *  RGB SOURCE ARGB + mask -> unsupported
      * ARGB SOURCE ARGB + mask -> unsupported
      * ARGB SOURCE  RGB + mask -> unsupported
      */
@@ -1222,22 +1250,32 @@ static cairo_int_status_t
 		needs_alpha = FALSE;
 	    } else {
 		needs_alpha = TRUE;
 	    }
 	} else if (src_format == CAIRO_FORMAT_ARGB32 &&
 		   dst->format == CAIRO_FORMAT_RGB24)
 	{
 	    needs_alpha = TRUE;
+	} else if (src_format == CAIRO_FORMAT_RGB24 &&
+		   dst->format == CAIRO_FORMAT_ARGB32 &&
+		   src->image)
+	{
+	    if (alpha == 255) {
+		needs_alpha = FALSE;
+	    } else {
+		needs_alpha = TRUE;
+	    }
 	} else {
 	    goto UNSUPPORTED;
 	}
     } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) {
 	if ((src_format == dst->format) ||
-	    (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24))
+	    (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24) ||
+	    (src_format == CAIRO_FORMAT_RGB24  && dst->format == CAIRO_FORMAT_ARGB32 && src->image))
 	{
 	    needs_alpha = FALSE;
 	} else {
 	    goto UNSUPPORTED;
 	}
     } else {
 	goto UNSUPPORTED;
     }