summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/13-quartz-cglayer-surface.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/13-quartz-cglayer-surface.patch')
-rw-r--r--gfx/cairo/13-quartz-cglayer-surface.patch253
1 files changed, 253 insertions, 0 deletions
diff --git a/gfx/cairo/13-quartz-cglayer-surface.patch b/gfx/cairo/13-quartz-cglayer-surface.patch
new file mode 100644
index 0000000000..f4edc5f364
--- /dev/null
+++ b/gfx/cairo/13-quartz-cglayer-surface.patch
@@ -0,0 +1,253 @@
+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
+@@ -55,7 +55,8 @@ typedef enum {
+ DO_DIRECT,
+ DO_SHADING,
+ DO_IMAGE,
+- DO_TILED_IMAGE
++ DO_TILED_IMAGE,
++ DO_LAYER
+ } cairo_quartz_action_t;
+
+ /* define CTFontRef for pre-10.5 SDKs */
+@@ -72,6 +73,11 @@ typedef struct cairo_quartz_surface {
+
+ cairo_surface_clipper_t clipper;
+
++ /**
++ * If non-null, this is the CGLayer for the surface.
++ */
++ CGLayerRef cgLayer;
++
+ cairo_rectangle_int_t extents;
+ cairo_rectangle_int_t virtual_extents;
+
+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
+@@ -503,6 +503,7 @@ static CGBlendMode
+ default:
+ ASSERT_NOT_REACHED;
+ }
++ return kCGBlendModeNormal; /* just to silence clang warning [-Wreturn-type] */
+ }
+
+ static cairo_int_status_t
+@@ -1065,7 +1066,7 @@ typedef struct {
+ /* Destination rect */
+ CGRect rect;
+
+- /* Used with DO_SHADING, DO_IMAGE and DO_TILED_IMAGE */
++ /* Used with DO_SHADING, DO_IMAGE, DO_TILED_IMAGE, DO_LAYER */
+ CGAffineTransform transform;
+
+ /* Used with DO_IMAGE and DO_TILED_IMAGE */
+@@ -1077,6 +1078,11 @@ typedef struct {
+ /* Temporary destination for unbounded operations */
+ CGLayerRef layer;
+ CGRect clipRect;
++
++ /* Source layer to be rendered when using DO_LAYER.
++ Unlike 'layer' above, this is not owned by the drawing state
++ but by the source surface. */
++ CGLayerRef sourceLayer;
+ } cairo_quartz_drawing_state_t;
+
+ /*
+@@ -1253,7 +1259,9 @@ static cairo_int_status_t
+ }
+
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+- (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
++ (source->extend == CAIRO_EXTEND_NONE ||
++ source->extend == CAIRO_EXTEND_PAD ||
++ (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
+ {
+ const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source;
+ cairo_surface_t *pat_surf = spat->surface;
+@@ -1265,6 +1273,20 @@ static cairo_int_status_t
+ cairo_fixed_t fw, fh;
+ cairo_bool_t is_bounded;
+
++ /* Draw nonrepeating CGLayer surface using DO_LAYER */
++ if (source->extend != CAIRO_EXTEND_REPEAT &&
++ cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
++ cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
++ if (quartz_surf->cgLayer) {
++ cairo_matrix_invert(&m);
++ _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform);
++ state->rect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
++ state->sourceLayer = quartz_surf->cgLayer;
++ state->action = DO_LAYER;
++ return CAIRO_STATUS_SUCCESS;
++ }
++ }
++
+ _cairo_surface_get_extents (composite->surface, &extents);
+ status = _cairo_surface_to_cgimage (pat_surf, &extents, format,
+ &m, clip, &img);
+@@ -1426,7 +1448,14 @@ static void
+ CGContextTranslateCTM (state->cgDrawContext, 0, state->rect.size.height);
+ CGContextScaleCTM (state->cgDrawContext, 1, -1);
+
+- if (state->action == DO_IMAGE) {
++ if (state->action == DO_LAYER) {
++ /* Note that according to Apple docs it's completely legal to draw a CGLayer
++ * to any CGContext, even one it wasn't created for.
++ */
++ assert (state->sourceLayer);
++ CGContextDrawLayerAtPoint (state->cgDrawContext, state->rect.origin,
++ state->sourceLayer);
++ } else if (state->action == DO_IMAGE) {
+ CGContextDrawImage (state->cgDrawContext, state->rect, state->image);
+ if (op == CAIRO_OPERATOR_SOURCE &&
+ state->cgDrawContext == state->cgMaskContext)
+@@ -1655,6 +1684,10 @@ static cairo_status_t
+
+ surface->imageData = NULL;
+
++ if (surface->cgLayer) {
++ CGLayerRelease (surface->cgLayer);
++ }
++
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+@@ -1693,9 +1726,14 @@ static cairo_surface_t *
+ int width,
+ int height)
+ {
+- cairo_quartz_surface_t *surface, *similar_quartz;
++ cairo_quartz_surface_t *similar_quartz;
+ cairo_surface_t *similar;
+ cairo_format_t format;
++ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
++
++ if (surface->cgLayer)
++ return cairo_quartz_surface_create_cg_layer (abstract_surface, content,
++ width, height);
+
+ if (content == CAIRO_CONTENT_COLOR_ALPHA)
+ format = CAIRO_FORMAT_ARGB32;
+@@ -2068,7 +2106,6 @@ static cairo_int_status_t
+ cairo_quartz_drawing_state_t state;
+ cairo_int_status_t rv = CAIRO_INT_STATUS_UNSUPPORTED;
+ int i;
+- CGFontRef cgfref = NULL;
+
+ cairo_bool_t didForceFontSmoothing = FALSE;
+ cairo_antialias_t effective_antialiasing;
+@@ -2087,10 +2124,12 @@ static cairo_int_status_t
+ CGContextSetTextDrawingMode (state.cgMaskContext, kCGTextClip);
+ }
+
+- /* this doesn't addref */
+- cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font);
+- CGContextSetFont (state.cgMaskContext, cgfref);
+- CGContextSetFontSize (state.cgMaskContext, 1.0);
++ if (!CTFontDrawGlyphsPtr) {
++ /* this doesn't addref */
++ CGFontRef cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font);
++ CGContextSetFont (state.cgMaskContext, cgfref);
++ CGContextSetFontSize (state.cgMaskContext, 1.0);
++ }
+
+ effective_antialiasing = scaled_font->options.antialias;
+ if (effective_antialiasing == CAIRO_ANTIALIAS_SUBPIXEL &&
+@@ -2625,6 +2664,79 @@ cairo_quartz_surface_create_for_cg_conte
+ }
+
+ /**
++ * cairo_quartz_surface_create_cg_layer
++ * @surface: The returned surface can be efficiently drawn into this
++ * destination surface (if tiling is not used)."
++ * @content: the content type of the surface
++ * @width: width of the surface, in pixels
++ * @height: height of the surface, in pixels
++ *
++ * Creates a Quartz surface backed by a CGLayer, if the given surface
++ * is a Quartz surface; the CGLayer is created to match the surface's
++ * Quartz context. Otherwise just calls cairo_surface_create_similar.
++ * The returned surface can be efficiently blitted to the given surface,
++ * but tiling and 'extend' modes other than NONE are not so efficient.
++ *
++ * Return value: the newly created surface.
++ *
++ * Since: 1.10
++ **/
++cairo_surface_t *
++cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
++ cairo_content_t content,
++ unsigned int width,
++ unsigned int height)
++{
++ cairo_quartz_surface_t *surf;
++ CGLayerRef layer;
++ CGContextRef ctx;
++ CGContextRef cgContext;
++
++ cgContext = cairo_quartz_surface_get_cg_context (surface);
++ if (!cgContext)
++ return cairo_surface_create_similar (surface, content,
++ width, height);
++
++ if (!_cairo_quartz_verify_surface_size(width, height))
++ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
++
++ /* If we pass zero width or height into CGLayerCreateWithContext below,
++ * it will fail.
++ */
++ if (width == 0 || height == 0) {
++ return (cairo_surface_t*)
++ _cairo_quartz_surface_create_internal (NULL, content,
++ width, height);
++ }
++
++ layer = CGLayerCreateWithContext (cgContext,
++ CGSizeMake (width, height),
++ NULL);
++ if (!layer)
++ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
++
++ ctx = CGLayerGetContext (layer);
++ /* Flip it when we draw into it, so that when we finally composite it
++ * to a flipped target, the directions match and Quartz will optimize
++ * the composition properly
++ */
++ CGContextTranslateCTM (ctx, 0, height);
++ CGContextScaleCTM (ctx, 1, -1);
++
++ CGContextRetain (ctx);
++ surf = _cairo_quartz_surface_create_internal (ctx, content,
++ width, height);
++ if (surf->base.status) {
++ CGLayerRelease (layer);
++ // create_internal will have set an error
++ return (cairo_surface_t*) surf;
++ }
++ surf->cgLayer = layer;
++
++ return (cairo_surface_t *) surf;
++}
++
++/**
+ * cairo_quartz_surface_create:
+ * @format: format of pixels in the surface to create
+ * @width: width of the surface, in pixels
+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
+@@ -61,6 +61,12 @@ cairo_quartz_surface_create_for_data (un
+ unsigned int height,
+ unsigned int stride);
+
++cairo_public cairo_surface_t *
++cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
++ cairo_content_t content,
++ unsigned int width,
++ unsigned int height);
++
+ cairo_public CGContextRef
+ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
+