From 8b4a426f36d455f29210e966140ef9fee3ea75c6 Mon Sep 17 00:00:00 2001 From: Jonathan Kew 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