Bug 1785744 [wpt PR 35504] - Recalc style for elements where :toggle() pseudo-class...
[gecko.git] / gfx / cairo / win32-ddb-dib.patch
bloba520d6e10ad37c71a2acc807e50e7a01a507159c
1 b=455513; add optional flag to allow converting a DDB to a DIB internally, if the surface is every used as a source; r=jmuizelaar
3 If a DDB is used as a source for an operation that can't be handled
4 natively by GDI, we end up needing to take a really slow path (creating a
5 temporary surface for acquire_source) for each operation. If we convert
6 the DDB to a DIB, we then end up having a real image buffer and can hand
7 things off to pixman directly.
9 This isn't the default mode because I'm not sure if there are cases where a
10 DDB is explicitly needed (e.g. for printing), and it would change
11 current cairo behaviour. It might become the default at some point in the
12 future.
14 diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h
15 --- a/gfx/cairo/cairo/src/cairo-win32-private.h
16 +++ b/gfx/cairo/cairo/src/cairo-win32-private.h
17 @@ -117,6 +117,9 @@
19 /* Whether we can use the CHECKJPEGFORMAT escape function */
20 CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
22 + /* if this DDB surface can be converted to a DIB if necessary */
23 + CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB = (1<<9),
26 cairo_status_t
27 diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
28 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c
29 +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
30 @@ -560,6 +560,56 @@
31 return CAIRO_STATUS_SUCCESS;
34 +static void
35 +_cairo_win32_convert_ddb_to_dib (cairo_win32_surface_t *surface)
37 + cairo_win32_surface_t *new_surface;
38 + int width = surface->extents.width;
39 + int height = surface->extents.height;
41 + BOOL ok;
42 + HBITMAP oldbitmap;
44 + new_surface = (cairo_win32_surface_t*)
45 + _cairo_win32_surface_create_for_dc (surface->dc,
46 + surface->format,
47 + width,
48 + height);
50 + if (new_surface->base.status)
51 + return;
53 + /* DDB can't be 32bpp, so BitBlt is safe */
54 + ok = BitBlt (new_surface->dc,
55 + 0, 0, width, height,
56 + surface->dc,
57 + 0, 0, SRCCOPY);
59 + if (!ok)
60 + goto out;
62 + /* Now swap around new_surface and surface's internal bitmap
63 + * pointers. */
64 + DeleteDC (new_surface->dc);
65 + new_surface->dc = NULL;
67 + oldbitmap = SelectObject (surface->dc, new_surface->bitmap);
68 + DeleteObject (oldbitmap);
70 + surface->image = new_surface->image;
71 + surface->is_dib = new_surface->is_dib;
72 + surface->bitmap = new_surface->bitmap;
74 + new_surface->bitmap = NULL;
75 + new_surface->image = NULL;
77 + /* Finally update flags */
78 + surface->flags = _cairo_win32_flags_for_dc (surface->dc);
80 + out:
81 + cairo_surface_destroy ((cairo_surface_t*)new_surface);
84 static cairo_status_t
85 _cairo_win32_surface_acquire_source_image (void *abstract_surface,
86 cairo_image_surface_t **image_out,
87 @@ -568,6 +618,17 @@
88 cairo_win32_surface_t *surface = abstract_surface;
89 cairo_win32_surface_t *local = NULL;
90 cairo_status_t status;
92 + if (!surface->image && !surface->is_dib && surface->bitmap &&
93 + (surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0)
94 + {
95 + /* This is a DDB, and we're being asked to use it as a source for
96 + * something that we couldn't support natively. So turn it into
97 + * a DIB, so that we have an equivalent image surface, as long
98 + * as we're allowed to via flags.
99 + */
100 + _cairo_win32_convert_ddb_to_dib (surface);
103 if (surface->image) {
104 *image_out = (cairo_image_surface_t *)surface->image;
105 @@ -2133,3 +2194,61 @@
106 free(rd);
107 fflush (stderr);
110 +/**
111 + * cairo_win32_surface_set_can_convert_to_dib
112 + * @surface: a #cairo_surface_t
113 + * @can_convert: a #cairo_bool_t indicating whether this surface can
114 + * be coverted to a DIB if necessary
116 + * A DDB surface with this flag set can be converted to a DIB if it's
117 + * used as a source in a way that GDI can't natively handle; for
118 + * example, drawing a RGB24 DDB onto an ARGB32 DIB. Doing this
119 + * conversion results in a significant speed optimization, because we
120 + * can call on pixman to perform the operation natively, instead of
121 + * reading the data from the DC each time.
123 + * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
124 + * changed, or an error otherwise.
125 + *
126 + */
127 +cairo_status_t
128 +cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t can_convert)
130 + cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
131 + if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
132 + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
134 + if (surface->bitmap) {
135 + if (can_convert)
136 + surface->flags |= CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
137 + else
138 + surface->flags &= ~CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
141 + return CAIRO_STATUS_SUCCESS;
144 +/**
145 + * cairo_win32_surface_get_can_convert_to_dib
146 + * @surface: a #cairo_surface_t
147 + * @can_convert: a #cairo_bool_t* that receives the return value
149 + * Returns the value of the flag indicating whether the surface can be
150 + * converted to a DIB if necessary, as set by
151 + * cairo_win32_surface_set_can_convert_to_dib.
153 + * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
154 + * retreived, or an error otherwise.
155 + *
156 + */
157 +cairo_status_t
158 +cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t *can_convert)
160 + cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
161 + if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
162 + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
164 + *can_convert = ((surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0);
165 + return CAIRO_STATUS_SUCCESS;
167 diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h
168 --- a/gfx/cairo/cairo/src/cairo-win32.h
169 +++ b/gfx/cairo/cairo/src/cairo-win32.h
170 @@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
171 cairo_public cairo_surface_t *
172 cairo_win32_surface_get_image (cairo_surface_t *surface);
174 +cairo_public cairo_status_t
175 +cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t can_convert);
177 +cairo_public cairo_status_t
178 +cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t *can_convert);
180 #if CAIRO_HAS_WIN32_FONT