@@ -71,23 +71,51 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
7171 this . matrix = null ;
7272 }
7373
74- _createGradient ( ctx ) {
74+ isOriginBased ( ) {
75+ return (
76+ this . _p0 [ 0 ] === 0 &&
77+ this . _p0 [ 1 ] === 0 &&
78+ ( ! this . isRadial ( ) || ( this . _p1 [ 0 ] === 0 && this . _p1 [ 1 ] === 0 ) )
79+ ) ;
80+ }
81+
82+ isRadial ( ) {
83+ return this . _type === "radial" ;
84+ }
85+
86+ _createGradient ( ctx , transform = null ) {
7587 let grad ;
88+ let firstPoint = this . _p0 ;
89+ let secondPoint = this . _p1 ;
90+ if ( transform ) {
91+ firstPoint = firstPoint . slice ( ) ;
92+ secondPoint = secondPoint . slice ( ) ;
93+ Util . applyTransform ( firstPoint , transform ) ;
94+ Util . applyTransform ( secondPoint , transform ) ;
95+ }
7696 if ( this . _type === "axial" ) {
7797 grad = ctx . createLinearGradient (
78- this . _p0 [ 0 ] ,
79- this . _p0 [ 1 ] ,
80- this . _p1 [ 0 ] ,
81- this . _p1 [ 1 ]
98+ firstPoint [ 0 ] ,
99+ firstPoint [ 1 ] ,
100+ secondPoint [ 0 ] ,
101+ secondPoint [ 1 ]
82102 ) ;
83103 } else if ( this . _type === "radial" ) {
104+ let r0 = this . _r0 ;
105+ let r1 = this . _r1 ;
106+ if ( transform ) {
107+ const scale = new Float32Array ( 2 ) ;
108+ Util . singularValueDecompose2dScale ( transform , scale ) ;
109+ r0 *= scale [ 0 ] ;
110+ r1 *= scale [ 0 ] ;
111+ }
84112 grad = ctx . createRadialGradient (
85- this . _p0 [ 0 ] ,
86- this . _p0 [ 1 ] ,
87- this . _r0 ,
88- this . _p1 [ 0 ] ,
89- this . _p1 [ 1 ] ,
90- this . _r1
113+ firstPoint [ 0 ] ,
114+ firstPoint [ 1 ] ,
115+ r0 ,
116+ secondPoint [ 0 ] ,
117+ secondPoint [ 1 ] ,
118+ r1
91119 ) ;
92120 }
93121
@@ -100,6 +128,32 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
100128 getPattern ( ctx , owner , inverse , pathType ) {
101129 let pattern ;
102130 if ( pathType === PathType . STROKE || pathType === PathType . FILL ) {
131+ if ( this . isOriginBased ( ) ) {
132+ let transf = Util . transform ( inverse , owner . baseTransform ) ;
133+ if ( this . matrix ) {
134+ transf = Util . transform ( transf , this . matrix ) ;
135+ }
136+ const precision = 1e-3 ;
137+ const n1 = Math . hypot ( transf [ 0 ] , transf [ 1 ] ) ;
138+ const n2 = Math . hypot ( transf [ 2 ] , transf [ 3 ] ) ;
139+ const ps = ( transf [ 0 ] * transf [ 2 ] + transf [ 1 ] * transf [ 3 ] ) / ( n1 * n2 ) ;
140+ if ( Math . abs ( ps ) < precision ) {
141+ // The images of the basis vectors are orthogonal.
142+ if ( this . isRadial ( ) ) {
143+ // If the images of the basis vectors are a square then the
144+ // circles are transformed to circles and we can use a gradient
145+ // directly.
146+ if ( Math . abs ( n1 - n2 ) < precision ) {
147+ return this . _createGradient ( ctx , transf ) ;
148+ }
149+ } else {
150+ // The rectangles are transformed to rectangles and we can use a
151+ // gradient directly.
152+ return this . _createGradient ( ctx , transf ) ;
153+ }
154+ }
155+ }
156+
103157 const ownerBBox = owner . current . getClippedPathBoundingBox (
104158 pathType ,
105159 getCurrentTransform ( ctx )
0 commit comments