forked from mirrors/gecko-dev
Bug 1900028 - Handle CAIRO_FORMAT_A8 in _cairo_surface_to_cgimage for masking operations. r=gfx-reviewers,lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D212354
This commit is contained in:
parent
ef05d7cc23
commit
50d383bca2
2 changed files with 214 additions and 6 deletions
124
gfx/cairo/26-quartz-surface-mask.patch
Normal file
124
gfx/cairo/26-quartz-surface-mask.patch
Normal file
|
|
@ -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;
|
||||
|
|
@ -684,6 +684,55 @@ CairoQuartzCreateGradientFunction (const cairo_gradient_pattern_t *gradient,
|
|||
&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 @@ _cairo_surface_to_cgimage (cairo_surface_t *source,
|
|||
&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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue