diff --git a/lib/web_ui/dev/goldens_lock.yaml b/lib/web_ui/dev/goldens_lock.yaml index 2d5ea68c65afab..7daac2c7ae55ff 100644 --- a/lib/web_ui/dev/goldens_lock.yaml +++ b/lib/web_ui/dev/goldens_lock.yaml @@ -1,2 +1,2 @@ repository: https://github.com/flutter/goldens.git -revision: 4fb2ce1ea4b3a0bd48b01d7b3724be87244964d6 +revision: f26d68c3596eece3d40112e9dff01dc55d9bae97 diff --git a/lib/web_ui/lib/src/engine/bitmap_canvas.dart b/lib/web_ui/lib/src/engine/bitmap_canvas.dart index bd3fc5390b8ea5..0d9420c8f60c7e 100644 --- a/lib/web_ui/lib/src/engine/bitmap_canvas.dart +++ b/lib/web_ui/lib/src/engine/bitmap_canvas.dart @@ -965,7 +965,9 @@ List _clipContent(List<_SaveClipEntry> clipStack, ..height = '${roundRect.bottom - clipOffsetY}px'; setElementTransform(curElement, newClipTransform.storage); } else if (entry.path != null) { - curElement.style.transform = matrix4ToCssTransform(newClipTransform); + curElement.style + ..transform = matrix4ToCssTransform(newClipTransform) + ..transformOrigin = '0 0 0'; String svgClipPath = createSvgClipDef(curElement as html.HtmlElement, entry.path!); final html.Element clipElement = html.Element.html(svgClipPath, treeSanitizer: _NullTreeSanitizer()); diff --git a/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart b/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart index 81f1163a4431ec..9e83e2734ff935 100644 --- a/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/canvas_draw_image_golden_test.dart @@ -23,7 +23,7 @@ void main() async { // Commit a recording canvas to a bitmap, and compare with the expected Future _checkScreenshot(RecordingCanvas rc, String fileName, {Rect region = const Rect.fromLTWH(0, 0, 500, 500), - double maxDiffRatePercent = 0.0}) async { + double maxDiffRatePercent = 0.0, bool write = false}) async { final EngineCanvas engineCanvas = BitmapCanvas(screenRect); rc.endRecording(); @@ -35,7 +35,7 @@ void main() async { sceneElement.append(engineCanvas.rootElement); html.document.body.append(sceneElement); await matchGoldenFile('$fileName.png', - region: region, maxDiffRatePercent: maxDiffRatePercent); + region: region, maxDiffRatePercent: maxDiffRatePercent, write: write); } finally { // The page is reused across tests, so remove the element after taking the // Scuba screenshot. @@ -374,6 +374,28 @@ void main() async { sceneElement.remove(); } }); + + // Regression test for https://github.com/flutter/flutter/issues/61691 + // + // The bug in bitmap_canvas.dart was that when we transformed and clipped + // the image we did not apply `transform-origin: 0 0 0` to the clipping + // element which resulted in an undesirable offset. + test('Paints clipped and transformed image', () async { + final Rect region = const Rect.fromLTRB(0, 0, 60, 70); + final RecordingCanvas canvas = RecordingCanvas(region); + canvas.translate(10, 10); + canvas.transform(Matrix4.rotationZ(0.4).storage); + canvas.clipPath(Path() + ..moveTo(10, 10) + ..lineTo(50, 10) + ..lineTo(50, 30) + ..lineTo(10, 30) + ..close() + ); + canvas.drawImage(createNineSliceImage(), Offset.zero, Paint()); + await _checkScreenshot(canvas, 'draw_clipped_and_transformed_image', region: region, + maxDiffRatePercent: 1.0); + }); } // 9 slice test image that has a shiny/glass look.