diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/layer_visitor.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/layer_visitor.dart index 629f6164596..68b08dc5fe1 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/layer_visitor.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/layer_visitor.dart @@ -329,9 +329,7 @@ class MeasureVisitor extends LayerVisitor { measuringCanvas.save(); measuringCanvas.translate(opacity.offset.dx, opacity.offset.dy); - final ui.Rect saveLayerBounds = opacity.paintBounds.shift(-opacity.offset); - - measuringCanvas.saveLayer(saveLayerBounds, paint); + measuringCanvas.saveLayer(ui.Rect.largest, paint); measureChildren(opacity); // Restore twice: once for the translate and once for the saveLayer. measuringCanvas.restore(); @@ -567,9 +565,7 @@ class PaintVisitor extends LayerVisitor { nWayCanvas.save(); nWayCanvas.translate(opacity.offset.dx, opacity.offset.dy); - final ui.Rect saveLayerBounds = opacity.paintBounds.shift(-opacity.offset); - - nWayCanvas.saveLayer(saveLayerBounds, paint); + nWayCanvas.saveLayer(ui.Rect.largest, paint); paintChildren(opacity); // Restore twice: once for the translate and once for the saveLayer. nWayCanvas.restore(); diff --git a/engine/src/flutter/lib/web_ui/test/ui/scene_builder_test.dart b/engine/src/flutter/lib/web_ui/test/ui/scene_builder_test.dart index 8199b1fd0b3..af17bf98eb3 100644 --- a/engine/src/flutter/lib/web_ui/test/ui/scene_builder_test.dart +++ b/engine/src/flutter/lib/web_ui/test/ui/scene_builder_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; +import 'dart:typed_data'; import 'package:test/bootstrap/browser.dart'; import 'package:test/test.dart'; @@ -403,6 +404,69 @@ Future testMain() async { }, skip: isFirefox && isHtml); // https://github.com/flutter/flutter/issues/86623 + + test('opacity layer with transformed children', () async { + final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); + sceneBuilder.pushOffset(0, 0); + sceneBuilder.pushOpacity(128); + // Push some complex transforms + final Float64List transform1 = Float64List.fromList([ + 1.00, + 0.00, + 0.00, + 0.00, + 0.06, + 1.00, + -0.88, + 0.00, + -0.03, + 0.60, + 0.47, + -0.00, + -4.58, + 257.03, + 63.11, + 0.81, + ]); + final Float64List transform2 = Float64List.fromList([ + 1.00, + 0.00, + 0.00, + 0.00, + 0.07, + 0.90, + -0.94, + 0.00, + -0.02, + 0.75, + 0.33, + -0.00, + -3.28, + 309.29, + 45.20, + 0.86, + ]); + sceneBuilder + .pushTransform(Matrix4.identity().scaled(0.3, 0.3).toFloat64()); + sceneBuilder.pushTransform(transform1); + sceneBuilder.pushTransform(transform2); + + sceneBuilder.addPicture(const ui.Offset(20, 20), + drawPicture((ui.Canvas canvas) { + canvas.drawCircle(const ui.Offset(25, 75), 25, + ui.Paint()..color = const ui.Color(0xFFFF0000)); + })); + sceneBuilder.pop(); + sceneBuilder.pop(); + sceneBuilder.pop(); + sceneBuilder.pop(); + sceneBuilder.pop(); + await renderScene(sceneBuilder.build()); + + await matchGoldenFile( + 'scene_builder_opacity_layer_with_transformed_children.png', + region: region); + }); }); }