|
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 |