From 8f598dd69d3f98da8a59cbd87640aedf22473290 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Fri, 23 Jul 2010 08:20:52 +0200 Subject: [PATCH] quartz: Use native PDF blend modes Quartz supports PDF blend modes since 10.4 and exposes Porter-Duff compositing operators through the public API since 10.5. --- src/cairo-quartz-surface.c | 246 ++++++++++-------- test/Makefile.am | 4 + ...extended-blend-alpha.quartz.argb32.ref.png | Bin 0 -> 9729 bytes .../extended-blend-alpha.quartz.rgb24.ref.png | Bin 0 -> 5598 bytes test/extended-blend.quartz.argb32.ref.png | Bin 0 -> 4284 bytes test/extended-blend.quartz.rgb24.ref.png | Bin 0 -> 3965 bytes 6 files changed, 146 insertions(+), 104 deletions(-) create mode 100644 test/extended-blend-alpha.quartz.argb32.ref.png create mode 100644 test/extended-blend-alpha.quartz.rgb24.ref.png create mode 100644 test/extended-blend.quartz.argb32.ref.png create mode 100644 test/extended-blend.quartz.rgb24.ref.png diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 32d0d47e3..c5fbe0339 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -77,6 +77,7 @@ * This macro can be used to conditionally compile backend-specific code. */ +#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 /* This method is private, but it exists. Its params are are exposed * as args to the NS* method, but not as CG. */ @@ -97,6 +98,7 @@ enum PrivateCGCompositeMode { }; typedef enum PrivateCGCompositeMode PrivateCGCompositeMode; CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode); +#endif CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform); /* Some of these are present in earlier versions of the OS than where @@ -356,6 +358,7 @@ _cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path, * Misc helpers/callbacks */ +#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 static PrivateCGCompositeMode _cairo_quartz_cairo_operator_to_quartz_composite (cairo_operator_t op) { @@ -403,114 +406,149 @@ _cairo_quartz_cairo_operator_to_quartz_composite (cairo_operator_t op) case CAIRO_OPERATOR_HSL_COLOR: case CAIRO_OPERATOR_HSL_LUMINOSITY: default: - assert (0); + ASSERT_NOT_REACHED; } } +#endif + +static CGBlendMode +_cairo_quartz_cairo_operator_to_quartz_blend (cairo_operator_t op) +{ + switch (op) { + case CAIRO_OPERATOR_MULTIPLY: + return kCGBlendModeMultiply; + case CAIRO_OPERATOR_SCREEN: + return kCGBlendModeScreen; + case CAIRO_OPERATOR_OVERLAY: + return kCGBlendModeOverlay; + case CAIRO_OPERATOR_DARKEN: + return kCGBlendModeDarken; + case CAIRO_OPERATOR_LIGHTEN: + return kCGBlendModeLighten; + case CAIRO_OPERATOR_COLOR_DODGE: + return kCGBlendModeColorDodge; + case CAIRO_OPERATOR_COLOR_BURN: + return kCGBlendModeColorBurn; + case CAIRO_OPERATOR_HARD_LIGHT: + return kCGBlendModeHardLight; + case CAIRO_OPERATOR_SOFT_LIGHT: + return kCGBlendModeSoftLight; + case CAIRO_OPERATOR_DIFFERENCE: + return kCGBlendModeDifference; + case CAIRO_OPERATOR_EXCLUSION: + return kCGBlendModeExclusion; + case CAIRO_OPERATOR_HSL_HUE: + return kCGBlendModeHue; + case CAIRO_OPERATOR_HSL_SATURATION: + return kCGBlendModeSaturation; + case CAIRO_OPERATOR_HSL_COLOR: + return kCGBlendModeColor; + case CAIRO_OPERATOR_HSL_LUMINOSITY: + return kCGBlendModeLuminosity; + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + case CAIRO_OPERATOR_CLEAR: + return kCGBlendModeClear; + case CAIRO_OPERATOR_SOURCE: + return kCGBlendModeCopy; + case CAIRO_OPERATOR_OVER: + return kCGBlendModeNormal; + case CAIRO_OPERATOR_IN: + return kCGBlendModeSourceIn; + case CAIRO_OPERATOR_OUT: + return kCGBlendModeSourceOut; + case CAIRO_OPERATOR_ATOP: + return kCGBlendModeSourceAtop; + case CAIRO_OPERATOR_DEST_OVER: + return kCGBlendModeDestinationOver; + case CAIRO_OPERATOR_DEST_IN: + return kCGBlendModeDestinationIn; + case CAIRO_OPERATOR_DEST_OUT: + return kCGBlendModeDestinationOut; + case CAIRO_OPERATOR_DEST_ATOP: + return kCGBlendModeDestinationAtop; + case CAIRO_OPERATOR_XOR: + return kCGBlendModeXOR; + case CAIRO_OPERATOR_ADD: + return kCGBlendModePlusLighter; +#else + case CAIRO_OPERATOR_CLEAR: + case CAIRO_OPERATOR_SOURCE: + case CAIRO_OPERATOR_OVER: + case CAIRO_OPERATOR_IN: + case CAIRO_OPERATOR_OUT: + case CAIRO_OPERATOR_ATOP: + case CAIRO_OPERATOR_DEST_OVER: + case CAIRO_OPERATOR_DEST_IN: + case CAIRO_OPERATOR_DEST_OUT: + case CAIRO_OPERATOR_DEST_ATOP: + case CAIRO_OPERATOR_XOR: + case CAIRO_OPERATOR_ADD: +#endif + + case CAIRO_OPERATOR_DEST: + case CAIRO_OPERATOR_SATURATE: + default: + ASSERT_NOT_REACHED; + } +} + +static cairo_int_status_t +_cairo_cgcontext_set_cairo_operator (CGContextRef context, cairo_operator_t op) +{ + CGBlendMode blendmode; + + if (op == CAIRO_OPERATOR_DEST) + return CAIRO_INT_STATUS_NOTHING_TO_DO; + + /* Quartz doesn't support SATURATE at all. COLOR_DODGE and + * COLOR_BURN in Quartz follow the ISO32000 definition, but cairo + * uses the definition from the Adobe Supplement. + */ + if (op == CAIRO_OPERATOR_SATURATE || + op == CAIRO_OPERATOR_COLOR_DODGE || + op == CAIRO_OPERATOR_COLOR_BURN) + { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + +#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + if (op <= CAIRO_OPERATOR_ADD) { + PrivateCGCompositeMode compmode; + + compmode = _cairo_quartz_cairo_operator_to_quartz_composite (op); + CGContextSetCompositeOperation (context, compmode); + return CAIRO_STATUS_SUCCESS; + } +#endif + + blendmode = _cairo_quartz_cairo_operator_to_quartz_blend (op); + CGContextSetBlendMode (context, blendmode); + return CAIRO_STATUS_SUCCESS; +} static cairo_int_status_t _cairo_quartz_surface_set_cairo_operator (cairo_quartz_surface_t *surface, cairo_operator_t op) { - ND ((stderr, "%p _cairo_quartz_surface_set_cairo_operator %d\n", surface, op)); + ND((stderr, "%p _cairo_quartz_surface_set_cairo_operator %d\n", surface, op)); if (surface->base.content == CAIRO_CONTENT_ALPHA) { - /* For some weird reason, some compositing operators are - swapped when operating on masks */ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_ADD: - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz_composite (op)); - return CAIRO_STATUS_SUCCESS; - - case CAIRO_OPERATOR_IN: - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeDestinationAtop); - return CAIRO_STATUS_SUCCESS; - - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_MULTIPLY: - case CAIRO_OPERATOR_SCREEN: - case CAIRO_OPERATOR_OVERLAY: - case CAIRO_OPERATOR_DARKEN: - case CAIRO_OPERATOR_LIGHTEN: - case CAIRO_OPERATOR_COLOR_DODGE: - case CAIRO_OPERATOR_COLOR_BURN: - case CAIRO_OPERATOR_HARD_LIGHT: - case CAIRO_OPERATOR_SOFT_LIGHT: - case CAIRO_OPERATOR_DIFFERENCE: - case CAIRO_OPERATOR_EXCLUSION: - case CAIRO_OPERATOR_HSL_HUE: - case CAIRO_OPERATOR_HSL_SATURATION: - case CAIRO_OPERATOR_HSL_COLOR: - case CAIRO_OPERATOR_HSL_LUMINOSITY: - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeSourceOver); - return CAIRO_STATUS_SUCCESS; - - case CAIRO_OPERATOR_DEST_ATOP: - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeSourceIn); - return CAIRO_STATUS_SUCCESS; - - case CAIRO_OPERATOR_SATURATE: - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositePlusLighter); - return CAIRO_STATUS_SUCCESS; - - - case CAIRO_OPERATOR_ATOP: - /* - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeDestinationOver); - return CAIRO_STATUS_SUCCESS; - */ - case CAIRO_OPERATOR_DEST: - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_XOR: - default: - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } else { - switch (op) { - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz_composite (op)); - return CAIRO_STATUS_SUCCESS; - - case CAIRO_OPERATOR_DEST: - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - case CAIRO_OPERATOR_SATURATE: - /* TODO: the following are mostly supported by CGContextSetBlendMode*/ - case CAIRO_OPERATOR_MULTIPLY: - case CAIRO_OPERATOR_SCREEN: - case CAIRO_OPERATOR_OVERLAY: - case CAIRO_OPERATOR_DARKEN: - case CAIRO_OPERATOR_LIGHTEN: - case CAIRO_OPERATOR_COLOR_DODGE: - case CAIRO_OPERATOR_COLOR_BURN: - case CAIRO_OPERATOR_HARD_LIGHT: - case CAIRO_OPERATOR_SOFT_LIGHT: - case CAIRO_OPERATOR_DIFFERENCE: - case CAIRO_OPERATOR_EXCLUSION: - case CAIRO_OPERATOR_HSL_HUE: - case CAIRO_OPERATOR_HSL_SATURATION: - case CAIRO_OPERATOR_HSL_COLOR: - case CAIRO_OPERATOR_HSL_LUMINOSITY: - default: - return CAIRO_INT_STATUS_UNSUPPORTED; - } + if (op == CAIRO_OPERATOR_OUT || + op == CAIRO_OPERATOR_XOR) + return CAIRO_INT_STATUS_UNSUPPORTED; + else if (op == CAIRO_OPERATOR_SATURATE) + op = CAIRO_OPERATOR_ADD; + else if (op == CAIRO_OPERATOR_IN) + op = CAIRO_OPERATOR_DEST_ATOP; + else if (op == CAIRO_OPERATOR_DEST_ATOP) + op = CAIRO_OPERATOR_IN; + else if (op == CAIRO_OPERATOR_ATOP) + return CAIRO_INT_STATUS_NOTHING_TO_DO; /* op = CAIRO_OPERATOR_DEST_OVER */ + else if (op == CAIRO_OPERATOR_DEST_OVER) + op = CAIRO_OPERATOR_ATOP; } + + return _cairo_cgcontext_set_cairo_operator (surface->cgContext, op); } static inline CGLineCap @@ -641,14 +679,15 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface, if (!cgc) return; - CGContextSetCompositeOperation (cgc, kPrivateCGCompositeCopy); + _cairo_cgcontext_set_cairo_operator (cgc, CAIRO_OPERATOR_SOURCE); + /* We want to mask out whatever we just rendered, so we fill the * surface opaque, and then we'll render transparent. */ CGContextSetAlpha (cgc, 1.0f); CGContextFillRect (cgc, CGRectMake (0, 0, clipBoxRound.size.width, clipBoxRound.size.height)); - CGContextSetCompositeOperation (cgc, kPrivateCGCompositeClear); + _cairo_cgcontext_set_cairo_operator (cgc, CAIRO_OPERATOR_CLEAR); CGContextSetShouldAntialias (cgc, (antialias != CAIRO_ANTIALIAS_NONE)); CGContextTranslateCTM (cgc, -clipBoxRound.origin.x, -clipBoxRound.origin.y); @@ -719,7 +758,7 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface, /* Then render with the mask */ CGContextSaveGState (surface->cgContext); - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy); + _cairo_quartz_surface_set_cairo_operator (surface, CAIRO_OPERATOR_SOURCE); CGContextClipToMask (surface->cgContext, clipBoxRound, maskImage); CGImageRelease (maskImage); @@ -1663,8 +1702,7 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, CGContextSaveGState (new_surface->cgContext); - CGContextSetCompositeOperation (new_surface->cgContext, - kPrivateCGCompositeCopy); + _cairo_quartz_surface_set_cairo_operator (new_surface, CAIRO_OPERATOR_SOURCE); CGContextTranslateCTM (new_surface->cgContext, -src_x, -src_y); CGContextDrawImage (new_surface->cgContext, diff --git a/test/Makefile.am b/test/Makefile.am index aa203bcc4..236fc4f2a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -483,11 +483,15 @@ REFERENCE_IMAGES = \ extended-blend.image16.ref.png \ extended-blend.argb32.ref.png \ extended-blend.rgb24.ref.png \ + extended-blend.quartz.argb32.ref.png \ + extended-blend.quartz.rgb24.ref.png \ extended-blend.svg12.argb32.xfail.png \ extended-blend.svg12.rgb24.xfail.png \ extended-blend-alpha.image16.ref.png \ extended-blend-alpha.argb32.ref.png \ extended-blend-alpha.rgb24.ref.png \ + extended-blend-alpha.quartz.argb32.ref.png \ + extended-blend-alpha.quartz.rgb24.ref.png \ extended-blend-alpha.svg12.argb32.xfail.png \ extended-blend-alpha.svg12.rgb24.xfail.png \ extend-pad-border.image16.ref.png \ diff --git a/test/extended-blend-alpha.quartz.argb32.ref.png b/test/extended-blend-alpha.quartz.argb32.ref.png new file mode 100644 index 0000000000000000000000000000000000000000..e5701a6520b5562684f52ffccb240b577472ab84 GIT binary patch literal 9729 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 literal 0 HcmV?d00001 diff --git a/test/extended-blend-alpha.quartz.rgb24.ref.png b/test/extended-blend-alpha.quartz.rgb24.ref.png new file mode 100644 index 0000000000000000000000000000000000000000..477d346c5640c6f9d7400b59b46cab8b0affaf36 GIT binary patch literal 5598 zcmZ`-2~?7K_qO_4rY4=H&-}{Nrcx(VEKMEPW-KLr6&n>yMVy?JRLm4qT*xLX8<$E6 z$pu>!7Z4pc6x=e?5?n@1O%Zoe#3juo7xH`S|25NCf0n~J?>XGxz0bY(xzGLmeg+QP zxqaVu85xjHiAzys*gy)pDi8$?3B#f`}c#YY?6$OJjv?RPmYAN zNosc@!@B6ycRx9FD7P%F-8ShY-e7L{lgRc%PWkL`)_-7sq%#Z${44p#f3t|N^Cj`K zE7RIg0qZM5qE*o<`TVSivPCBF$C6Fwf4i{t`NlTcJJG6NkAb1HL87$&(U^i`M$ zDYB$B7dd!G7MdS=wdKvR%j08m<=@2^PsD0EU(3A zl$1YK9-FCz%`V!}eH@$UARO-Mr$kqOzrtRvgoHl+rSC6)Kcetwsno6#WBVXZeC8I9`^vS00y^ zWoT%3i;aI(k{sv9K6_b;;v8%8F4pP5#RDO-8t6&$VRaF|>hb5X-9yZTeMO_~Ztk}6 zt93Sf#dqF_BBzl6r&5RRM4|3AWBGz}P^wcUePRe@B)AFfrCfZQN&I4HdG~;_2fD|y z1zA?lP)2X~og{>OfyP3)Je>n0K&dV4c6st%`GRy{ali0T_0Z?OT%zQ2laEIKQg!X2 zq2+Z?JFm*K8b=^C+0DT!6@Olh6nL2_K=h>9*l(ra}qVMZcrhv*XzzP-CrG2H#9AYjF zYxV7apAe=`Mftq!Eu7daH~bo{yj0&x?`D3$;x>uNu0;az*3>Tdna?xbG_HIM6V7~@ zeDvAqzi%xJ=76Yh-lFVumcj5{QprZ0ff?o#_=Ya>uYN{V{)SiWyH|(n>6>?kgR3k4HbSR z4fzB+9jm08M4Re}cUxuu*}Y>@mDv+PtI^zPNKI~p(^A u&+6V0a|8HOhXP40eo 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 KseJQauKpLrBnOB9 literal 0 HcmV?d00001 diff --git a/test/extended-blend.quartz.argb32.ref.png b/test/extended-blend.quartz.argb32.ref.png new file mode 100644 index 0000000000000000000000000000000000000000..173c6e23ce4c720b3c08fca6f471d72341db8b15 GIT binary patch literal 4284 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 aVw2Sec7GU-6p;2SA0c;RyemB;e*QmWs?PfW literal 0 HcmV?d00001 diff --git a/test/extended-blend.quartz.rgb24.ref.png b/test/extended-blend.quartz.rgb24.ref.png new file mode 100644 index 0000000000000000000000000000000000000000..56a1214ee1a1cecd6f06e637a5261540b68d1697 GIT binary patch literal 3965 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 literal 0 HcmV?d00001