@@ -1032,6 +1032,12 @@ static int QuartzCreateMask(SEXP mask,
10321032
10331033 cs = CGColorSpaceCreateDeviceGray ();
10341034
1035+ /* For alpha masks, create a bitmap with only an alpha channel */
1036+ uint32_t bitmapInfo = kCGImageAlphaNone ;
1037+ if (R_GE_maskType (mask ) == R_GE_alphaMask ) {
1038+ bitmapInfo = kCGImageAlphaOnly ;
1039+ }
1040+
10351041 /* Create bitmap grahics context
10361042 * drawing is redirected to this context */
10371043 quartz_bitmap = CGBitmapContextCreate (NULL ,
@@ -1040,7 +1046,7 @@ static int QuartzCreateMask(SEXP mask,
10401046 8 ,
10411047 0 ,
10421048 cs ,
1043- kCGImageAlphaNone );
1049+ bitmapInfo );
10441050
10451051 quartz_mask -> context = quartz_bitmap ;
10461052 xd -> masks [index ] = quartz_mask ;
@@ -1055,6 +1061,31 @@ static int QuartzCreateMask(SEXP mask,
10551061 eval (R_fcall , R_GlobalEnv );
10561062 UNPROTECT (1 );
10571063
1064+ /* When working with an alpha mask, convert into a grayscale bitmap */
1065+ if (R_GE_maskType (mask ) == R_GE_alphaMask ) {
1066+ CGContextRef alpha_bitmap = quartz_bitmap ;
1067+
1068+ /* Create a new grayscale bitmap with no alpha channel */
1069+ int stride = CGBitmapContextGetBytesPerRow (alpha_bitmap );
1070+ quartz_bitmap = CGBitmapContextCreate (NULL ,
1071+ (size_t ) devWidth ,
1072+ (size_t ) devHeight ,
1073+ 8 ,
1074+ stride ,
1075+ cs ,
1076+ kCGImageAlphaNone );
1077+ quartz_mask -> context = quartz_bitmap ;
1078+
1079+ void * alpha_data = CGBitmapContextGetData (alpha_bitmap );
1080+ void * gray_data = CGBitmapContextGetData (quartz_bitmap );
1081+
1082+ /* Copy the alpha channel data into the grayscale bitmap */
1083+ memcpy (gray_data , alpha_data , stride * devHeight );
1084+
1085+ /* We're finished with the alpha channel bitmap now */
1086+ CGContextRelease (alpha_bitmap );
1087+ }
1088+
10581089 /* Create image from bitmap context */
10591090 CGImageRef maskImage ;
10601091 maskImage = CGBitmapContextCreateImage (quartz_bitmap );
@@ -2730,10 +2761,6 @@ static SEXP RQuartz_setMask(SEXP mask, SEXP ref, pDevDesc dd) {
27302761 if (isNull (mask )) {
27312762 /* Set NO mask */
27322763 index = -1 ;
2733- } else if (R_GE_maskType (mask ) == R_GE_alphaMask ) {
2734- warning (_ ("Ignored alpha mask (not supported on this device)" ));
2735- /* Set NO mask */
2736- index = -1 ;
27372764 } else {
27382765 if (isNull (ref )) {
27392766 /* Create a new mask */
@@ -2953,8 +2980,10 @@ static SEXP RQuartz_capabilities(SEXP capabilities) {
29532980 SET_VECTOR_ELT (capabilities , R_GE_capability_clippingPaths , clippingPaths );
29542981 UNPROTECT (1 );
29552982
2956- PROTECT (masks = allocVector (INTSXP , 1 ));
2983+
2984+ PROTECT (masks = allocVector (INTSXP , 2 ));
29572985 INTEGER (masks )[0 ] = R_GE_luminanceMask ;
2986+ INTEGER (masks )[1 ] = R_GE_alphaMask ;
29582987 SET_VECTOR_ELT (capabilities , R_GE_capability_masks , masks );
29592988 UNPROTECT (1 );
29602989
0 commit comments