@@ -160,6 +160,15 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
160160 case * image.Uniform :
161161 drawGlyphOver (dst0 , r , src0 , mask0 , mp )
162162 return
163+ case * image.RGBA :
164+ drawRGBAMaskOver (dst0 , r , src0 , sp , mask0 , mp )
165+ return
166+ case * image.Gray :
167+ drawGrayMaskOver (dst0 , r , src0 , sp , mask0 , mp )
168+ return
169+ case image.RGBA64Image :
170+ drawRGBA64ImageMaskOver (dst0 , r , src0 , sp , mask0 , mp )
171+ return
163172 }
164173 }
165174 } else {
@@ -602,6 +611,156 @@ func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask
602611 }
603612}
604613
614+ func drawGrayMaskOver (dst * image.RGBA , r image.Rectangle , src * image.Gray , sp image.Point , mask * image.Alpha , mp image.Point ) {
615+ x0 , x1 , dx := r .Min .X , r .Max .X , 1
616+ y0 , y1 , dy := r .Min .Y , r .Max .Y , 1
617+ if r .Overlaps (r .Add (sp .Sub (r .Min ))) {
618+ if sp .Y < r .Min .Y || sp .Y == r .Min .Y && sp .X < r .Min .X {
619+ x0 , x1 , dx = x1 - 1 , x0 - 1 , - 1
620+ y0 , y1 , dy = y1 - 1 , y0 - 1 , - 1
621+ }
622+ }
623+
624+ sy := sp .Y + y0 - r .Min .Y
625+ my := mp .Y + y0 - r .Min .Y
626+ sx0 := sp .X + x0 - r .Min .X
627+ mx0 := mp .X + x0 - r .Min .X
628+ sx1 := sx0 + (x1 - x0 )
629+ i0 := dst .PixOffset (x0 , y0 )
630+ di := dx * 4
631+ for y := y0 ; y != y1 ; y , sy , my = y + dy , sy + dy , my + dy {
632+ for i , sx , mx := i0 , sx0 , mx0 ; sx != sx1 ; i , sx , mx = i + di , sx + dx , mx + dx {
633+ mi := mask .PixOffset (mx , my )
634+ ma := uint32 (mask .Pix [mi ])
635+ ma |= ma << 8
636+ si := src .PixOffset (sx , sy )
637+ sy := uint32 (src .Pix [si ])
638+ sy |= sy << 8
639+ sa := uint32 (0xffff )
640+
641+ d := dst .Pix [i : i + 4 : i + 4 ] // Small cap improves performance, see https://golang.org/issue/27857
642+ dr := uint32 (d [0 ])
643+ dg := uint32 (d [1 ])
644+ db := uint32 (d [2 ])
645+ da := uint32 (d [3 ])
646+
647+ // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
648+ // We work in 16-bit color, and so would normally do:
649+ // dr |= dr << 8
650+ // and similarly for dg, db and da, but instead we multiply a
651+ // (which is a 16-bit color, ranging in [0,65535]) by 0x101.
652+ // This yields the same result, but is fewer arithmetic operations.
653+ a := (m - (sa * ma / m )) * 0x101
654+
655+ d [0 ] = uint8 ((dr * a + sy * ma ) / m >> 8 )
656+ d [1 ] = uint8 ((dg * a + sy * ma ) / m >> 8 )
657+ d [2 ] = uint8 ((db * a + sy * ma ) / m >> 8 )
658+ d [3 ] = uint8 ((da * a + sa * ma ) / m >> 8 )
659+ }
660+ i0 += dy * dst .Stride
661+ }
662+ }
663+
664+ func drawRGBAMaskOver (dst * image.RGBA , r image.Rectangle , src * image.RGBA , sp image.Point , mask * image.Alpha , mp image.Point ) {
665+ x0 , x1 , dx := r .Min .X , r .Max .X , 1
666+ y0 , y1 , dy := r .Min .Y , r .Max .Y , 1
667+ if dst == src && r .Overlaps (r .Add (sp .Sub (r .Min ))) {
668+ if sp .Y < r .Min .Y || sp .Y == r .Min .Y && sp .X < r .Min .X {
669+ x0 , x1 , dx = x1 - 1 , x0 - 1 , - 1
670+ y0 , y1 , dy = y1 - 1 , y0 - 1 , - 1
671+ }
672+ }
673+
674+ sy := sp .Y + y0 - r .Min .Y
675+ my := mp .Y + y0 - r .Min .Y
676+ sx0 := sp .X + x0 - r .Min .X
677+ mx0 := mp .X + x0 - r .Min .X
678+ sx1 := sx0 + (x1 - x0 )
679+ i0 := dst .PixOffset (x0 , y0 )
680+ di := dx * 4
681+ for y := y0 ; y != y1 ; y , sy , my = y + dy , sy + dy , my + dy {
682+ for i , sx , mx := i0 , sx0 , mx0 ; sx != sx1 ; i , sx , mx = i + di , sx + dx , mx + dx {
683+ mi := mask .PixOffset (mx , my )
684+ ma := uint32 (mask .Pix [mi ])
685+ ma |= ma << 8
686+ si := src .PixOffset (sx , sy )
687+ sr := uint32 (src .Pix [si + 0 ])
688+ sg := uint32 (src .Pix [si + 1 ])
689+ sb := uint32 (src .Pix [si + 2 ])
690+ sa := uint32 (src .Pix [si + 3 ])
691+ sr |= sr << 8
692+ sg |= sg << 8
693+ sb |= sb << 8
694+ sa |= sa << 8
695+ d := dst .Pix [i : i + 4 : i + 4 ] // Small cap improves performance, see https://golang.org/issue/27857
696+ dr := uint32 (d [0 ])
697+ dg := uint32 (d [1 ])
698+ db := uint32 (d [2 ])
699+ da := uint32 (d [3 ])
700+
701+ // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
702+ // We work in 16-bit color, and so would normally do:
703+ // dr |= dr << 8
704+ // and similarly for dg, db and da, but instead we multiply a
705+ // (which is a 16-bit color, ranging in [0,65535]) by 0x101.
706+ // This yields the same result, but is fewer arithmetic operations.
707+ a := (m - (sa * ma / m )) * 0x101
708+
709+ d [0 ] = uint8 ((dr * a + sr * ma ) / m >> 8 )
710+ d [1 ] = uint8 ((dg * a + sg * ma ) / m >> 8 )
711+ d [2 ] = uint8 ((db * a + sb * ma ) / m >> 8 )
712+ d [3 ] = uint8 ((da * a + sa * ma ) / m >> 8 )
713+ }
714+ i0 += dy * dst .Stride
715+ }
716+ }
717+
718+ func drawRGBA64ImageMaskOver (dst * image.RGBA , r image.Rectangle , src image.RGBA64Image , sp image.Point , mask * image.Alpha , mp image.Point ) {
719+ x0 , x1 , dx := r .Min .X , r .Max .X , 1
720+ y0 , y1 , dy := r .Min .Y , r .Max .Y , 1
721+ if image .Image (dst ) == src && r .Overlaps (r .Add (sp .Sub (r .Min ))) {
722+ if sp .Y < r .Min .Y || sp .Y == r .Min .Y && sp .X < r .Min .X {
723+ x0 , x1 , dx = x1 - 1 , x0 - 1 , - 1
724+ y0 , y1 , dy = y1 - 1 , y0 - 1 , - 1
725+ }
726+ }
727+
728+ sy := sp .Y + y0 - r .Min .Y
729+ my := mp .Y + y0 - r .Min .Y
730+ sx0 := sp .X + x0 - r .Min .X
731+ mx0 := mp .X + x0 - r .Min .X
732+ sx1 := sx0 + (x1 - x0 )
733+ i0 := dst .PixOffset (x0 , y0 )
734+ di := dx * 4
735+ for y := y0 ; y != y1 ; y , sy , my = y + dy , sy + dy , my + dy {
736+ for i , sx , mx := i0 , sx0 , mx0 ; sx != sx1 ; i , sx , mx = i + di , sx + dx , mx + dx {
737+ mi := mask .PixOffset (mx , my )
738+ ma := uint32 (mask .Pix [mi ])
739+ ma |= ma << 8
740+ srgba := src .RGBA64At (sx , sy )
741+ d := dst .Pix [i : i + 4 : i + 4 ] // Small cap improves performance, see https://golang.org/issue/27857
742+ dr := uint32 (d [0 ])
743+ dg := uint32 (d [1 ])
744+ db := uint32 (d [2 ])
745+ da := uint32 (d [3 ])
746+
747+ // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
748+ // We work in 16-bit color, and so would normally do:
749+ // dr |= dr << 8
750+ // and similarly for dg, db and da, but instead we multiply a
751+ // (which is a 16-bit color, ranging in [0,65535]) by 0x101.
752+ // This yields the same result, but is fewer arithmetic operations.
753+ a := (m - (uint32 (srgba .A ) * ma / m )) * 0x101
754+
755+ d [0 ] = uint8 ((dr * a + uint32 (srgba .R )* ma ) / m >> 8 )
756+ d [1 ] = uint8 ((dg * a + uint32 (srgba .G )* ma ) / m >> 8 )
757+ d [2 ] = uint8 ((db * a + uint32 (srgba .B )* ma ) / m >> 8 )
758+ d [3 ] = uint8 ((da * a + uint32 (srgba .A )* ma ) / m >> 8 )
759+ }
760+ i0 += dy * dst .Stride
761+ }
762+ }
763+
605764func drawRGBA (dst * image.RGBA , r image.Rectangle , src image.Image , sp image.Point , mask image.Image , mp image.Point , op Op ) {
606765 x0 , x1 , dx := r .Min .X , r .Max .X , 1
607766 y0 , y1 , dy := r .Min .Y , r .Max .Y , 1
0 commit comments