@@ -305,7 +305,7 @@ class Renderer2D extends Renderer {
305305 // Start a new path. Everything from here on out should become part of this
306306 // one path so that we can clip to the whole thing.
307307 this . clipPath = new Path2D ( ) ;
308- this . initialClipTransform = this . drawingContext . getTransform ( ) . inverse ( ) ;
308+ this . initialTransform = this . drawingContext . getTransform ( ) ;
309309
310310 if ( this . _clipInvert ) {
311311 // Slight hack: draw a big rectangle over everything with reverse winding
@@ -331,7 +331,10 @@ class Renderer2D extends Renderer {
331331 }
332332
333333 endClip ( ) {
334+ const currentTransform = this . drawingContext . getTransform ( ) ;
335+ this . drawingContext . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
334336 this . drawingContext . clip ( this . clipPath ) ;
337+ this . drawingContext . setTransform ( currentTransform ) ;
335338 this . clipPath = null ;
336339
337340 super . endClip ( ) ;
@@ -728,25 +731,34 @@ class Renderer2D extends Renderer {
728731 radiusY = h / 2 ;
729732 if ( this . _clipping ) {
730733 const tempPath = new Path2D ( ) ;
731- tempPath . ellipse ( centerX , centerY , radiusX , radiusY , 0 , 0 , 2 * Math . PI ) ;
732-
733- const currentTransform = this . drawingContext . getTransform ( ) ;
734- const initialClip = this . initialClipTransform ;
735- if ( currentTransform . a < 0 || currentTransform . d < 0 ) {
736- const fixedTransform = new DOMMatrix ( [
737- Math . abs ( currentTransform . a ) , currentTransform . b ,
738- currentTransform . c , Math . abs ( currentTransform . d ) ,
739- currentTransform . e , currentTransform . f
740- ] ) ;
741- const relativeTransform = initialClip . multiply ( fixedTransform ) ;
742- this . clipPath . addPath ( tempPath , relativeTransform ) ;
743- } else {
744- // Normal case
745- const relativeTransform = initialClip . multiply ( currentTransform ) ;
746- this . clipPath . addPath ( tempPath , relativeTransform ) ;
747- }
734+ const current = this . drawingContext . getTransform ( ) ;
735+ // Transform coordinates manually but preserve scale signs
736+ const transformPoint = ( x , y ) => {
737+ return {
738+ x : current . a * x + current . c * y + current . e ,
739+ y : current . b * x + current . d * y + current . f
740+ } ;
741+ } ;
742+ const transformedCenter = transformPoint ( centerX , centerY ) ;
743+ // Calculate transformed radii WITHOUT Math.abs() to preserve negative scaling
744+ const scaleX = Math . sqrt ( current . a * current . a + current . c * current . c ) ;
745+ const scaleY = Math . sqrt ( current . b * current . b + current . d * current . d ) ;
746+
747+ // Preserve the sign of the scaling for mirroring effects
748+ const signX = current . a < 0 ? - 1 : 1 ;
749+ const signY = current . d < 0 ? - 1 : 1 ;
750+
751+ const transformedRadiusX = scaleX * radiusX * signX ;
752+ const transformedRadiusY = scaleY * radiusY * signY ;
753+ tempPath . ellipse (
754+ transformedCenter . x ,
755+ transformedCenter . y ,
756+ Math . abs ( transformedRadiusX ) ,
757+ Math . abs ( transformedRadiusY ) ,
758+ 0 , 0 , 2 * Math . PI
759+ ) ;
760+ this . clipPath . addPath ( tempPath ) ;
748761 } else {
749- // Normal drawing (existing code)
750762 ctx . beginPath ( ) ;
751763 ctx . ellipse ( centerX , centerY , radiusX , radiusY , 0 , 0 , 2 * Math . PI ) ;
752764 ctx . closePath ( ) ;
0 commit comments