@@ -101,11 +101,7 @@ class _CanvasPool extends _SaveStackTracking {
101101 _rootElement.append (_canvas);
102102 _context = _canvas.context2D;
103103 _contextHandle = ContextStateHandle (_context);
104- _initializeViewport ();
105- if (requiresClearRect) {
106- // Now that the context is reset, clear old contents.
107- _context.clearRect (0 , 0 , _widthInBitmapPixels, _heightInBitmapPixels);
108- }
104+ _initializeViewport (requiresClearRect);
109105 _replayClipStack ();
110106 }
111107
@@ -136,20 +132,34 @@ class _CanvasPool extends _SaveStackTracking {
136132 translate (transform.dx, transform.dy);
137133 }
138134
139- int _replaySingleSaveEntry (
140- int clipDepth, Matrix4 transform, List <_SaveClipEntry > clipStack) {
135+ int _replaySingleSaveEntry (int clipDepth, Matrix4 prevTransform,
136+ Matrix4 transform, List <_SaveClipEntry > clipStack) {
141137 final html.CanvasRenderingContext2D ctx = _context;
142- if (! transform.isIdentity ()) {
143- final double ratio = EngineWindow .browserDevicePixelRatio;
144- ctx.setTransform (ratio, 0 , 0 , ratio, 0 , 0 );
145- ctx.transform (transform[0 ], transform[1 ], transform[4 ], transform[5 ],
146- transform[12 ], transform[13 ]);
147- }
148138 if (clipStack != null ) {
149139 for (int clipCount = clipStack.length;
150140 clipDepth < clipCount;
151141 clipDepth++ ) {
152142 _SaveClipEntry clipEntry = clipStack[clipDepth];
143+ Matrix4 clipTimeTransform = clipEntry.currentTransform;
144+ // If transform for entry recording change since last element, update.
145+ // Comparing only matrix3 elements since Canvas API restricted.
146+ if (clipTimeTransform[0 ] != prevTransform[0 ] ||
147+ clipTimeTransform[1 ] != prevTransform[1 ] ||
148+ clipTimeTransform[4 ] != prevTransform[4 ] ||
149+ clipTimeTransform[5 ] != prevTransform[5 ] ||
150+ clipTimeTransform[12 ] != prevTransform[12 ] ||
151+ clipTimeTransform[13 ] != prevTransform[13 ]) {
152+ final double ratio = EngineWindow .browserDevicePixelRatio;
153+ ctx.setTransform (ratio, 0 , 0 , ratio, 0 , 0 );
154+ ctx.transform (
155+ clipTimeTransform[0 ],
156+ clipTimeTransform[1 ],
157+ clipTimeTransform[4 ],
158+ clipTimeTransform[5 ],
159+ clipTimeTransform[12 ],
160+ clipTimeTransform[13 ]);
161+ prevTransform = clipTimeTransform;
162+ }
153163 if (clipEntry.rect != null ) {
154164 _clipRect (ctx, clipEntry.rect);
155165 } else if (clipEntry.rrect != null ) {
@@ -160,23 +170,39 @@ class _CanvasPool extends _SaveStackTracking {
160170 }
161171 }
162172 }
173+ // If transform was changed between last clip operation and save call,
174+ // update.
175+ if (transform[0 ] != prevTransform[0 ] ||
176+ transform[1 ] != prevTransform[1 ] ||
177+ transform[4 ] != prevTransform[4 ] ||
178+ transform[5 ] != prevTransform[5 ] ||
179+ transform[12 ] != prevTransform[12 ] ||
180+ transform[13 ] != prevTransform[13 ]) {
181+ final double ratio = EngineWindow .browserDevicePixelRatio;
182+ ctx.setTransform (ratio, 0 , 0 , ratio, 0 , 0 );
183+ ctx.transform (transform[0 ], transform[1 ], transform[4 ], transform[5 ],
184+ transform[12 ], transform[13 ]);
185+ }
163186 return clipDepth;
164187 }
165188
166189 void _replayClipStack () {
167190 // Replay save/clip stack on this canvas now.
168191 html.CanvasRenderingContext2D ctx = _context;
169192 int clipDepth = 0 ;
193+ Matrix4 prevTransform = Matrix4 .identity ();
170194 for (int saveStackIndex = 0 , len = _saveStack.length;
171195 saveStackIndex < len;
172196 saveStackIndex++ ) {
173197 _SaveStackEntry saveEntry = _saveStack[saveStackIndex];
174198 clipDepth = _replaySingleSaveEntry (
175- clipDepth, saveEntry.transform, saveEntry.clipStack);
199+ clipDepth, prevTransform, saveEntry.transform, saveEntry.clipStack);
200+ prevTransform = saveEntry.transform;
176201 ctx.save ();
177202 ++ _saveContextCount;
178203 }
179- _replaySingleSaveEntry (clipDepth, _currentTransform, _clipStack);
204+ _replaySingleSaveEntry (
205+ clipDepth, prevTransform, _currentTransform, _clipStack);
180206 }
181207
182208 // Marks this pool for reuse.
@@ -216,7 +242,7 @@ class _CanvasPool extends _SaveStackTracking {
216242 /// Configures the canvas such that its coordinate system follows the scene's
217243 /// coordinate system, and the pixel ratio is applied such that CSS pixels are
218244 /// translated to bitmap pixels.
219- void _initializeViewport () {
245+ void _initializeViewport (bool clearCanvas ) {
220246 html.CanvasRenderingContext2D ctx = context;
221247 // Save the canvas state with top-level transforms so we can undo
222248 // any clips later when we reuse the canvas.
@@ -226,6 +252,9 @@ class _CanvasPool extends _SaveStackTracking {
226252 // We always start with identity transform because the surrounding transform
227253 // is applied on the DOM elements.
228254 ctx.setTransform (1 , 0 , 0 , 1 , 0 , 0 );
255+ if (clearCanvas) {
256+ ctx.clearRect (0 , 0 , _widthInBitmapPixels, _heightInBitmapPixels);
257+ }
229258
230259 // This scale makes sure that 1 CSS pixel is translated to the correct
231260 // number of bitmap pixels.
0 commit comments