@@ -306,6 +306,7 @@ class Renderer2D extends Renderer {
306306 // Start a new path. Everything from here on out should become part of this
307307 // one path so that we can clip to the whole thing.
308308 this . clipPath = new Path2D ( ) ;
309+ this . _clipBaseTransform = this . drawingContext . getTransform ( ) ;
309310
310311 if ( this . _clipInvert ) {
311312 // Slight hack: draw a big rectangle over everything with reverse winding
@@ -331,7 +332,11 @@ class Renderer2D extends Renderer {
331332 }
332333
333334 endClip ( ) {
335+ const savedTransform = this . drawingContext . getTransform ( ) ;
336+ this . drawingContext . setTransform ( this . _clipBaseTransform ) ;
334337 this . drawingContext . clip ( this . clipPath ) ;
338+ this . drawingContext . setTransform ( savedTransform ) ;
339+
335340 this . clipPath = null ;
336341
337342 super . endClip ( ) ;
@@ -546,16 +551,17 @@ class Renderer2D extends Renderer {
546551 // round down to get integer numbers
547552 x = Math . floor ( x ) ;
548553 y = Math . floor ( y ) ;
549- if ( imgOrCol instanceof Image ) {
554+ if ( imgOrCol instanceof Graphics || imgOrCol instanceof Image ) {
550555 this . drawingContext . save ( ) ;
551556 this . drawingContext . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
552557 this . drawingContext . scale (
553558 this . _pixelDensity ,
554559 this . _pixelDensity
555560 ) ;
556- this . drawingContext . clearRect ( x , y , imgOrCol . width , imgOrCol . height ) ;
557- this . drawingContext . drawImage ( imgOrCol . canvas , x , y ) ;
558- this . drawingContext . restore ( ) ;
561+ const width = imgOrCol . width ;
562+ const height = imgOrCol . height ;
563+ this . drawingContext . clearRect ( x , y , width , height ) ;
564+ this . drawingContext . drawImage ( imgOrCol . canvas , x , y , width , height ) ;
559565 } else {
560566 let r = 0 ,
561567 g = 0 ,
@@ -652,7 +658,7 @@ class Renderer2D extends Renderer {
652658 * start <= stop < start + TWO_PI
653659 */
654660 arc ( x , y , w , h , start , stop , mode ) {
655- const ctx = this . clipPa || this . drawingContext ;
661+ const ctx = this . drawingContext ;
656662 const rx = w / 2.0 ;
657663 const ry = h / 2.0 ;
658664 const epsilon = 0.00001 ; // Smallest visible angle on displays up to 4K.
@@ -663,7 +669,15 @@ class Renderer2D extends Renderer {
663669 centerY = y + h / 2 ,
664670 radiusX = w / 2 ,
665671 radiusY = h / 2 ;
666-
672+ if ( this . _clipping ) {
673+ const tempPath = new Path2D ( ) ;
674+ tempPath . ellipse ( centerX , centerY , radiusX , radiusY , 0 , start , stop ) ;
675+ const currentTransform = this . drawingContext . getTransform ( ) ;
676+ const clipBaseTransform = this . _clipBaseTransform . inverse ( ) ;
677+ const relativeTransform = clipBaseTransform . multiply ( currentTransform ) ;
678+ this . clipPath . addPath ( tempPath , relativeTransform ) ;
679+ return this ;
680+ }
667681 // Determines whether to add a line to the center, which should be done
668682 // when the mode is PIE or default; as well as when the start and end
669683 // angles do not form a full circle.
@@ -675,16 +689,16 @@ class Renderer2D extends Renderer {
675689
676690 // Fill curves
677691 if ( this . states . fillColor ) {
678- if ( ! this . _clipping ) ctx . beginPath ( ) ;
692+ ctx . beginPath ( ) ;
679693 ctx . ellipse ( centerX , centerY , radiusX , radiusY , 0 , start , stop ) ;
680694 if ( createPieSlice ) ctx . lineTo ( centerX , centerY ) ;
681695 ctx . closePath ( ) ;
682- if ( ! this . _clipping ) ctx . fill ( ) ;
696+ ctx . fill ( ) ;
683697 }
684698
685699 // Stroke curves
686700 if ( this . states . strokeColor ) {
687- if ( ! this . _clipping ) ctx . beginPath ( ) ;
701+ ctx . beginPath ( ) ;
688702 ctx . ellipse ( centerX , centerY , radiusX , radiusY , 0 , start , stop ) ;
689703
690704 if ( mode === constants . PIE && createPieSlice ) {
@@ -697,16 +711,15 @@ class Renderer2D extends Renderer {
697711 // Stroke connects back to path begin for both PIE and CHORD
698712 ctx . closePath ( ) ;
699713 }
700-
701- if ( ! this . _clipping ) ctx . stroke ( ) ;
714+ ctx . stroke ( ) ;
702715 }
703716
704717 return this ;
705718
706719 }
707720
708721 ellipse ( args ) {
709- const ctx = this . clipPath || this . drawingContext ;
722+ const ctx = this . drawingContext ;
710723 const doFill = ! ! this . states . fillColor ,
711724 doStroke = this . states . strokeColor ;
712725 const x = parseFloat ( args [ 0 ] ) ,
@@ -726,56 +739,83 @@ class Renderer2D extends Renderer {
726739 centerY = y + h / 2 ,
727740 radiusX = w / 2 ,
728741 radiusY = h / 2 ;
729- if ( ! this . _clipping ) ctx . beginPath ( ) ;
730-
742+ if ( this . _clipping ) {
743+ const tempPath = new Path2D ( ) ;
744+ tempPath . ellipse ( centerX , centerY , radiusX , radiusY , 0 , 0 , 2 * Math . PI ) ;
745+ const currentTransform = this . drawingContext . getTransform ( ) ;
746+ const clipBaseTransform = this . _clipBaseTransform . inverse ( ) ;
747+ const relativeTransform = clipBaseTransform . multiply ( currentTransform ) ;
748+ this . clipPath . addPath ( tempPath , relativeTransform ) ;
749+ return this ;
750+ }
751+ ctx . beginPath ( ) ;
731752 ctx . ellipse ( centerX , centerY , radiusX , radiusY , 0 , 0 , 2 * Math . PI ) ;
732753 ctx . closePath ( ) ;
733-
734- if ( ! this . _clipping && doFill ) {
754+ if ( doFill ) {
735755 ctx . fill ( ) ;
736756 }
737- if ( ! this . _clipping && doStroke ) {
757+ if ( doStroke ) {
738758 ctx . stroke ( ) ;
739759 }
760+
761+ return this ;
740762 }
741763
742764 line ( x1 , y1 , x2 , y2 ) {
743- const ctx = this . clipPath || this . drawingContext ;
765+ const ctx = this . drawingContext ;
744766 if ( ! this . states . strokeColor ) {
745767 return this ;
746768 } else if ( this . _getStroke ( ) === styleEmpty ) {
747769 return this ;
748770 }
749- if ( ! this . _clipping ) ctx . beginPath ( ) ;
771+ if ( this . _clipping ) {
772+ const tempPath = new Path2D ( ) ;
773+ tempPath . moveTo ( x1 , y1 ) ;
774+ tempPath . lineTo ( x2 , y2 ) ;
775+ const currentTransform = this . drawingContext . getTransform ( ) ;
776+ const clipBaseTransform = this . _clipBaseTransform . inverse ( ) ;
777+ const relativeTransform = clipBaseTransform . multiply ( currentTransform ) ;
778+ this . clipPath . addPath ( tempPath , relativeTransform ) ;
779+ return this ;
780+ }
781+ ctx . beginPath ( ) ;
750782 ctx . moveTo ( x1 , y1 ) ;
751783 ctx . lineTo ( x2 , y2 ) ;
752784 ctx . stroke ( ) ;
785+
753786 return this ;
754787 }
755788
756789 point ( x , y ) {
757- const ctx = this . clipPath || this . drawingContext ;
790+ const ctx = this . drawingContext ;
758791 if ( ! this . states . strokeColor ) {
759792 return this ;
760793 } else if ( this . _getStroke ( ) === styleEmpty ) {
761794 return this ;
762795 }
763796 const s = this . _getStroke ( ) ;
764797 const f = this . _getFill ( ) ;
765- if ( ! this . _clipping ) {
766- // swapping fill color to stroke and back after for correct point rendering
767- this . _setFill ( s ) ;
798+ if ( this . _clipping ) {
799+ const tempPath = new Path2D ( ) ;
800+ const drawingContextWidth = this . drawingContext . lineWidth ;
801+ tempPath . arc ( x , y , drawingContextWidth / 2 , 0 , constants . TWO_PI ) ;
802+ const currentTransform = this . drawingContext . getTransform ( ) ;
803+ const clipBaseTransform = this . _clipBaseTransform . inverse ( ) ;
804+ const relativeTransform = clipBaseTransform . multiply ( currentTransform ) ;
805+ this . clipPath . addPath ( tempPath , relativeTransform ) ;
806+ return this ;
768807 }
769- if ( ! this . _clipping ) ctx . beginPath ( ) ;
808+ this . _setFill ( s ) ;
809+ ctx . beginPath ( ) ;
770810 ctx . arc ( x , y , ctx . lineWidth / 2 , 0 , constants . TWO_PI , false ) ;
771- if ( ! this . _clipping ) {
772- ctx . fill ( ) ;
773- this . _setFill ( f ) ;
774- }
811+ ctx . fill ( ) ;
812+ this . _setFill ( f ) ;
813+
814+ return this ;
775815 }
776816
777817 quad ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 ) {
778- const ctx = this . clipPath || this . drawingContext ;
818+ const ctx = this . drawingContext ;
779819 const doFill = ! ! this . states . fillColor ,
780820 doStroke = this . states . strokeColor ;
781821 if ( doFill && ! doStroke ) {
@@ -787,16 +827,29 @@ class Renderer2D extends Renderer {
787827 return this ;
788828 }
789829 }
790- if ( ! this . _clipping ) ctx . beginPath ( ) ;
830+ if ( this . _clipping ) {
831+ const tempPath = new Path2D ( ) ;
832+ tempPath . moveTo ( x1 , y1 ) ;
833+ tempPath . lineTo ( x2 , y2 ) ;
834+ tempPath . lineTo ( x3 , y3 ) ;
835+ tempPath . lineTo ( x4 , y4 ) ;
836+ tempPath . closePath ( ) ;
837+ const currentTransform = this . drawingContext . getTransform ( ) ;
838+ const clipBaseTransform = this . _clipBaseTransform . inverse ( ) ;
839+ const relativeTransform = clipBaseTransform . multiply ( currentTransform ) ;
840+ this . clipPath . addPath ( tempPath , relativeTransform ) ;
841+ return this ;
842+ }
843+ ctx . beginPath ( ) ;
791844 ctx . moveTo ( x1 , y1 ) ;
792845 ctx . lineTo ( x2 , y2 ) ;
793846 ctx . lineTo ( x3 , y3 ) ;
794847 ctx . lineTo ( x4 , y4 ) ;
795848 ctx . closePath ( ) ;
796- if ( ! this . _clipping && doFill ) {
849+ if ( doFill ) {
797850 ctx . fill ( ) ;
798851 }
799- if ( ! this . _clipping && doStroke ) {
852+ if ( doStroke ) {
800853 ctx . stroke ( ) ;
801854 }
802855 return this ;
@@ -811,7 +864,7 @@ class Renderer2D extends Renderer {
811864 let tr = args [ 5 ] ;
812865 let br = args [ 6 ] ;
813866 let bl = args [ 7 ] ;
814- const ctx = this . clipPath || this . drawingContext ;
867+ const ctx = this . drawingContext ;
815868 const doFill = ! ! this . states . fillColor ,
816869 doStroke = this . states . strokeColor ;
817870 if ( doFill && ! doStroke ) {
@@ -823,8 +876,20 @@ class Renderer2D extends Renderer {
823876 return this ;
824877 }
825878 }
826- if ( ! this . _clipping ) ctx . beginPath ( ) ;
827-
879+ if ( this . _clipping ) {
880+ const tempPath = new Path2D ( ) ;
881+ if ( typeof tl === 'undefined' ) {
882+ tempPath . rect ( x , y , w , h ) ;
883+ } else {
884+ tempPath . roundRect ( x , y , w , h , [ tl , tr , br , bl ] ) ;
885+ }
886+ const currentTransform = this . drawingContext . getTransform ( ) ;
887+ const clipBaseTransform = this . _clipBaseTransform . inverse ( ) ;
888+ const relativeTransform = clipBaseTransform . multiply ( currentTransform ) ;
889+ this . clipPath . addPath ( tempPath , relativeTransform ) ;
890+ return this ;
891+ }
892+ ctx . beginPath ( ) ;
828893 if ( typeof tl === 'undefined' ) {
829894 // No rounded corners
830895 ctx . rect ( x , y , w , h ) ;
@@ -875,18 +940,18 @@ class Renderer2D extends Renderer {
875940
876941 ctx . roundRect ( x , y , w , h , [ tl , tr , br , bl ] ) ;
877942 }
878- if ( ! this . _clipping && this . states . fillColor ) {
943+ if ( doFill ) {
879944 ctx . fill ( ) ;
880945 }
881- if ( ! this . _clipping && this . states . strokeColor ) {
946+ if ( doStroke ) {
882947 ctx . stroke ( ) ;
883948 }
884949 return this ;
885950 }
886951
887952
888953 triangle ( args ) {
889- const ctx = this . clipPath || this . drawingContext ;
954+ const ctx = this . drawingContext ;
890955 const doFill = ! ! this . states . fillColor ,
891956 doStroke = this . states . strokeColor ;
892957 const x1 = args [ 0 ] ,
@@ -904,17 +969,31 @@ class Renderer2D extends Renderer {
904969 return this ;
905970 }
906971 }
907- if ( ! this . _clipping ) ctx . beginPath ( ) ;
972+ if ( this . _clipping ) {
973+ const tempPath = new Path2D ( ) ;
974+ tempPath . moveTo ( x1 , y1 ) ;
975+ tempPath . lineTo ( x2 , y2 ) ;
976+ tempPath . lineTo ( x3 , y3 ) ;
977+ tempPath . closePath ( ) ;
978+ const currentTransform = this . drawingContext . getTransform ( ) ;
979+ const clipBaseTransform = this . _clipBaseTransform . inverse ( ) ;
980+ const relativeTransform = clipBaseTransform . multiply ( currentTransform ) ;
981+ this . clipPath . addPath ( tempPath , relativeTransform ) ;
982+ return this ;
983+ }
984+ ctx . beginPath ( ) ;
908985 ctx . moveTo ( x1 , y1 ) ;
909986 ctx . lineTo ( x2 , y2 ) ;
910987 ctx . lineTo ( x3 , y3 ) ;
911988 ctx . closePath ( ) ;
912- if ( ! this . _clipping && doFill ) {
989+ if ( doFill ) {
913990 ctx . fill ( ) ;
914991 }
915- if ( ! this . _clipping && doStroke ) {
992+ if ( doStroke ) {
916993 ctx . stroke ( ) ;
917994 }
995+
996+ return this ;
918997 }
919998
920999 //////////////////////////////////////////////
0 commit comments