Bug 1857841 - pt 3. Add a new page kind named "fresh" r=glandium
[gecko.git] / gfx / cairo / 09-quartz-surface-additions.patch
blob104d453f4f2ad95bc73552acbd4ca9aedcb4d85b
1 diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
2 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h
3 +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
4 @@ -71,8 +71,11 @@ typedef struct cairo_quartz_surface {
5 cairo_surface_t *imageSurfaceEquiv;
7 cairo_surface_clipper_t clipper;
9 cairo_rectangle_int_t extents;
10 cairo_rectangle_int_t virtual_extents;
12 + cairo_bool_t ownsData;
13 } cairo_quartz_surface_t;
15 typedef struct cairo_quartz_image_surface {
16 diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
17 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
18 +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
19 @@ -1520,6 +1520,103 @@ static cairo_int_status_t
23 + * get source/dest image implementation
24 + */
26 +/* Read the image from the surface's front buffer */
27 +static cairo_int_status_t
28 +_cairo_quartz_get_image (cairo_quartz_surface_t *surface,
29 + cairo_image_surface_t **image_out)
31 + unsigned char *imageData;
32 + cairo_image_surface_t *isurf;
34 + if (IS_EMPTY(surface)) {
35 + *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
36 + return CAIRO_STATUS_SUCCESS;
37 + }
39 + if (surface->imageSurfaceEquiv) {
40 + CGContextFlush(surface->cgContext);
41 + *image_out = (cairo_image_surface_t*) cairo_surface_reference(surface->imageSurfaceEquiv);
42 + return CAIRO_STATUS_SUCCESS;
43 + }
45 + if (_cairo_quartz_is_cgcontext_bitmap_context(surface->cgContext)) {
46 + unsigned int stride;
47 + unsigned int bitinfo;
48 + unsigned int bpc, bpp;
49 + CGColorSpaceRef colorspace;
50 + unsigned int color_comps;
52 + CGContextFlush(surface->cgContext);
53 + imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext);
55 +#ifdef USE_10_3_WORKAROUNDS
56 + bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext);
57 +#else
58 + bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext);
59 +#endif
60 + stride = CGBitmapContextGetBytesPerRow (surface->cgContext);
61 + bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext);
62 + bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext);
64 + // let's hope they don't add YUV under us
65 + colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
66 + color_comps = CGColorSpaceGetNumberOfComponents(colorspace);
68 + // XXX TODO: We can handle all of these by converting to
69 + // pixman masks, including non-native-endian masks
70 + if (bpc != 8)
71 + return CAIRO_INT_STATUS_UNSUPPORTED;
73 + if (bpp != 32 && bpp != 8)
74 + return CAIRO_INT_STATUS_UNSUPPORTED;
76 + if (color_comps != 3 && color_comps != 1)
77 + return CAIRO_INT_STATUS_UNSUPPORTED;
79 + if (bpp == 32 && color_comps == 3 &&
80 + (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst &&
81 + (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
82 + {
83 + isurf = (cairo_image_surface_t *)
84 + cairo_image_surface_create_for_data (imageData,
85 + CAIRO_FORMAT_ARGB32,
86 + surface->extents.width,
87 + surface->extents.height,
88 + stride);
89 + } else if (bpp == 32 && color_comps == 3 &&
90 + (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst &&
91 + (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
92 + {
93 + isurf = (cairo_image_surface_t *)
94 + cairo_image_surface_create_for_data (imageData,
95 + CAIRO_FORMAT_RGB24,
96 + surface->extents.width,
97 + surface->extents.height,
98 + stride);
99 + } else if (bpp == 8 && color_comps == 1)
101 + isurf = (cairo_image_surface_t *)
102 + cairo_image_surface_create_for_data (imageData,
103 + CAIRO_FORMAT_A8,
104 + surface->extents.width,
105 + surface->extents.height,
106 + stride);
107 + } else {
108 + return CAIRO_INT_STATUS_UNSUPPORTED;
110 + } else {
111 + return CAIRO_INT_STATUS_UNSUPPORTED;
114 + *image_out = isurf;
115 + return CAIRO_STATUS_SUCCESS;
120 * Cairo surface backend implementations
123 @@ -1542,11 +1639,14 @@ static cairo_status_t
124 surface->cgContext = NULL;
126 if (surface->imageSurfaceEquiv) {
127 + if (surface->ownsData)
128 + _cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv);
129 cairo_surface_destroy (surface->imageSurfaceEquiv);
130 surface->imageSurfaceEquiv = NULL;
131 + } else if (surface->imageData && surface->ownsData) {
132 + free (surface->imageData);
135 - free (surface->imageData);
136 surface->imageData = NULL;
138 return CAIRO_STATUS_SUCCESS;
139 @@ -2298,6 +2398,8 @@ cairo_quartz_surface_t *
140 surface->cgContext = cgContext;
141 surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
143 + surface->ownsData = TRUE;
145 return surface;
148 @@ -2452,10 +2554,124 @@ cairo_quartz_surface_create (cairo_forma
149 surf->imageData = imageData;
150 surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride);
152 + // We created this data, so we can delete it.
153 + surf->ownsData = TRUE;
155 return &surf->base;
159 + * cairo_quartz_surface_create_for_data
160 + * @data: a pointer to a buffer supplied by the application in which
161 + * to write contents. This pointer must be suitably aligned for any
162 + * kind of variable, (for example, a pointer returned by malloc).
163 + * @format: format of pixels in the surface to create
164 + * @width: width of the surface, in pixels
165 + * @height: height of the surface, in pixels
167 + * Creates a Quartz surface backed by a CGBitmap. The surface is
168 + * created using the Device RGB (or Device Gray, for A8) color space.
169 + * All Cairo operations, including those that require software
170 + * rendering, will succeed on this surface.
172 + * Return value: the newly created surface.
174 + * Since: 1.12 [Mozilla addition]
175 + **/
176 +cairo_surface_t *
177 +cairo_quartz_surface_create_for_data (unsigned char *data,
178 + cairo_format_t format,
179 + unsigned int width,
180 + unsigned int height,
181 + unsigned int stride)
183 + cairo_quartz_surface_t *surf;
184 + CGContextRef cgc;
185 + CGColorSpaceRef cgColorspace;
186 + CGBitmapInfo bitinfo;
187 + void *imageData = data;
188 + int bitsPerComponent;
189 + unsigned int i;
191 + // verify width and height of surface
192 + if (!_cairo_quartz_verify_surface_size(width, height))
193 + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
195 + if (width == 0 || height == 0) {
196 + return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format),
197 + width, height);
200 + if (format == CAIRO_FORMAT_ARGB32 ||
201 + format == CAIRO_FORMAT_RGB24)
203 + cgColorspace = CGColorSpaceCreateDeviceRGB();
204 + bitinfo = kCGBitmapByteOrder32Host;
205 + if (format == CAIRO_FORMAT_ARGB32)
206 + bitinfo |= kCGImageAlphaPremultipliedFirst;
207 + else
208 + bitinfo |= kCGImageAlphaNoneSkipFirst;
209 + bitsPerComponent = 8;
210 + } else if (format == CAIRO_FORMAT_A8) {
211 + cgColorspace = NULL;
212 + bitinfo = kCGImageAlphaOnly;
213 + bitsPerComponent = 8;
214 + } else if (format == CAIRO_FORMAT_A1) {
215 + /* I don't think we can usefully support this, as defined by
216 + * cairo_format_t -- these are 1-bit pixels stored in 32-bit
217 + * quantities.
218 + */
219 + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
220 + } else {
221 + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
224 + cgc = CGBitmapContextCreate (imageData,
225 + width,
226 + height,
227 + bitsPerComponent,
228 + stride,
229 + cgColorspace,
230 + bitinfo);
231 + CGColorSpaceRelease (cgColorspace);
233 + if (!cgc) {
234 + free (imageData);
235 + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
238 + /* flip the Y axis */
239 + CGContextTranslateCTM (cgc, 0.0, height);
240 + CGContextScaleCTM (cgc, 1.0, -1.0);
242 + surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format),
243 + width, height);
244 + if (surf->base.status) {
245 + CGContextRelease (cgc);
246 + free (imageData);
247 + // create_internal will have set an error
248 + return (cairo_surface_t*) surf;
251 + surf->imageData = imageData;
253 + cairo_surface_t* tmpImageSurfaceEquiv =
254 + cairo_image_surface_create_for_data (imageData, format,
255 + width, height, stride);
257 + if (cairo_surface_status (tmpImageSurfaceEquiv)) {
258 + // Tried & failed to create an imageSurfaceEquiv!
259 + cairo_surface_destroy (tmpImageSurfaceEquiv);
260 + surf->imageSurfaceEquiv = NULL;
261 + } else {
262 + surf->imageSurfaceEquiv = tmpImageSurfaceEquiv;
263 + surf->ownsData = FALSE;
266 + return (cairo_surface_t *) surf;
269 +/**
270 * cairo_quartz_surface_get_cg_context:
271 * @surface: the Cairo Quartz surface
273 @@ -2497,6 +2713,18 @@ cairo_bool_t
274 return surface->backend == &cairo_quartz_surface_backend;
277 +cairo_surface_t *
278 +cairo_quartz_surface_get_image (cairo_surface_t *surface)
280 + cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *)surface;
281 + cairo_image_surface_t *image;
283 + if (_cairo_quartz_get_image(quartz, &image))
284 + return NULL;
286 + return (cairo_surface_t *)image;
289 /* Debug stuff */
291 #ifdef QUARTZ_DEBUG
292 diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h
293 --- a/gfx/cairo/cairo/src/cairo-quartz.h
294 +++ b/gfx/cairo/cairo/src/cairo-quartz.h
295 @@ -54,9 +54,19 @@ cairo_quartz_surface_create_for_cg_conte
296 unsigned int width,
297 unsigned int height);
299 +cairo_surface_t *
300 +cairo_quartz_surface_create_for_data (unsigned char *data,
301 + cairo_format_t format,
302 + unsigned int width,
303 + unsigned int height,
304 + unsigned int stride);
306 cairo_public CGContextRef
307 cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
309 +cairo_public cairo_surface_t *
310 +cairo_quartz_surface_get_image (cairo_surface_t *surface);
312 #if CAIRO_HAS_QUARTZ_FONT