@@ -635,16 +635,7 @@ export default function (doc, svg, x, y, options) {
635635 luminosity : 'Luminosity' ,
636636 } ;
637637
638- const maskBackdrop = [ 0 , 0 , 0 ] ;
639- if ( doc . _activeColorProfile ) {
640- let i = doc . _activeColorProfile . channels - 3 ;
641- while ( i > 0 ) {
642- maskBackdrop . push ( 0 ) ;
643- i -- ;
644- }
645- }
646-
647- function docBeginGroup ( bbox ) {
638+ function docBeginGroup ( bbox , groupColorSpace ) {
648639 let group = new ( function PDFGroup ( ) { } ) ( ) ;
649640 group . name = 'G' + ( doc . _groupCount = ( doc . _groupCount || 0 ) + 1 ) ;
650641 group . resources = doc . ref ( ) ;
@@ -653,7 +644,7 @@ export default function (doc, svg, x, y, options) {
653644 Subtype : 'Form' ,
654645 FormType : 1 ,
655646 BBox : bbox ,
656- Group : { S : 'Transparency' , CS : colorSpace , I : true , K : false } ,
647+ Group : { S : 'Transparency' , CS : groupColorSpace || colorSpace , I : true , K : false } ,
657648 Resources : group . resources ,
658649 } ) ;
659650 group . xobj . write ( '' ) ;
@@ -703,14 +694,14 @@ export default function (doc, svg, x, y, options) {
703694 let name = 'M' + ( doc . _maskCount = ( doc . _maskCount || 0 ) + 1 ) ;
704695 let gstate = doc . ref ( {
705696 Type : 'ExtGState' ,
706- CA : 1 ,
707697 ca : 1 ,
698+ CA : 1 ,
708699 BM : 'Normal' ,
709700 SMask : {
710- // This should ideally be an Alpha mask for clipping but when we set it to Alpha the firefox pdf viewer doesn't render masks correctly
711701 S : 'Luminosity' ,
712702 G : group . xobj ,
713- BC : maskBackdrop ,
703+ CS : 'DeviceRGB' ,
704+ BC : [ 0 , 0 , 0 ] ,
714705 } ,
715706 } ) ;
716707 gstate . end ( ) ;
@@ -853,22 +844,22 @@ export default function (doc, svg, x, y, options) {
853844 function docEndText ( ) {
854845 doc . addContent ( 'ET' ) ;
855846 }
856- function docFillColor ( color , isClip ) {
857- if ( isClip ) {
858- // always write clips in RGB colorspace
847+ function docFillColor ( color , maskOrClip ) {
848+ if ( color [ 0 ] . constructor . name === 'PDFPattern' ) {
849+ doc . fillOpacity ( color [ 1 ] ) ;
850+ docUsePattern ( color [ 0 ] , false ) ;
851+ return ;
852+ }
853+ if ( maskOrClip ) {
854+ // always write clips/masks in RGB colorspace
859855 const oldColorProfile = doc . _activeColorProfile ;
860856 doc . _activeColorProfile = null ;
861- doc . fillColor ( RGBDefaultColors . white [ 0 ] , RGBDefaultColors . white [ 1 ] ) ;
857+ doc . fillColor ( color [ 0 ] , color [ 1 ] ) ;
862858 doc . _activeColorProfile = oldColorProfile ;
863859 return ;
864860 }
865861
866- if ( color [ 0 ] . constructor . name === 'PDFPattern' ) {
867- doc . fillOpacity ( color [ 1 ] ) ;
868- docUsePattern ( color [ 0 ] , false ) ;
869- } else {
870- doc . fillColor ( color [ 0 ] , color [ 1 ] ) ;
871- }
862+ doc . fillColor ( color [ 0 ] , color [ 1 ] ) ;
872863 }
873864 function docStrokeColor ( color ) {
874865 if ( color [ 0 ] . constructor . name === 'PDFPattern' ) {
@@ -1083,6 +1074,10 @@ export default function (doc, svg, x, y, options) {
10831074 let newColor = color [ 0 ] . slice ( ) ,
10841075 newOpacity = color [ 1 ] * opacity ;
10851076 if ( isMask ) {
1077+ // For mask rendering, use DeviceRGB (premultiplied).
1078+ if ( newColor . length === 4 ) {
1079+ newColor = cmykToRgb ( newColor ) ;
1080+ }
10861081 for ( let i = 0 ; i < newColor . length ; i ++ ) {
10871082 newColor [ i ] *= newOpacity ;
10881083 }
@@ -1091,6 +1086,27 @@ export default function (doc, svg, x, y, options) {
10911086 return [ newColor , newOpacity ] ;
10921087 }
10931088 }
1089+ function cmykToRgb ( cmyk ) {
1090+ let c = cmyk [ 0 ] ,
1091+ m = cmyk [ 1 ] ,
1092+ y = cmyk [ 2 ] ,
1093+ k = cmyk [ 3 ] ;
1094+ if ( c > 1 || m > 1 || y > 1 || k > 1 ) {
1095+ c /= 100 ;
1096+ m /= 100 ;
1097+ y /= 100 ;
1098+ k /= 100 ;
1099+ }
1100+ c = Math . max ( 0 , Math . min ( 1 , c ) ) ;
1101+ m = Math . max ( 0 , Math . min ( 1 , m ) ) ;
1102+ y = Math . max ( 0 , Math . min ( 1 , y ) ) ;
1103+ k = Math . max ( 0 , Math . min ( 1 , k ) ) ;
1104+ return [
1105+ Math . round ( 255 * ( 1 - c ) * ( 1 - k ) ) ,
1106+ Math . round ( 255 * ( 1 - m ) * ( 1 - k ) ) ,
1107+ Math . round ( 255 * ( 1 - y ) * ( 1 - k ) ) ,
1108+ ] ;
1109+ }
10941110 function multiplyMatrix ( ) {
10951111 function multiply ( a , b ) {
10961112 return [
@@ -2458,7 +2474,7 @@ export default function (doc, svg, x, y, options) {
24582474 fill = this . get ( 'fill' ) ,
24592475 fillOpacity = this . get ( 'fill-opacity' ) ;
24602476 if ( isClip ) {
2461- return DefaultColors . white ;
2477+ return RGBDefaultColors . white ;
24622478 }
24632479 if ( fill !== 'none' && opacity && fillOpacity ) {
24642480 if ( fill instanceof SvgElemGradient || fill instanceof SvgElemPattern ) {
@@ -2759,7 +2775,7 @@ export default function (doc, svg, x, y, options) {
27592775 doc . image ( image , 0 , 0 ) ;
27602776 } else {
27612777 doc . rect ( 0 , 0 , image . width , image . height ) ;
2762- docFillColor ( DefaultColors . white , true ) ;
2778+ docFillColor ( RGBDefaultColors . white , true ) ;
27632779 }
27642780 doc . restore ( ) ;
27652781 } ;
@@ -3036,7 +3052,7 @@ export default function (doc, svg, x, y, options) {
30363052 lineCap = this . get ( 'stroke-linecap' ) ;
30373053 if ( fill || stroke ) {
30383054 if ( fill ) {
3039- docFillColor ( fill ) ;
3055+ docFillColor ( fill , isMask ) ;
30403056 }
30413057 if ( stroke ) {
30423058 for ( let j = 0 ; j < subPaths . length ; j ++ ) {
@@ -3045,7 +3061,7 @@ export default function (doc, svg, x, y, options) {
30453061 if ( subPaths [ j ] . startPoint && subPaths [ j ] . startPoint . length > 1 ) {
30463062 let x = subPaths [ j ] . startPoint [ 0 ] ,
30473063 y = subPaths [ j ] . startPoint [ 1 ] ;
3048- docFillColor ( stroke ) ;
3064+ docFillColor ( stroke , isMask ) ;
30493065 if ( lineCap === 'square' ) {
30503066 doc . rect ( x - 0.5 * lineWidth , y - 0.5 * lineWidth , lineWidth , lineWidth ) ;
30513067 } else if ( lineCap === 'round' ) {
@@ -3111,7 +3127,7 @@ export default function (doc, svg, x, y, options) {
31113127 }
31123128 } else {
31133129 this . shape . insertInDocument ( ) ;
3114- docFillColor ( DefaultColors . white , true ) ;
3130+ docFillColor ( RGBDefaultColors . white , true ) ;
31153131 doc . fill ( this . get ( 'clip-rule' ) ) ;
31163132 }
31173133 doc . restore ( ) ;
@@ -3314,7 +3330,7 @@ export default function (doc, svg, x, y, options) {
33143330 var SvgElemClipPath = function ( obj , inherits ) {
33153331 SvgElemHasChildren . call ( this , obj , inherits ) ;
33163332 this . useMask = function ( bBox ) {
3317- let group = docBeginGroup ( getPageBBox ( ) ) ;
3333+ let group = docBeginGroup ( getPageBBox ( ) , 'DeviceRGB' ) ;
33183334 doc . save ( ) ;
33193335 doc . transform . apply ( doc , this . get ( 'transform' ) ) ;
33203336 if ( this . attr ( 'clipPathUnits' ) === 'objectBoundingBox' ) {
@@ -3331,7 +3347,10 @@ export default function (doc, svg, x, y, options) {
33313347 var SvgElemMask = function ( obj , inherits ) {
33323348 SvgElemHasChildren . call ( this , obj , inherits ) ;
33333349 this . useMask = function ( bBox ) {
3334- let group = docBeginGroup ( getPageBBox ( ) ) ;
3350+ let group = docBeginGroup ( getPageBBox ( ) , 'DeviceRGB' ) ;
3351+
3352+ const savedColorProfile = doc . _activeColorProfile ;
3353+ doc . _activeColorProfile = null ;
33353354 doc . save ( ) ;
33363355 /* let x, y, w, h; */
33373356 if ( this . attr ( 'maskUnits' ) === 'userSpaceOnUse' ) {
@@ -3349,8 +3368,10 @@ export default function (doc, svg, x, y, options) {
33493368 doc . transform ( bBox [ 2 ] - bBox [ 0 ] , 0 , 0 , bBox [ 3 ] - bBox [ 1 ] , bBox [ 0 ] , bBox [ 1 ] ) ;
33503369 }
33513370 this . clip ( ) ;
3371+ // treat all masks as luminosity mask
33523372 this . drawChildren ( false , true ) ;
33533373 doc . restore ( ) ;
3374+ doc . _activeColorProfile = savedColorProfile ;
33543375 docEndGroup ( group ) ;
33553376 docApplyMask ( group ) ;
33563377 } ;
@@ -3424,7 +3445,7 @@ export default function (doc, svg, x, y, options) {
34243445 }
34253446 if ( fill || stroke || isClip ) {
34263447 if ( fill ) {
3427- docFillColor ( fill , isClip ) ;
3448+ docFillColor ( fill , isClip || isMask ) ;
34283449 }
34293450 if ( stroke && strokeWidth ) {
34303451 docStrokeColor ( stroke ) ;
@@ -3458,7 +3479,7 @@ export default function (doc, svg, x, y, options) {
34583479 let fill = this . getFill ( isClip , isMask ) ,
34593480 stroke = this . getStroke ( isClip , isMask ) ;
34603481 if ( fill ) {
3461- docFillColor ( fill , isClip ) ;
3482+ docFillColor ( fill , isClip || isMask ) ;
34623483 }
34633484 if ( stroke ) {
34643485 docStrokeColor ( stroke ) ;
0 commit comments