[framework] remove usage and deprecate physical model layer (#102274)
diff --git a/packages/flutter/lib/src/rendering/flex.dart b/packages/flutter/lib/src/rendering/flex.dart
index 99107df..04043d0 100644
--- a/packages/flutter/lib/src/rendering/flex.dart
+++ b/packages/flutter/lib/src/rendering/flex.dart
@@ -1083,20 +1083,14 @@
if (size.isEmpty)
return;
- if (clipBehavior == Clip.none) {
- _clipRectLayer.layer = null;
- defaultPaint(context, offset);
- } else {
- // We have overflow and the clipBehavior isn't none. Clip it.
- _clipRectLayer.layer = context.pushClipRect(
- needsCompositing,
- offset,
- Offset.zero & size,
- defaultPaint,
- clipBehavior: clipBehavior,
- oldLayer: _clipRectLayer.layer,
- );
- }
+ _clipRectLayer.layer = context.pushClipRect(
+ needsCompositing,
+ offset,
+ Offset.zero & size,
+ defaultPaint,
+ clipBehavior: clipBehavior,
+ oldLayer: _clipRectLayer.layer,
+ );
assert(() {
// Only set this if it's null to save work. It gets reset to null if the
diff --git a/packages/flutter/lib/src/rendering/flow.dart b/packages/flutter/lib/src/rendering/flow.dart
index 153fe3f..4655d06 100644
--- a/packages/flutter/lib/src/rendering/flow.dart
+++ b/packages/flutter/lib/src/rendering/flow.dart
@@ -388,19 +388,14 @@
@override
void paint(PaintingContext context, Offset offset) {
- if (clipBehavior == Clip.none) {
- _clipRectLayer.layer = null;
- _paintWithDelegate(context, offset);
- } else {
- _clipRectLayer.layer = context.pushClipRect(
- needsCompositing,
- offset,
- Offset.zero & size,
- _paintWithDelegate,
- clipBehavior: clipBehavior,
- oldLayer: _clipRectLayer.layer,
- );
- }
+ _clipRectLayer.layer = context.pushClipRect(
+ needsCompositing,
+ offset,
+ Offset.zero & size,
+ _paintWithDelegate,
+ clipBehavior: clipBehavior,
+ oldLayer: _clipRectLayer.layer,
+ );
}
final LayerHandle<ClipRectLayer> _clipRectLayer = LayerHandle<ClipRectLayer>();
diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart
index 4644180..b7f468a 100644
--- a/packages/flutter/lib/src/rendering/layer.dart
+++ b/packages/flutter/lib/src/rendering/layer.dart
@@ -1972,12 +1972,20 @@
/// When debugging, setting [debugDisablePhysicalShapeLayers] to true will cause this
/// layer to be skipped (directly replaced by its children). This can be helpful
/// to track down the cause of performance problems.
+@Deprecated(
+ 'Use a clip and canvas operations directly (See RenderPhysicalModel). '
+ 'This feature was deprecated after v2.13.0-0.0.pre.',
+)
class PhysicalModelLayer extends ContainerLayer {
/// Creates a composited layer that uses a physical model to producing
/// lighting effects.
///
/// The [clipPath], [clipBehavior], [elevation], [color], and [shadowColor]
/// arguments must be non-null before the compositing phase of the pipeline.
+ @Deprecated(
+ 'Use a clip and canvas operations directly (See RenderPhysicalModel). '
+ 'This feature was deprecated after v2.13.0-0.0.pre.',
+ )
PhysicalModelLayer({
Path? clipPath,
Clip clipBehavior = Clip.none,
diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart
index c517ae1..73648a2 100644
--- a/packages/flutter/lib/src/rendering/object.dart
+++ b/packages/flutter/lib/src/rendering/object.dart
@@ -491,6 +491,10 @@
/// (e.g. from opacity layer to a clip rect layer).
/// {@endtemplate}
ClipRectLayer? pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter, { Clip clipBehavior = Clip.hardEdge, ClipRectLayer? oldLayer }) {
+ if (clipBehavior == Clip.none) {
+ painter(this, offset);
+ return null;
+ }
final Rect offsetClipRect = clipRect.shift(offset);
if (needsCompositing) {
final ClipRectLayer layer = oldLayer ?? ClipRectLayer();
@@ -526,6 +530,10 @@
/// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
ClipRRectLayer? pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, RRect clipRRect, PaintingContextCallback painter, { Clip clipBehavior = Clip.antiAlias, ClipRRectLayer? oldLayer }) {
assert(clipBehavior != null);
+ if (clipBehavior == Clip.none) {
+ painter(this, offset);
+ return null;
+ }
final Rect offsetBounds = bounds.shift(offset);
final RRect offsetClipRRect = clipRRect.shift(offset);
if (needsCompositing) {
@@ -562,6 +570,10 @@
/// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
ClipPathLayer? pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter, { Clip clipBehavior = Clip.antiAlias, ClipPathLayer? oldLayer }) {
assert(clipBehavior != null);
+ if (clipBehavior == Clip.none) {
+ painter(this, offset);
+ return null;
+ }
final Rect offsetBounds = bounds.shift(offset);
final Path offsetClipPath = clipPath.shift(offset);
if (needsCompositing) {
diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart
index 7e45a9d..28b5990 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -1828,9 +1828,6 @@
}
@override
- bool get alwaysNeedsCompositing => true;
-
- @override
void describeSemanticsConfiguration(SemanticsConfiguration config) {
super.describeSemanticsConfiguration(config);
config.elevation = elevation;
@@ -1845,6 +1842,8 @@
}
}
+final Paint _transparentPaint = Paint()..color = const Color(0x00000000);
+
/// Creates a physical model layer that clips its child to a rounded
/// rectangle.
///
@@ -1873,9 +1872,6 @@
_shape = shape,
_borderRadius = borderRadius;
- @override
- PhysicalModelLayer? get layer => super.layer as PhysicalModelLayer?;
-
/// The shape of the layer.
///
/// Defaults to [BoxShape.rectangle]. The [borderRadius] affects the corners
@@ -1933,42 +1929,79 @@
@override
void paint(PaintingContext context, Offset offset) {
- if (child != null) {
- _updateClip();
- final RRect offsetRRect = _clip!.shift(offset);
- final Rect offsetBounds = offsetRRect.outerRect;
- final Path offsetRRectAsPath = Path()..addRRect(offsetRRect);
- bool paintShadows = true;
- assert(() {
- if (debugDisableShadows) {
- if (elevation > 0.0) {
- context.canvas.drawRRect(
- offsetRRect,
- Paint()
- ..color = shadowColor
- ..style = PaintingStyle.stroke
- ..strokeWidth = elevation * 2.0,
- );
- }
- paintShadows = false;
- }
- return true;
- }());
- layer ??= PhysicalModelLayer();
- layer!
- ..clipPath = offsetRRectAsPath
- ..clipBehavior = clipBehavior
- ..elevation = paintShadows ? elevation : 0.0
- ..color = color
- ..shadowColor = shadowColor;
- context.pushLayer(layer!, super.paint, offset, childPaintBounds: offsetBounds);
- assert(() {
- layer!.debugCreator = debugCreator;
- return true;
- }());
- } else {
+ if (child == null) {
layer = null;
+ return;
}
+
+ _updateClip();
+ final RRect offsetRRect = _clip!.shift(offset);
+ final Rect offsetBounds = offsetRRect.outerRect;
+ final Path offsetRRectAsPath = Path()..addRRect(offsetRRect);
+ bool paintShadows = true;
+ assert(() {
+ if (debugDisableShadows) {
+ if (elevation > 0.0) {
+ context.canvas.drawRRect(
+ offsetRRect,
+ Paint()
+ ..color = shadowColor
+ ..style = PaintingStyle.stroke
+ ..strokeWidth = elevation * 2.0,
+ );
+ }
+ paintShadows = false;
+ }
+ return true;
+ }());
+
+ final Canvas canvas = context.canvas;
+ if (elevation != 0.0 && paintShadows) {
+ // The drawShadow call doesn't add the region of the shadow to the
+ // picture's bounds, so we draw a hardcoded amount of extra space to
+ // account for the maximum potential area of the shadow.
+ // TODO(jsimmons): remove this when Skia does it for us.
+ canvas.drawRect(
+ offsetBounds.inflate(20.0),
+ _transparentPaint,
+ );
+ canvas.drawShadow(
+ offsetRRectAsPath,
+ shadowColor,
+ elevation,
+ color.alpha != 0xFF,
+ );
+ }
+ final bool usesSaveLayer = clipBehavior == Clip.antiAliasWithSaveLayer;
+ if (!usesSaveLayer) {
+ canvas.drawRRect(
+ offsetRRect,
+ Paint()..color = color
+ );
+ }
+ layer = context.pushClipRRect(
+ needsCompositing,
+ offset,
+ Offset.zero & size,
+ _clip!,
+ (PaintingContext context, Offset offset) {
+ if (usesSaveLayer) {
+ // If we want to avoid the bleeding edge artifact
+ // (https://github.com/flutter/flutter/issues/18057#issue-328003931)
+ // using saveLayer, we have to call drawPaint instead of drawPath as
+ // anti-aliased drawPath will always have such artifacts.
+ context.canvas.drawPaint( Paint()..color = color);
+ }
+ super.paint(context, offset);
+ },
+ oldLayer: layer as ClipRRectLayer?,
+ clipBehavior: clipBehavior,
+ );
+
+ assert(() {
+ layer?.debugCreator = debugCreator;
+ return true;
+ }());
}
@override
@@ -2007,9 +2040,6 @@
assert(shadowColor != null);
@override
- PhysicalModelLayer? get layer => super.layer as PhysicalModelLayer?;
-
- @override
Path get _defaultClip => Path()..addRect(Offset.zero & size);
@override
@@ -2025,41 +2055,78 @@
@override
void paint(PaintingContext context, Offset offset) {
- if (child != null) {
- _updateClip();
- final Rect offsetBounds = offset & size;
- final Path offsetPath = _clip!.shift(offset);
- bool paintShadows = true;
- assert(() {
- if (debugDisableShadows) {
- if (elevation > 0.0) {
- context.canvas.drawPath(
- offsetPath,
- Paint()
- ..color = shadowColor
- ..style = PaintingStyle.stroke
- ..strokeWidth = elevation * 2.0,
- );
- }
- paintShadows = false;
- }
- return true;
- }());
- layer ??= PhysicalModelLayer();
- layer!
- ..clipPath = offsetPath
- ..clipBehavior = clipBehavior
- ..elevation = paintShadows ? elevation : 0.0
- ..color = color
- ..shadowColor = shadowColor;
- context.pushLayer(layer!, super.paint, offset, childPaintBounds: offsetBounds);
- assert(() {
- layer!.debugCreator = debugCreator;
- return true;
- }());
- } else {
+ if (child == null) {
layer = null;
+ return;
}
+
+ _updateClip();
+ final Rect offsetBounds = offset & size;
+ final Path offsetPath = _clip!.shift(offset);
+ bool paintShadows = true;
+ assert(() {
+ if (debugDisableShadows) {
+ if (elevation > 0.0) {
+ context.canvas.drawPath(
+ offsetPath,
+ Paint()
+ ..color = shadowColor
+ ..style = PaintingStyle.stroke
+ ..strokeWidth = elevation * 2.0,
+ );
+ }
+ paintShadows = false;
+ }
+ return true;
+ }());
+
+ final Canvas canvas = context.canvas;
+ if (elevation != 0.0 && paintShadows) {
+ // The drawShadow call doesn't add the region of the shadow to the
+ // picture's bounds, so we draw a hardcoded amount of extra space to
+ // account for the maximum potential area of the shadow.
+ // TODO(jsimmons): remove this when Skia does it for us.
+ canvas.drawRect(
+ offsetBounds.inflate(20.0),
+ _transparentPaint,
+ );
+ canvas.drawShadow(
+ offsetPath,
+ shadowColor,
+ elevation,
+ color.alpha != 0xFF,
+ );
+ }
+ final bool usesSaveLayer = clipBehavior == Clip.antiAliasWithSaveLayer;
+ if (!usesSaveLayer) {
+ canvas.drawPath(
+ offsetPath,
+ Paint()..color = color
+ );
+ }
+ layer = context.pushClipPath(
+ needsCompositing,
+ offset,
+ Offset.zero & size,
+ _clip!,
+ (PaintingContext context, Offset offset) {
+ if (usesSaveLayer) {
+ // If we want to avoid the bleeding edge artifact
+ // (https://github.com/flutter/flutter/issues/18057#issue-328003931)
+ // using saveLayer, we have to call drawPaint instead of drawPath as
+ // anti-aliased drawPath will always have such artifacts.
+ context.canvas.drawPaint( Paint()..color = color);
+ }
+ super.paint(context, offset);
+ },
+ oldLayer: layer as ClipPathLayer?,
+ clipBehavior: clipBehavior,
+ );
+
+ assert(() {
+ layer?.debugCreator = debugCreator;
+ return true;
+ }());
}
@override
diff --git a/packages/flutter/lib/src/rendering/shifted_box.dart b/packages/flutter/lib/src/rendering/shifted_box.dart
index 7ecdbb2..1d989ad 100644
--- a/packages/flutter/lib/src/rendering/shifted_box.dart
+++ b/packages/flutter/lib/src/rendering/shifted_box.dart
@@ -799,20 +799,15 @@
return;
}
- if (clipBehavior == Clip.none) {
- _clipRectLayer.layer = null;
- super.paint(context, offset);
- } else {
- // We have overflow and the clipBehavior isn't none. Clip it.
- _clipRectLayer.layer = context.pushClipRect(
- needsCompositing,
- offset,
- Offset.zero & size,
- super.paint,
- clipBehavior: clipBehavior,
- oldLayer: _clipRectLayer.layer,
- );
- }
+ // We have overflow and the clipBehavior isn't none. Clip it.
+ _clipRectLayer.layer = context.pushClipRect(
+ needsCompositing,
+ offset,
+ Offset.zero & size,
+ super.paint,
+ clipBehavior: clipBehavior,
+ oldLayer: _clipRectLayer.layer,
+ );
// Display the overflow indicator.
assert(() {
diff --git a/packages/flutter/test/material/chip_filter_test.dart b/packages/flutter/test/material/chip_filter_test.dart
index 3405f3b..773aada 100644
--- a/packages/flutter/test/material/chip_filter_test.dart
+++ b/packages/flutter/test/material/chip_filter_test.dart
@@ -64,6 +64,8 @@
expect(
finder,
paints
+ // Physical model path
+ ..path()
// The first path that is painted is the selection overlay. We do not care
// how it is painted but it has to be added it to this pattern so that the
// check mark can be checked next.
diff --git a/packages/flutter/test/material/chip_input_test.dart b/packages/flutter/test/material/chip_input_test.dart
index 84929d3..6c6ca97 100644
--- a/packages/flutter/test/material/chip_input_test.dart
+++ b/packages/flutter/test/material/chip_input_test.dart
@@ -64,6 +64,8 @@
expect(
finder,
paints
+ // Physical model layer path
+ ..path()
// The first path that is painted is the selection overlay. We do not care
// how it is painted but it has to be added it to this pattern so that the
// check mark can be checked next.
diff --git a/packages/flutter/test/material/outlined_button_test.dart b/packages/flutter/test/material/outlined_button_test.dart
index ecbf00c..d899247 100644
--- a/packages/flutter/test/material/outlined_button_test.dart
+++ b/packages/flutter/test/material/outlined_button_test.dart
@@ -852,10 +852,6 @@
),
);
}
-
- // 116 = 16 + 'button'.length * 14 + 16, horizontal padding = 16
- const Rect clipRect = Rect.fromLTRB(0.0, 0.0, 116.0, 36.0);
- final Path clipPath = Path()..addRect(clipRect);
final Finder outlinedButton = find.byType(OutlinedButton);
BorderSide getBorderSide() {
@@ -873,12 +869,6 @@
// Expect that the button is disabled and painted with the disabled border color.
expect(tester.widget<OutlinedButton>(outlinedButton).enabled, false);
expect(getBorderSide(), disabledBorderSide);
- _checkPhysicalLayer(
- tester.element(outlinedButton),
- fillColor,
- clipPath: clipPath,
- clipRect: clipRect,
- );
// Pump a new button with a no-op onPressed callback to make it enabled.
await tester.pumpWidget(
@@ -896,23 +886,11 @@
// Wait for the border's color to change to pressed
await tester.pump(const Duration(milliseconds: 200));
expect(getBorderSide(), pressedBorderSide);
- _checkPhysicalLayer(
- tester.element(outlinedButton),
- fillColor,
- clipPath: clipPath,
- clipRect: clipRect,
- );
// Tap gesture completes, button returns to its initial configuration.
await gesture.up();
await tester.pumpAndSettle();
expect(getBorderSide(), enabledBorderSide);
- _checkPhysicalLayer(
- tester.element(outlinedButton),
- fillColor,
- clipPath: clipPath,
- clipRect: clipRect,
- );
});
testWidgets('OutlinedButton has no clip by default', (WidgetTester tester) async {
@@ -1748,29 +1726,6 @@
});
}
-PhysicalModelLayer _findPhysicalLayer(Element element) {
- expect(element, isNotNull);
- RenderObject? object = element.renderObject;
- while (object != null && object is! RenderRepaintBoundary && object is! RenderView) {
- object = object.parent as RenderObject?;
- }
- expect(object!.debugLayer, isNotNull);
- expect(object.debugLayer!.firstChild, isA<PhysicalModelLayer>());
- final PhysicalModelLayer layer = object.debugLayer!.firstChild! as PhysicalModelLayer;
- final Layer child = layer.firstChild!;
- return child is PhysicalModelLayer ? child : layer;
-}
-
-void _checkPhysicalLayer(Element element, Color expectedColor, { Path? clipPath, Rect? clipRect }) {
- final PhysicalModelLayer expectedLayer = _findPhysicalLayer(element);
- expect(expectedLayer.elevation, 0.0);
- expect(expectedLayer.color, expectedColor);
- if (clipPath != null) {
- expect(clipRect, isNotNull);
- expect(expectedLayer.clipPath, coversSameAreaAs(clipPath, areaToCompare: clipRect!.inflate(10.0)));
- }
-}
-
TextStyle _iconStyle(WidgetTester tester, IconData icon) {
final RichText iconRichText = tester.widget<RichText>(
find.descendant(of: find.byIcon(icon), matching: find.byType(RichText)),
diff --git a/packages/flutter/test/material/range_slider_test.dart b/packages/flutter/test/material/range_slider_test.dart
index 6e8595b..c3d0b69 100644
--- a/packages/flutter/test/material/range_slider_test.dart
+++ b/packages/flutter/test/material/range_slider_test.dart
@@ -1360,7 +1360,7 @@
);
// Represents the Raised Button and Range Slider.
- expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 3));
+ expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 4));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 3));
await tester.tap(find.text('Next'));
@@ -1379,7 +1379,7 @@
);
// Represents the raised button with inner page text.
- expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 1));
+ expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1));
// Don't stop holding the value indicator.
diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart
index 5438310..c2c8b6d 100644
--- a/packages/flutter/test/material/slider_test.dart
+++ b/packages/flutter/test/material/slider_test.dart
@@ -784,6 +784,7 @@
expect(
valueIndicatorBox,
paints
+ ..rrect(color: const Color(0xfffafafa))
..rrect(color: customColor1) // active track
..rrect(color: customColor2) // inactive track
..circle(color: customColor1.withOpacity(0.12)) // overlay
@@ -2415,7 +2416,7 @@
..paragraph(),
);
- expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
+ expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 3));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 2));
await tester.tap(find.text('Next'));
@@ -2432,7 +2433,7 @@
);
// Represents the ElevatedButton with inner Text, inner page.
- expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 1));
+ expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1));
// Don't stop holding the value indicator.
diff --git a/packages/flutter/test/material/slider_theme_test.dart b/packages/flutter/test/material/slider_theme_test.dart
index 93e607c..e890fdd 100644
--- a/packages/flutter/test/material/slider_theme_test.dart
+++ b/packages/flutter/test/material/slider_theme_test.dart
@@ -1134,6 +1134,8 @@
expect(
valueIndicatorBox,
paints
+ // physical model
+ ..rrect()
..rrect(rrect: RRect.fromLTRBAndCorners(
24.0, 298.0, 24.0, 302.0,
topLeft: const Radius.circular(2.0),
diff --git a/packages/flutter/test/material/toggle_buttons_test.dart b/packages/flutter/test/material/toggle_buttons_test.dart
index 7937117..55ddfa3 100644
--- a/packages/flutter/test/material/toggle_buttons_test.dart
+++ b/packages/flutter/test/material/toggle_buttons_test.dart
@@ -1015,6 +1015,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model
+ ..path()
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
@@ -1042,6 +1044,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model
+ ..path()
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
@@ -1068,6 +1072,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model
+ ..path()
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
@@ -1108,6 +1114,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model
+ ..path()
..path(
style: PaintingStyle.stroke,
color: borderColor,
@@ -1137,6 +1145,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model
+ ..path()
..path(
style: PaintingStyle.stroke,
color: selectedBorderColor,
@@ -1165,6 +1175,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model
+ ..path()
..path(
style: PaintingStyle.stroke,
color: disabledBorderColor,
@@ -1432,6 +1444,8 @@
expect(
toggleButtonRenderObject[0],
paints
+ // physical model
+ ..path()
// leading side, top and bottom - enabled
..path(
style: PaintingStyle.stroke,
@@ -1445,6 +1459,8 @@
expect(
toggleButtonRenderObject[1],
paints
+ // physical model
+ ..path()
// leading side - selected
..path(
style: PaintingStyle.stroke,
@@ -1464,6 +1480,8 @@
expect(
toggleButtonRenderObject[2],
paints
+ // physical model
+ ..path()
// leading side - selected, since previous button is selected
..path(
style: PaintingStyle.stroke,
@@ -1515,6 +1533,8 @@
expect(
toggleButtonRenderObject[0],
paints
+ // physical model
+ ..path()
// left side, top and right - enabled.
..path(
style: PaintingStyle.stroke,
@@ -1528,6 +1548,8 @@
expect(
toggleButtonRenderObject[1],
paints
+ // physical model
+ ..path()
// top side - selected.
..path(
style: PaintingStyle.stroke,
@@ -1547,6 +1569,8 @@
expect(
toggleButtonRenderObject[2],
paints
+ // physical model
+ ..path()
// top side - selected, since previous button is selected.
..path(
style: PaintingStyle.stroke,
@@ -1712,6 +1736,8 @@
expect(
toggleButtonRenderObject[0],
paints
+ // physical model paints
+ ..path()
// left side, top and right - enabled.
..path(
style: PaintingStyle.stroke,
diff --git a/packages/flutter/test/material/toggle_buttons_theme_test.dart b/packages/flutter/test/material/toggle_buttons_theme_test.dart
index cd8246e..5d26f85 100644
--- a/packages/flutter/test/material/toggle_buttons_theme_test.dart
+++ b/packages/flutter/test/material/toggle_buttons_theme_test.dart
@@ -543,6 +543,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model layer paint
+ ..path()
..path(
style: PaintingStyle.stroke,
color: borderColor,
@@ -576,6 +578,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model layer paint
+ ..path()
..path(
style: PaintingStyle.stroke,
color: selectedBorderColor,
@@ -608,6 +612,8 @@
expect(
toggleButtonRenderObject,
paints
+ // physical model layer paint
+ ..path()
..path(
style: PaintingStyle.stroke,
color: disabledBorderColor,
diff --git a/packages/flutter/test/rendering/debug_test.dart b/packages/flutter/test/rendering/debug_test.dart
index b31703e..74d80e4 100644
--- a/packages/flutter/test/rendering/debug_test.dart
+++ b/packages/flutter/test/rendering/debug_test.dart
@@ -222,7 +222,7 @@
);
final RenderOpacity root = RenderOpacity(
opacity: .5,
- child: blackBox,
+ child: RenderRepaintBoundary(child: blackBox),
);
layout(root, phase: EnginePhase.compositingBits);
diff --git a/packages/flutter/test/rendering/proxy_box_test.dart b/packages/flutter/test/rendering/proxy_box_test.dart
index 70dfff9..4957f2f 100644
--- a/packages/flutter/test/rendering/proxy_box_test.dart
+++ b/packages/flutter/test/rendering/proxy_box_test.dart
@@ -5,9 +5,8 @@
import 'dart:typed_data';
import 'dart:ui' as ui show Gradient, Image, ImageFilter;
-import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
-import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
@@ -15,7 +14,6 @@
void main() {
TestRenderingFlutterBinding.ensureInitialized();
-
test('RenderFittedBox handles applying paint transform and hit-testing with empty size', () {
final RenderFittedBox fittedBox = RenderFittedBox(
child: RenderCustomPaint(
@@ -61,47 +59,20 @@
expect(painted, equals(false));
});
- test('RenderPhysicalModel compositing on Fuchsia', () {
- debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
-
+ test('RenderPhysicalModel compositing', () {
final RenderPhysicalModel root = RenderPhysicalModel(color: const Color(0xffff00ff));
layout(root, phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
+ expect(root.needsCompositing, isFalse);
// On Fuchsia, the system compositor is responsible for drawing shadows
// for physical model layers with non-zero elevation.
root.elevation = 1.0;
pumpFrame(phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
+ expect(root.needsCompositing, isFalse);
root.elevation = 0.0;
pumpFrame(phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
-
- debugDefaultTargetPlatformOverride = null;
- });
-
- test('RenderPhysicalModel compositing on non-Fuchsia', () {
- for (final TargetPlatform platform in TargetPlatform.values) {
- if (platform == TargetPlatform.fuchsia) {
- continue;
- }
- debugDefaultTargetPlatformOverride = platform;
-
- final RenderPhysicalModel root = RenderPhysicalModel(color: const Color(0xffff00ff));
- layout(root, phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
-
- // Flutter now composites physical shapes on all platforms.
- root.elevation = 1.0;
- pumpFrame(phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
-
- root.elevation = 0.0;
- pumpFrame(phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
- }
- debugDefaultTargetPlatformOverride = null;
+ expect(root.needsCompositing, isFalse);
});
test('RenderSemanticsGestureHandler adds/removes correct semantic actions', () {
@@ -128,9 +99,6 @@
group('RenderPhysicalShape', () {
test('shape change triggers repaint', () {
for (final TargetPlatform platform in TargetPlatform.values) {
- if (platform == TargetPlatform.fuchsia) {
- continue;
- }
debugDefaultTargetPlatformOverride = platform;
final RenderPhysicalShape root = RenderPhysicalShape(
@@ -151,27 +119,24 @@
debugDefaultTargetPlatformOverride = null;
});
- test('compositing on non-Fuchsia', () {
+ test('compositing', () {
for (final TargetPlatform platform in TargetPlatform.values) {
- if (platform == TargetPlatform.fuchsia) {
- continue;
- }
debugDefaultTargetPlatformOverride = platform;
final RenderPhysicalShape root = RenderPhysicalShape(
color: const Color(0xffff00ff),
clipper: const ShapeBorderClipper(shape: CircleBorder()),
);
layout(root, phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
+ expect(root.needsCompositing, isFalse);
// On non-Fuchsia platforms, we composite physical shape layers
root.elevation = 1.0;
pumpFrame(phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
+ expect(root.needsCompositing, isFalse);
root.elevation = 0.0;
pumpFrame(phase: EnginePhase.composite);
- expect(root.needsCompositing, isTrue);
+ expect(root.needsCompositing, isFalse);
}
debugDefaultTargetPlatformOverride = null;
});
@@ -287,7 +252,9 @@
test('RenderOpacity reuses its layer', () {
_testLayerReuse<OpacityLayer>(RenderOpacity(
opacity: 0.5, // must not be 0 or 1.0. Otherwise, it won't create a layer
- child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter
+ child: RenderRepaintBoundary(
+ child: RenderSizedBox(const Size(1.0, 1.0)),
+ ), // size doesn't matter
));
});
@@ -353,9 +320,7 @@
test('RenderClipRect reuses its layer', () {
_testLayerReuse<ClipRectLayer>(RenderClipRect(
clipper: _TestRectClipper(),
- // Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter
));
@@ -364,9 +329,7 @@
test('RenderClipRRect reuses its layer', () {
_testLayerReuse<ClipRRectLayer>(RenderClipRRect(
clipper: _TestRRectClipper(),
- // Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter
));
@@ -375,9 +338,7 @@
test('RenderClipOval reuses its layer', () {
_testLayerReuse<ClipPathLayer>(RenderClipOval(
clipper: _TestRectClipper(),
- // Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter
));
@@ -386,32 +347,28 @@
test('RenderClipPath reuses its layer', () {
_testLayerReuse<ClipPathLayer>(RenderClipPath(
clipper: _TestPathClipper(),
- // Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter
));
});
test('RenderPhysicalModel reuses its layer', () {
- _testLayerReuse<PhysicalModelLayer>(RenderPhysicalModel(
+ _testLayerReuse<ClipRRectLayer>(RenderPhysicalModel(
+ clipBehavior: Clip.hardEdge,
color: const Color.fromRGBO(0, 0, 0, 1.0),
- // Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter
));
});
test('RenderPhysicalShape reuses its layer', () {
- _testLayerReuse<PhysicalModelLayer>(RenderPhysicalShape(
+ _testLayerReuse<ClipPathLayer>(RenderPhysicalShape(
clipper: _TestPathClipper(),
+ clipBehavior: Clip.hardEdge,
color: const Color.fromRGBO(0, 0, 0, 1.0),
- // Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter
));
@@ -421,9 +378,7 @@
_testLayerReuse<TransformLayer>(RenderTransform(
// Use a 3D transform to force compositing.
transform: Matrix4.rotationX(0.1),
- // Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter
));
@@ -434,8 +389,7 @@
fit: BoxFit.cover,
clipBehavior: Clip.hardEdge,
// Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(100.0, 200.0)),
), // size doesn't matter
));
@@ -445,8 +399,7 @@
_testLayerReuse<TransformLayer>(RenderFittedBox(
fit: BoxFit.fill,
// Inject opacity under the clip to force compositing.
- child: RenderOpacity(
- opacity: 0.5,
+ child: RenderRepaintBoundary(
child: RenderSizedBox(const Size(1, 1)),
), // size doesn't matter
));
@@ -768,7 +721,7 @@
expect(L, isNot(Layer));
expect(renderObject.debugLayer, null);
layout(renderObject, phase: EnginePhase.paint, constraints: BoxConstraints.tight(const Size(10, 10)));
- final Layer layer = renderObject.debugLayer!;
+ final Layer? layer = renderObject.debugLayer;
expect(layer, isA<L>());
expect(layer, isNotNull);
diff --git a/packages/flutter/test/widgets/mouse_region_test.dart b/packages/flutter/test/widgets/mouse_region_test.dart
index 7da9407..929fe1b 100644
--- a/packages/flutter/test/widgets/mouse_region_test.dart
+++ b/packages/flutter/test/widgets/mouse_region_test.dart
@@ -793,7 +793,7 @@
await tester.pumpWidget(
MouseRegion(
onEnter: (PointerEnterEvent _) {},
- child: const Opacity(opacity: 0.5, child: Placeholder()),
+ child: const RepaintBoundary(child: Placeholder()),
),
);
diff --git a/packages/flutter/test/widgets/nested_scroll_view_test.dart b/packages/flutter/test/widgets/nested_scroll_view_test.dart
index 62a257e..b29488d 100644
--- a/packages/flutter/test/widgets/nested_scroll_view_test.dart
+++ b/packages/flutter/test/widgets/nested_scroll_view_test.dart
@@ -591,35 +591,28 @@
)),
);
- PhysicalModelLayer? _dfsFindPhysicalLayer(ContainerLayer layer) {
- expect(layer, isNotNull);
- Layer? child = layer.firstChild;
- while (child != null) {
- if (child is PhysicalModelLayer) {
- return child;
+ Object? _dfsFindPhysicalLayer(RenderObject object) {
+ expect(object, isNotNull);
+ if (object is RenderPhysicalModel || object is RenderPhysicalShape) {
+ return object;
+ }
+ final List<RenderObject> children = <RenderObject>[];
+ object.visitChildren(children.add);
+ for (final RenderObject child in children) {
+ final Object? result = _dfsFindPhysicalLayer(child);
+ if (result != null) {
+ return result;
}
- if (child is ContainerLayer) {
- Layer? innerChild = child.firstChild;
- while (innerChild != null) {
- if (innerChild is ContainerLayer) {
- final PhysicalModelLayer? candidate = _dfsFindPhysicalLayer(innerChild);
- if (candidate != null) {
- return candidate;
- }
- }
- innerChild = innerChild.nextSibling;
- }
- }
- child = child.nextSibling;
}
return null;
}
- final ContainerLayer nestedScrollViewLayer = find.byType(NestedScrollView).evaluate().first.renderObject!.debugLayer!;
+ final RenderObject nestedScrollViewLayer = find.byType(NestedScrollView).evaluate().first.renderObject!;
void _checkPhysicalLayer({required double elevation}) {
- final PhysicalModelLayer? layer = _dfsFindPhysicalLayer(nestedScrollViewLayer);
- expect(layer, isNotNull);
- expect(layer!.elevation, equals(elevation));
+ final dynamic physicalModel = _dfsFindPhysicalLayer(nestedScrollViewLayer);
+ expect(physicalModel, isNotNull);
+ // ignore: avoid_dynamic_calls
+ expect(physicalModel.elevation, equals(elevation));
}
int expectedBuildCount = 0;
diff --git a/packages/flutter/test/widgets/physical_model_test.dart b/packages/flutter/test/widgets/physical_model_test.dart
index ccd8698..4591603 100644
--- a/packages/flutter/test/widgets/physical_model_test.dart
+++ b/packages/flutter/test/widgets/physical_model_test.dart
@@ -43,30 +43,6 @@
expect(renderPhysicalShape.clipBehavior, equals(Clip.antiAlias));
});
- testWidgets('PhysicalModel - creates a physical model layer when it needs compositing', (WidgetTester tester) async {
- debugDisableShadows = false;
- await tester.pumpWidget(
- MaterialApp(
- home: PhysicalModel(
- color: Colors.grey,
- shadowColor: Colors.red,
- elevation: 1.0,
- child: Material(child: TextField(controller: TextEditingController())),
- ),
- ),
- );
- await tester.pump();
-
- final RenderPhysicalModel renderPhysicalModel = tester.allRenderObjects.whereType<RenderPhysicalModel>().first;
- expect(renderPhysicalModel.needsCompositing, true);
-
- final PhysicalModelLayer physicalModelLayer = tester.layers.whereType<PhysicalModelLayer>().first;
- expect(physicalModelLayer.shadowColor, Colors.red);
- expect(physicalModelLayer.color, Colors.grey);
- expect(physicalModelLayer.elevation, 1.0);
- debugDisableShadows = true;
- });
-
testWidgets('PhysicalModel - clips when overflows and elevation is 0', (WidgetTester tester) async {
const Key key = Key('test');
await tester.pumpWidget(
diff --git a/packages/flutter/test/widgets/transform_test.dart b/packages/flutter/test/widgets/transform_test.dart
index 621a4ee..a21056e 100644
--- a/packages/flutter/test/widgets/transform_test.dart
+++ b/packages/flutter/test/widgets/transform_test.dart
@@ -240,8 +240,7 @@
child: ClipRect(
child: Transform(
transform: Matrix4.diagonal3Values(0.5, 0.5, 1.0),
- child: Opacity(
- opacity: 0.9,
+ child: RepaintBoundary(
child: Container(
color: const Color(0xFF00FF00),
),
@@ -265,7 +264,7 @@
await tester.pumpWidget(
Transform.rotate(
angle: math.pi / 2.0,
- child: Opacity(opacity: 0.5, child: Container()),
+ child: RepaintBoundary(child: Container()),
),
);
@@ -305,7 +304,7 @@
await tester.pumpWidget(
Transform.translate(
offset: const Offset(100.0, 50.0),
- child: Opacity(opacity: 0.5, child: Container()),
+ child: RepaintBoundary(child: Container()),
),
);
@@ -320,7 +319,7 @@
await tester.pumpWidget(
Transform.scale(
scale: 2.0,
- child: Opacity(opacity: 0.5, child: Container()),
+ child: RepaintBoundary(child: Container()),
),
);