Bug 611433 - Add cairo_quartz_surface_create_for_data. r=jrmuizel a=blocking2.0

This commit is contained in:
Joe Drew 2010-12-16 23:33:07 -08:00
Родитель d4d7a6cb22
Коммит 6dde0ea5e0
6 изменённых файлов: 408 добавлений и 21 удалений

Просмотреть файл

@ -76,6 +76,8 @@ quartz-cglayers-fix-fallback.patch: Bug 572912; fix bug in fallback code in prev
quartz-get-image.patch: Bug 575521; add a way to get the image surface associated with a surface quartz-get-image.patch: Bug 575521; add a way to get the image surface associated with a surface
quartz-create-for-data.patch: Bug 575521; add a way to create quartz surfaces backed with application-provided data
premultiply-alpha-solid-gradients.patch: bug 539165; multiply the solid color by the alpha component before using it for a solid surface premultiply-alpha-solid-gradients.patch: bug 539165; multiply the solid color by the alpha component before using it for a solid surface
xlib-initialize-members.path: bug 548793; initialize XRender version if the server doesn't have the extension xlib-initialize-members.path: bug 548793; initialize XRender version if the server doesn't have the extension

Просмотреть файл

@ -68,6 +68,8 @@ typedef struct cairo_quartz_surface {
CGLayerRef cgLayer; CGLayerRef cgLayer;
cairo_rectangle_int_t extents; cairo_rectangle_int_t extents;
cairo_bool_t ownsData;
} cairo_quartz_surface_t; } cairo_quartz_surface_t;
typedef struct cairo_quartz_image_surface { typedef struct cairo_quartz_image_surface {

Просмотреть файл

@ -1916,10 +1916,11 @@ _cairo_quartz_surface_finish (void *abstract_surface)
} }
if (surface->imageSurfaceEquiv) { if (surface->imageSurfaceEquiv) {
_cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv); if (surface->ownsData)
_cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv);
cairo_surface_destroy (surface->imageSurfaceEquiv); cairo_surface_destroy (surface->imageSurfaceEquiv);
surface->imageSurfaceEquiv = NULL; surface->imageSurfaceEquiv = NULL;
} else if (surface->imageData) { } else if (surface->imageData && surface->ownsData) {
free (surface->imageData); free (surface->imageData);
} }
@ -2927,6 +2928,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
surface->imageSurfaceEquiv = NULL; surface->imageSurfaceEquiv = NULL;
surface->bitmapContextImage = NULL; surface->bitmapContextImage = NULL;
surface->cgLayer = NULL; surface->cgLayer = NULL;
surface->ownsData = TRUE;
return surface; return surface;
} }
@ -3070,14 +3072,94 @@ cairo_surface_t *
cairo_quartz_surface_create (cairo_format_t format, cairo_quartz_surface_create (cairo_format_t format,
unsigned int width, unsigned int width,
unsigned int height) unsigned int height)
{
int stride;
unsigned char *data;
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)
{
stride = width * 4;
} else if (format == CAIRO_FORMAT_A8) {
stride = width;
} 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));
}
/* The Apple docs say that for best performance, the stride and the data
* pointer should be 16-byte aligned. malloc already aligns to 16-bytes,
* so we don't have to anything special on allocation.
*/
stride = (stride + 15) & ~15;
data = _cairo_malloc_ab (height, stride);
if (!data) {
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
/* zero the memory to match the image surface behaviour */
memset (data, 0, height * stride);
cairo_quartz_surface_t *surf;
surf = (cairo_quartz_surface_t *) cairo_quartz_surface_create_for_data
(data, format, width, height, stride);
if (surf->base.status) {
free (data);
return (cairo_surface_t *) surf;
}
// We created this data, so we can delete it.
surf->ownsData = TRUE;
return (cairo_surface_t *) surf;
}
/**
* 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
**/
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; cairo_quartz_surface_t *surf;
CGContextRef cgc; CGContextRef cgc;
CGColorSpaceRef cgColorspace; CGColorSpaceRef cgColorspace;
CGBitmapInfo bitinfo; CGBitmapInfo bitinfo;
void *imageData; void *imageData = data;
int stride;
int bitsPerComponent; int bitsPerComponent;
unsigned int i;
// verify width and height of surface // verify width and height of surface
if (!_cairo_quartz_verify_surface_size(width, height)) if (!_cairo_quartz_verify_surface_size(width, height))
@ -3098,10 +3180,8 @@ cairo_quartz_surface_create (cairo_format_t format,
else else
bitinfo |= kCGImageAlphaNoneSkipFirst; bitinfo |= kCGImageAlphaNoneSkipFirst;
bitsPerComponent = 8; bitsPerComponent = 8;
stride = width * 4;
} else if (format == CAIRO_FORMAT_A8) { } else if (format == CAIRO_FORMAT_A8) {
cgColorspace = NULL; cgColorspace = NULL;
stride = width;
bitinfo = kCGImageAlphaOnly; bitinfo = kCGImageAlphaOnly;
bitsPerComponent = 8; bitsPerComponent = 8;
} else if (format == CAIRO_FORMAT_A1) { } else if (format == CAIRO_FORMAT_A1) {
@ -3114,21 +3194,6 @@ cairo_quartz_surface_create (cairo_format_t format,
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
} }
/* The Apple docs say that for best performance, the stride and the data
* pointer should be 16-byte aligned. malloc already aligns to 16-bytes,
* so we don't have to anything special on allocation.
*/
stride = (stride + 15) & ~15;
imageData = _cairo_malloc_ab (height, stride);
if (!imageData) {
CGColorSpaceRelease (cgColorspace);
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
/* zero the memory to match the image surface behaviour */
memset (imageData, 0, height * stride);
cgc = CGBitmapContextCreate (imageData, cgc = CGBitmapContextCreate (imageData,
width, width,
height, height,
@ -3168,6 +3233,7 @@ cairo_quartz_surface_create (cairo_format_t format,
surf->imageSurfaceEquiv = NULL; surf->imageSurfaceEquiv = NULL;
} else { } else {
surf->imageSurfaceEquiv = tmpImageSurfaceEquiv; surf->imageSurfaceEquiv = tmpImageSurfaceEquiv;
surf->ownsData = FALSE;
} }
return (cairo_surface_t *) surf; return (cairo_surface_t *) surf;

Просмотреть файл

@ -49,6 +49,13 @@ cairo_quartz_surface_create (cairo_format_t format,
unsigned int width, unsigned int width,
unsigned int height); unsigned int height);
cairo_public 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 cairo_surface_t * cairo_public cairo_surface_t *
cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface, cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
cairo_content_t content, cairo_content_t content,

Просмотреть файл

@ -181,6 +181,7 @@
#define cairo_quartz_image_surface_create _moz_cairo_quartz_image_surface_create #define cairo_quartz_image_surface_create _moz_cairo_quartz_image_surface_create
#define cairo_quartz_image_surface_get_image _moz_cairo_quartz_image_surface_get_image #define cairo_quartz_image_surface_get_image _moz_cairo_quartz_image_surface_get_image
#define cairo_quartz_surface_create _moz_cairo_quartz_surface_create #define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
#define cairo_quartz_surface_create_for_data _moz_cairo_quartz_surface_create_for_data
#define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context #define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context
#define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context #define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context
#define cairo_quartz_surface_get_image _moz_cairo_quartz_surface_get_image #define cairo_quartz_surface_get_image _moz_cairo_quartz_surface_get_image

Просмотреть файл

@ -0,0 +1,309 @@
diff --git a/gfx/cairo/README b/gfx/cairo/README
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -71,16 +71,18 @@ quartz-cache-CGImageRef.patch: cache CGI
quartz-remove-snapshot.patch: remove broken implementation of backend snapshot
quartz-cglayers.patch: add support for cairo surfaces backed by CGLayers
quartz-cglayers-fix-fallback.patch: Bug 572912; fix bug in fallback code in previous patch
quartz-get-image.patch: Bug 575521; add a way to get the image surface associated with a surface
+quartz-create-for-data.patch: Bug 575521; add a way to create quartz surfaces backed with application-provided data
+
premultiply-alpha-solid-gradients.patch: bug 539165; multiply the solid color by the alpha component before using it for a solid surface
xlib-initialize-members.path: bug 548793; initialize XRender version if the server doesn't have the extension
remove-comma: remove a comma from enum
d2d.patch: add d2d support
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
@@ -63,16 +63,18 @@ typedef struct cairo_quartz_surface {
CGImageRef bitmapContextImage;
/**
* If non-null, this is the CGLayer for the surface.
*/
CGLayerRef cgLayer;
cairo_rectangle_int_t extents;
+
+ cairo_bool_t ownsData;
} cairo_quartz_surface_t;
typedef struct cairo_quartz_image_surface {
cairo_surface_t base;
cairo_rectangle_int_t extents;
CGImageRef image;
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
@@ -1880,20 +1880,21 @@ _cairo_quartz_surface_finish (void *abst
surface->cgContext = NULL;
if (surface->bitmapContextImage) {
CGImageRelease (surface->bitmapContextImage);
surface->bitmapContextImage = NULL;
}
if (surface->imageSurfaceEquiv) {
- _cairo_image_surface_assume_ownership_of_data (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) {
+ } else if (surface->imageData && surface->ownsData) {
free (surface->imageData);
}
surface->imageData = NULL;
if (surface->cgLayer) {
CGLayerRelease (surface->cgLayer);
}
@@ -2888,16 +2889,17 @@ _cairo_quartz_surface_create_internal (C
surface->cgContext = cgContext;
surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
surface->imageData = NULL;
surface->imageSurfaceEquiv = NULL;
surface->bitmapContextImage = NULL;
surface->cgLayer = NULL;
+ surface->ownsData = TRUE;
return surface;
}
/**
* cairo_quartz_surface_create_for_cg_context
* @cgContext: the existing CGContext for which to create the surface
* @width: width of the surface, in pixels
@@ -3031,23 +3033,103 @@ cairo_quartz_surface_create_cg_layer (ca
*
* Since: 1.4
**/
cairo_surface_t *
cairo_quartz_surface_create (cairo_format_t format,
unsigned int width,
unsigned int height)
{
+ int stride;
+ unsigned char *data;
+
+ 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)
+ {
+ stride = width * 4;
+ } else if (format == CAIRO_FORMAT_A8) {
+ stride = width;
+ } 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));
+ }
+
+ /* The Apple docs say that for best performance, the stride and the data
+ * pointer should be 16-byte aligned. malloc already aligns to 16-bytes,
+ * so we don't have to anything special on allocation.
+ */
+ stride = (stride + 15) & ~15;
+
+ data = _cairo_malloc_ab (height, stride);
+ if (!data) {
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+
+ /* zero the memory to match the image surface behaviour */
+ memset (data, 0, height * stride);
+
+ cairo_quartz_surface_t *surf;
+ surf = (cairo_quartz_surface_t *) cairo_quartz_surface_create_for_data
+ (data, format, width, height, stride);
+ if (surf->base.status) {
+ free (data);
+ return (cairo_surface_t *) surf;
+ }
+
+ // We created this data, so we can delete it.
+ surf->ownsData = TRUE;
+
+ return (cairo_surface_t *) surf;
+}
+
+/**
+ * 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
+ **/
+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;
- int stride;
+ 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);
@@ -3058,47 +3140,30 @@ cairo_quartz_surface_create (cairo_forma
{
cgColorspace = CGColorSpaceCreateDeviceRGB();
bitinfo = kCGBitmapByteOrder32Host;
if (format == CAIRO_FORMAT_ARGB32)
bitinfo |= kCGImageAlphaPremultipliedFirst;
else
bitinfo |= kCGImageAlphaNoneSkipFirst;
bitsPerComponent = 8;
- stride = width * 4;
} else if (format == CAIRO_FORMAT_A8) {
cgColorspace = NULL;
- stride = width;
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));
}
- /* The Apple docs say that for best performance, the stride and the data
- * pointer should be 16-byte aligned. malloc already aligns to 16-bytes,
- * so we don't have to anything special on allocation.
- */
- stride = (stride + 15) & ~15;
-
- imageData = _cairo_malloc_ab (height, stride);
- if (!imageData) {
- CGColorSpaceRelease (cgColorspace);
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- /* zero the memory to match the image surface behaviour */
- memset (imageData, 0, height * stride);
-
cgc = CGBitmapContextCreate (imageData,
width,
height,
bitsPerComponent,
stride,
cgColorspace,
bitinfo);
CGColorSpaceRelease (cgColorspace);
@@ -3118,16 +3183,17 @@ cairo_quartz_surface_create (cairo_forma
CGContextRelease (cgc);
free (imageData);
// create_internal will have set an error
return (cairo_surface_t*) surf;
}
surf->imageData = imageData;
surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride);
+ surf->ownsData = FALSE;
return (cairo_surface_t *) surf;
}
/**
* cairo_quartz_surface_get_cg_context
* @surface: the Cairo Quartz surface
*
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
@@ -45,16 +45,23 @@
CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_quartz_surface_create (cairo_format_t format,
unsigned int width,
unsigned int height);
cairo_public 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 cairo_surface_t *
cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
unsigned int width,
unsigned int height);
cairo_public cairo_surface_t *
cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
unsigned int width,
unsigned int height);
diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h
--- a/gfx/cairo/cairo/src/cairo-rename.h
+++ b/gfx/cairo/cairo/src/cairo-rename.h
@@ -176,16 +176,17 @@
#define cairo_qpainter_surface_get_image _moz_cairo_qpainter_surface_get_image
#define cairo_qpainter_surface_get_qimage _moz_cairo_qpainter_surface_get_qimage
#define cairo_qpainter_surface_get_qpainter _moz_cairo_qpainter_surface_get_qpainter
#define cairo_quartz_font_face_create_for_atsu_font_id _moz_cairo_quartz_font_face_create_for_atsu_font_id
#define cairo_quartz_font_face_create_for_cgfont _moz_cairo_quartz_font_face_create_for_cgfont
#define cairo_quartz_image_surface_create _moz_cairo_quartz_image_surface_create
#define cairo_quartz_image_surface_get_image _moz_cairo_quartz_image_surface_get_image
#define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
+#define cairo_quartz_surface_create_for_data _moz_cairo_quartz_surface_create_for_data
#define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context
#define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context
#define cairo_quartz_surface_get_image _moz_cairo_quartz_surface_get_image
#define cairo_rectangle _moz_cairo_rectangle
#define cairo_rectangle_list_destroy _moz_cairo_rectangle_list_destroy
#define cairo_reference _moz_cairo_reference
#define cairo_rel_curve_to _moz_cairo_rel_curve_to
#define cairo_rel_line_to _moz_cairo_rel_line_to