Source code

Revision control

Copy as Markdown

Other Tools

From 8b4a426f36d455f29210e966140ef9fee3ea75c6 Mon Sep 17 00:00:00 2001
From: Jonathan Kew <jkew@mozilla.com>
Date: Wed, 22 Apr 2026 13:00:22 -0700
Subject: [PATCH 09/29] Add cairo_quartz_surface_get_image
---
src/cairo-quartz-surface.c | 106 ++++++++++++++++++++++++++++++++++++-
src/cairo-quartz.h | 3 ++
2 files changed, 108 insertions(+), 1 deletion(-)
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index f3d2cd54e..fdcfbb071 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -409,6 +409,7 @@ _cairo_quartz_cairo_operator_to_quartz_blend (cairo_operator_t op)
default:
ASSERT_NOT_REACHED;
}
+ return kCGBlendModeNormal; /* unreached */
}
static cairo_int_status_t
@@ -998,7 +999,7 @@ _cairo_quartz_setup_pattern_source (cairo_quartz_drawing_state_t *state,
_cairo_surface_get_extents (&surface->base, &pattern_extents);
}
- if (source->extend == CAIRO_EXTEND_NONE) {
+ if (source->extend == CAIRO_EXTEND_NONE || source->extend == CAIRO_EXTEND_PAD) {
int x, y;
if (op == CAIRO_OPERATOR_SOURCE &&
@@ -1401,6 +1402,97 @@ _cairo_quartz_surface_unmap_image (void *abstract_surface,
}
+/*
+ * get source/dest image implementation
+ */
+
+/* Read the image from the surface's front buffer */
+static cairo_int_status_t
+_cairo_quartz_get_image (cairo_quartz_surface_t *surface,
+ cairo_image_surface_t **image_out)
+{
+ unsigned char *imageData;
+ cairo_image_surface_t *isurf;
+
+ if (_cairo_quartz_is_zero_surface (&surface->base)) {
+ *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (_cairo_quartz_is_cgcontext_bitmap_context(surface->cgContext)) {
+ unsigned int stride;
+ unsigned int bitinfo;
+ unsigned int bpc, bpp;
+ CGColorSpaceRef colorspace;
+ unsigned int color_comps;
+
+ CGContextFlush(surface->cgContext);
+ imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext);
+
+#ifdef USE_10_3_WORKAROUNDS
+ bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext);
+#else
+ bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext);
+#endif
+ stride = CGBitmapContextGetBytesPerRow (surface->cgContext);
+ bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext);
+ bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext);
+
+ // let's hope they don't add YUV under us
+ colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
+ color_comps = CGColorSpaceGetNumberOfComponents(colorspace);
+
+ // XXX TODO: We can handle all of these by converting to
+ // pixman masks, including non-native-endian masks
+ if (bpc != 8)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (bpp != 32 && bpp != 8)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (color_comps != 3 && color_comps != 1)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (bpp == 32 && color_comps == 3 &&
+ (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst &&
+ (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
+ {
+ isurf = (cairo_image_surface_t *)
+ cairo_image_surface_create_for_data (imageData,
+ CAIRO_FORMAT_ARGB32,
+ surface->extents.width,
+ surface->extents.height,
+ stride);
+ } else if (bpp == 32 && color_comps == 3 &&
+ (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst &&
+ (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
+ {
+ isurf = (cairo_image_surface_t *)
+ cairo_image_surface_create_for_data (imageData,
+ CAIRO_FORMAT_RGB24,
+ surface->extents.width,
+ surface->extents.height,
+ stride);
+ } else if (bpp == 8 && color_comps == 1)
+ {
+ isurf = (cairo_image_surface_t *)
+ cairo_image_surface_create_for_data (imageData,
+ CAIRO_FORMAT_A8,
+ surface->extents.width,
+ surface->extents.height,
+ stride);
+ } else {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ } else {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ *image_out = isurf;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+
/*
* Cairo surface backend implementations
*/
@@ -2478,3 +2570,15 @@ _cairo_quartz_surface_to_png (cairo_surface_t *abstract_surface, const char *des
CGImageRelease (image);
return CAIRO_STATUS_SUCCESS;
}
+
+cairo_surface_t *
+cairo_quartz_surface_get_image (cairo_surface_t *surface)
+{
+ cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *)surface;
+ cairo_image_surface_t *image;
+
+ if (_cairo_quartz_get_image(quartz, &image))
+ return NULL;
+
+ return (cairo_surface_t *)image;
+}
diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h
index 9e11e876f..14482424a 100644
--- a/src/cairo-quartz.h
+++ b/src/cairo-quartz.h
@@ -57,6 +57,9 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
cairo_public CGContextRef
cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
+cairo_public cairo_surface_t *
+cairo_quartz_surface_get_image (cairo_surface_t *surface);
+
#if CAIRO_HAS_QUARTZ_FONT
/*
--
2.53.0