summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/09-quartz-surface-additions.patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/cairo/09-quartz-surface-additions.patch314
1 files changed, 314 insertions, 0 deletions
diff --git a/gfx/cairo/09-quartz-surface-additions.patch b/gfx/cairo/09-quartz-surface-additions.patch
new file mode 100644
index 0000000000..104d453f4f
--- /dev/null
+++ b/gfx/cairo/09-quartz-surface-additions.patch
@@ -0,0 +1,314 @@
+diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
+--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
++++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
+@@ -71,8 +71,11 @@ typedef struct cairo_quartz_surface {
+ cairo_surface_t *imageSurfaceEquiv;
+
+ cairo_surface_clipper_t clipper;
++
+ cairo_rectangle_int_t extents;
+ cairo_rectangle_int_t virtual_extents;
++
++ cairo_bool_t ownsData;
+ } cairo_quartz_surface_t;
+
+ typedef struct cairo_quartz_image_surface {
+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
+@@ -1520,6 +1520,103 @@ static cairo_int_status_t
+
+
+ /*
++ * 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 (IS_EMPTY(surface)) {
++ *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
++ return CAIRO_STATUS_SUCCESS;
++ }
++
++ if (surface->imageSurfaceEquiv) {
++ CGContextFlush(surface->cgContext);
++ *image_out = (cairo_image_surface_t*) cairo_surface_reference(surface->imageSurfaceEquiv);
++ 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
+ */
+
+@@ -1542,11 +1639,14 @@ static cairo_status_t
+ surface->cgContext = NULL;
+
+ if (surface->imageSurfaceEquiv) {
++ if (surface->ownsData)
++ _cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv);
+ cairo_surface_destroy (surface->imageSurfaceEquiv);
+ surface->imageSurfaceEquiv = NULL;
++ } else if (surface->imageData && surface->ownsData) {
++ free (surface->imageData);
+ }
+
+- free (surface->imageData);
+ surface->imageData = NULL;
+
+ return CAIRO_STATUS_SUCCESS;
+@@ -2298,6 +2398,8 @@ cairo_quartz_surface_t *
+ surface->cgContext = cgContext;
+ surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
+
++ surface->ownsData = TRUE;
++
+ return surface;
+ }
+
+@@ -2452,10 +2554,124 @@ cairo_quartz_surface_create (cairo_forma
+ surf->imageData = imageData;
+ surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride);
+
++ // We created this data, so we can delete it.
++ surf->ownsData = TRUE;
++
+ return &surf->base;
+ }
+
+ /**
++ * cairo_quartz_surface_create_for_data
++ * @data: a pointer to a buffer supplied by the application in which
++ * to write contents. This pointer must be suitably aligned for any
++ * kind of variable, (for example, a pointer returned by malloc).
++ * @format: format of pixels in the surface to create
++ * @width: width of the surface, in pixels
++ * @height: height of the surface, in pixels
++ *
++ * Creates a Quartz surface backed by a CGBitmap. The surface is
++ * created using the Device RGB (or Device Gray, for A8) color space.
++ * All Cairo operations, including those that require software
++ * rendering, will succeed on this surface.
++ *
++ * Return value: the newly created surface.
++ *
++ * Since: 1.12 [Mozilla addition]
++ **/
++cairo_surface_t *
++cairo_quartz_surface_create_for_data (unsigned char *data,
++ cairo_format_t format,
++ unsigned int width,
++ unsigned int height,
++ unsigned int stride)
++{
++ cairo_quartz_surface_t *surf;
++ CGContextRef cgc;
++ CGColorSpaceRef cgColorspace;
++ CGBitmapInfo bitinfo;
++ void *imageData = data;
++ int bitsPerComponent;
++ unsigned int i;
++
++ // verify width and height of surface
++ if (!_cairo_quartz_verify_surface_size(width, height))
++ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
++
++ if (width == 0 || height == 0) {
++ return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format),
++ width, height);
++ }
++
++ if (format == CAIRO_FORMAT_ARGB32 ||
++ format == CAIRO_FORMAT_RGB24)
++ {
++ cgColorspace = CGColorSpaceCreateDeviceRGB();
++ bitinfo = kCGBitmapByteOrder32Host;
++ if (format == CAIRO_FORMAT_ARGB32)
++ bitinfo |= kCGImageAlphaPremultipliedFirst;
++ else
++ bitinfo |= kCGImageAlphaNoneSkipFirst;
++ bitsPerComponent = 8;
++ } else if (format == CAIRO_FORMAT_A8) {
++ cgColorspace = NULL;
++ bitinfo = kCGImageAlphaOnly;
++ bitsPerComponent = 8;
++ } else if (format == CAIRO_FORMAT_A1) {
++ /* I don't think we can usefully support this, as defined by
++ * cairo_format_t -- these are 1-bit pixels stored in 32-bit
++ * quantities.
++ */
++ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
++ } else {
++ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
++ }
++
++ cgc = CGBitmapContextCreate (imageData,
++ width,
++ height,
++ bitsPerComponent,
++ stride,
++ cgColorspace,
++ bitinfo);
++ CGColorSpaceRelease (cgColorspace);
++
++ if (!cgc) {
++ free (imageData);
++ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
++ }
++
++ /* flip the Y axis */
++ CGContextTranslateCTM (cgc, 0.0, height);
++ CGContextScaleCTM (cgc, 1.0, -1.0);
++
++ surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format),
++ width, height);
++ if (surf->base.status) {
++ CGContextRelease (cgc);
++ free (imageData);
++ // create_internal will have set an error
++ return (cairo_surface_t*) surf;
++ }
++
++ surf->imageData = imageData;
++
++ cairo_surface_t* tmpImageSurfaceEquiv =
++ cairo_image_surface_create_for_data (imageData, format,
++ width, height, stride);
++
++ if (cairo_surface_status (tmpImageSurfaceEquiv)) {
++ // Tried & failed to create an imageSurfaceEquiv!
++ cairo_surface_destroy (tmpImageSurfaceEquiv);
++ surf->imageSurfaceEquiv = NULL;
++ } else {
++ surf->imageSurfaceEquiv = tmpImageSurfaceEquiv;
++ surf->ownsData = FALSE;
++ }
++
++ return (cairo_surface_t *) surf;
++}
++
++/**
+ * cairo_quartz_surface_get_cg_context:
+ * @surface: the Cairo Quartz surface
+ *
+@@ -2497,6 +2713,18 @@ cairo_bool_t
+ return surface->backend == &cairo_quartz_surface_backend;
+ }
+
++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;
++}
++
+ /* Debug stuff */
+
+ #ifdef QUARTZ_DEBUG
+diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h
+--- a/gfx/cairo/cairo/src/cairo-quartz.h
++++ b/gfx/cairo/cairo/src/cairo-quartz.h
+@@ -54,9 +54,19 @@ cairo_quartz_surface_create_for_cg_conte
+ unsigned int width,
+ unsigned int height);
+
++cairo_surface_t *
++cairo_quartz_surface_create_for_data (unsigned char *data,
++ cairo_format_t format,
++ unsigned int width,
++ unsigned int height,
++ unsigned int stride);
++
+ 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
+
+ /*