summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/26-quartz-surface-mask.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/26-quartz-surface-mask.patch')
-rw-r--r--gfx/cairo/26-quartz-surface-mask.patch124
1 files changed, 124 insertions, 0 deletions
diff --git a/gfx/cairo/26-quartz-surface-mask.patch b/gfx/cairo/26-quartz-surface-mask.patch
new file mode 100644
index 0000000000..dd5c71c07a
--- /dev/null
+++ b/gfx/cairo/26-quartz-surface-mask.patch
@@ -0,0 +1,124 @@
+# HG changeset patch
+# User Jonathan Kew <jkew@mozilla.com>
+# Date 1717237382 -3600
+# Sat Jun 01 11:23:02 2024 +0100
+# Node ID d5f7b9fd904e04406c56899c5cac9248b122ea35
+# Parent c8d3e447c892474e061c9ffd22ec1823f06ecffa
+Bug 1900028 - Handle CAIRO_FORMAT_A8 in _cairo_surface_to_cgimage for masking operations.
+
+Differential Revision: https://phabricator.services.mozilla.com/D212354
+
+diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
+--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
+@@ -684,6 +684,55 @@ CairoQuartzCreateGradientFunction (const
+ &gradient_callbacks);
+ }
+
++static CGImageRef
++CairoQuartzCreateCGImageMask (cairo_format_t format,
++ unsigned int width,
++ unsigned int height,
++ unsigned int stride,
++ void *data,
++ cairo_bool_t interpolate,
++ CGDataProviderReleaseDataCallback releaseCallback,
++ void *releaseInfo)
++{
++ CGImageRef image = NULL;
++ CGDataProviderRef dataProvider = NULL;
++ int bitsPerComponent = 8, bitsPerPixel = 8;
++
++ if (format != CAIRO_FORMAT_A8)
++ return NULL;
++
++ dataProvider = CGDataProviderCreateWithData (releaseInfo,
++ data,
++ height * stride,
++ releaseCallback);
++
++ if (unlikely (!dataProvider)) {
++ // manually release
++ if (releaseCallback)
++ releaseCallback (releaseInfo, data, height * stride);
++ goto FINISH;
++ }
++
++ cairo_quartz_float_t decode[] = {1.0, 0.0};
++ image = CGImageMaskCreate (width, height,
++ bitsPerComponent,
++ bitsPerPixel,
++ stride,
++ dataProvider,
++ decode,
++ interpolate);
++
++FINISH:
++ CGDataProviderRelease (dataProvider);
++ return image;
++}
++
++static void
++DataProviderReleaseCallback (void *info, const void *data, size_t size)
++{
++ free (info);
++}
++
+ static cairo_status_t
+ _cairo_surface_to_cgimage (cairo_surface_t *source,
+ cairo_rectangle_int_t *extents,
+@@ -742,13 +791,48 @@ static cairo_status_t
+ &image_extra);
+ if (unlikely (status))
+ return status;
+- image_surface =
+- (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base);
+- status = image_surface->base.status;
+- if (status)
++
++ if (surface->format == CAIRO_FORMAT_A8) {
++ /* cairo_quartz_image_surface_create doesn't handle CAIRO_FORMAT_A8,
++ * so we create a CGImage manually here for masking operations.
++ */
++ void* image_data = _cairo_malloc_ab (surface->height, surface->stride);
++ if (unlikely (!image_data))
++ {
++ _cairo_surface_release_source_image (source, surface, image_extra);
++ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
++ }
++
++ /* The last row of data may have less than stride bytes so make sure we
++ * only copy the minimum amount required from that row.
++ */
++ memcpy (image_data, surface->data,
++ (surface->height - 1) * surface->stride +
++ cairo_format_stride_for_width (surface->format,
++ surface->width));
++ *image_out = CairoQuartzCreateCGImageMask (surface->format,
++ surface->width,
++ surface->height,
++ surface->stride,
++ image_data,
++ TRUE,
++ DataProviderReleaseCallback,
++ image_data);
++ /* TODO: differentiate memory error and unsupported surface type */
++ if (unlikely (*image_out == NULL))
++ status = CAIRO_INT_STATUS_UNSUPPORTED;
++
+ _cairo_surface_release_source_image (source, surface, image_extra);
+- else
+- acquired = TRUE;
++ return status;
++ } else {
++ image_surface =
++ (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base);
++ status = image_surface->base.status;
++ if (status)
++ _cairo_surface_release_source_image (source, surface, image_extra);
++ else
++ acquired = TRUE;
++ }
+ }
+
+ *image_out = NULL;