gfx/cairo/gdi-RGB24-ARGB32.patch

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:5a4da10a61a4
1 changeset: 106848:28db6dbdd9ea
2 tag: gdi-patch
3 tag: qbase
4 tag: qtip
5 tag: tip
6 user: Jeff Muizelaar <jmuizelaar@mozilla.com>
7 date: Wed Sep 12 22:52:06 2012 -0400
8 summary: Bug 788794. Use BitBlt to do SOURCE and OVER from RGB24 to ARGB32. r=nical
9
10 diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
11 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c
12 +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
13 @@ -884,16 +884,28 @@ static cairo_int_status_t
14 src_x, src_y,
15 src_w, src_h,
16 blend_function))
17 return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
18
19 return CAIRO_STATUS_SUCCESS;
20 }
21
22 +/* makes the alpha channel in a RGB24 surface 0xff */
23 +static void
24 +make_opaque (cairo_image_surface_t *image, cairo_rectangle_int_t src_r)
25 +{
26 + int x; int y;
27 + for (y = src_r.y; y < src_r.height; y++) {
28 + for (x = src_r.x; x < src_r.width; x++) {
29 + image->data[y * image->stride + x*4 + 3] = 0xff;
30 + }
31 + }
32 +}
33 +
34 static cairo_int_status_t
35 _cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
36 cairo_image_surface_t *src_image,
37 cairo_win32_surface_t *dst,
38 cairo_rectangle_int_t src_extents,
39 cairo_rectangle_int_t src_r,
40 cairo_rectangle_int_t dst_r,
41 int alpha,
42 @@ -935,16 +947,24 @@ static cairo_int_status_t
43 src_r.width, - (int) src_r.height,
44 src_image->data,
45 &bi,
46 DIB_RGB_COLORS,
47 SRCCOPY))
48 return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
49 }
50 } else if (!needs_alpha) {
51 + if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32) {
52 + /* Because we store RGB24 & ARGB32 in the same way GDI has no way
53 + * to ignore the alpha channel from a RGB24 source. Therefore, we set
54 + * the alpha channel in our RGB24 source to opaque so that we can treat
55 + * it like ARGB32. */
56 + GdiFlush();
57 + make_opaque(src->image, src_r);
58 + }
59 /* BitBlt or StretchBlt? */
60 if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
61 if (!BitBlt (dst->dc,
62 dst_r.x, dst_r.y,
63 dst_r.width, dst_r.height,
64 src->dc,
65 src_r.x, src_r.y,
66 SRCCOPY))
67 @@ -1184,28 +1204,36 @@ static cairo_int_status_t
68 }
69 } else {
70 needs_repeat = TRUE;
71 }
72
73 /*
74 * Operations that we can do:
75 *
76 + * AlphaBlend uses the following formula for alpha when not use the per-pixel alpha (AlphaFormat = 0)
77 + * Dst.Alpha = Src.Alpha * (SCA/255.0) + Dst.Alpha * (1.0 - (SCA/255.0))
78 + * This turns into Dst.Alpha = Src.Alpha when SCA = 255.
79 + * (http://msdn.microsoft.com/en-us/library/aa921335.aspx)
80 + *
81 * RGB OVER RGB -> BitBlt (same as SOURCE)
82 - * RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
83 + * RGB OVER ARGB -> Partially supported, We convert this operation into a ARGB SOURCE ARGB
84 + * by setting the alpha values of the source to 255.
85 * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA
86 * ARGB OVER RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte
87 *
88 * RGB OVER RGB + mask -> AlphaBlend, no AC_SRC_ALPHA
89 - * RGB OVER ARGB + mask -> UNSUPPORTED
90 + * RGB OVER ARGB + mask -> Partially supported, We convert this operation into a ARGB OVER ARGB + mask
91 + * by setting the alpha values of the source to 255.
92 * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA
93 * ARGB OVER RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte
94 *
95 * RGB SOURCE RGB -> BitBlt
96 - * RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
97 + * RGB SOURCE ARGB -> Partially supported, We convert this operation into a ARGB SOURCE ARGB
98 + * by setting the alpha values of the source to 255.
99 * ARGB SOURCE ARGB -> BitBlt
100 * ARGB SOURCE RGB -> BitBlt
101 *
102 * RGB SOURCE RGB + mask -> unsupported
103 * RGB SOURCE ARGB + mask -> unsupported
104 * ARGB SOURCE ARGB + mask -> unsupported
105 * ARGB SOURCE RGB + mask -> unsupported
106 */
107 @@ -1222,22 +1250,32 @@ static cairo_int_status_t
108 needs_alpha = FALSE;
109 } else {
110 needs_alpha = TRUE;
111 }
112 } else if (src_format == CAIRO_FORMAT_ARGB32 &&
113 dst->format == CAIRO_FORMAT_RGB24)
114 {
115 needs_alpha = TRUE;
116 + } else if (src_format == CAIRO_FORMAT_RGB24 &&
117 + dst->format == CAIRO_FORMAT_ARGB32 &&
118 + src->image)
119 + {
120 + if (alpha == 255) {
121 + needs_alpha = FALSE;
122 + } else {
123 + needs_alpha = TRUE;
124 + }
125 } else {
126 goto UNSUPPORTED;
127 }
128 } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) {
129 if ((src_format == dst->format) ||
130 - (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24))
131 + (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24) ||
132 + (src_format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32 && src->image))
133 {
134 needs_alpha = FALSE;
135 } else {
136 goto UNSUPPORTED;
137 }
138 } else {
139 goto UNSUPPORTED;
140 }
141

mercurial