Unverified Commit fba9214d authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[framework] remove usage and deprecate physical model layer (#102274)

parent e493d5ce
...@@ -1083,20 +1083,14 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -1083,20 +1083,14 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
if (size.isEmpty) if (size.isEmpty)
return; return;
if (clipBehavior == Clip.none) { _clipRectLayer.layer = context.pushClipRect(
_clipRectLayer.layer = null; needsCompositing,
defaultPaint(context, offset); offset,
} else { Offset.zero & size,
// We have overflow and the clipBehavior isn't none. Clip it. defaultPaint,
_clipRectLayer.layer = context.pushClipRect( clipBehavior: clipBehavior,
needsCompositing, oldLayer: _clipRectLayer.layer,
offset, );
Offset.zero & size,
defaultPaint,
clipBehavior: clipBehavior,
oldLayer: _clipRectLayer.layer,
);
}
assert(() { assert(() {
// Only set this if it's null to save work. It gets reset to null if the // Only set this if it's null to save work. It gets reset to null if the
......
...@@ -388,19 +388,14 @@ class RenderFlow extends RenderBox ...@@ -388,19 +388,14 @@ class RenderFlow extends RenderBox
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (clipBehavior == Clip.none) { _clipRectLayer.layer = context.pushClipRect(
_clipRectLayer.layer = null; needsCompositing,
_paintWithDelegate(context, offset); offset,
} else { Offset.zero & size,
_clipRectLayer.layer = context.pushClipRect( _paintWithDelegate,
needsCompositing, clipBehavior: clipBehavior,
offset, oldLayer: _clipRectLayer.layer,
Offset.zero & size, );
_paintWithDelegate,
clipBehavior: clipBehavior,
oldLayer: _clipRectLayer.layer,
);
}
} }
final LayerHandle<ClipRectLayer> _clipRectLayer = LayerHandle<ClipRectLayer>(); final LayerHandle<ClipRectLayer> _clipRectLayer = LayerHandle<ClipRectLayer>();
......
...@@ -1972,12 +1972,20 @@ class BackdropFilterLayer extends ContainerLayer { ...@@ -1972,12 +1972,20 @@ class BackdropFilterLayer extends ContainerLayer {
/// When debugging, setting [debugDisablePhysicalShapeLayers] to true will cause this /// When debugging, setting [debugDisablePhysicalShapeLayers] to true will cause this
/// layer to be skipped (directly replaced by its children). This can be helpful /// layer to be skipped (directly replaced by its children). This can be helpful
/// to track down the cause of performance problems. /// 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 { class PhysicalModelLayer extends ContainerLayer {
/// Creates a composited layer that uses a physical model to producing /// Creates a composited layer that uses a physical model to producing
/// lighting effects. /// lighting effects.
/// ///
/// The [clipPath], [clipBehavior], [elevation], [color], and [shadowColor] /// The [clipPath], [clipBehavior], [elevation], [color], and [shadowColor]
/// arguments must be non-null before the compositing phase of the pipeline. /// 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({ PhysicalModelLayer({
Path? clipPath, Path? clipPath,
Clip clipBehavior = Clip.none, Clip clipBehavior = Clip.none,
......
...@@ -491,6 +491,10 @@ class PaintingContext extends ClipContext { ...@@ -491,6 +491,10 @@ class PaintingContext extends ClipContext {
/// (e.g. from opacity layer to a clip rect layer). /// (e.g. from opacity layer to a clip rect layer).
/// {@endtemplate} /// {@endtemplate}
ClipRectLayer? pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter, { Clip clipBehavior = Clip.hardEdge, ClipRectLayer? oldLayer }) { 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); final Rect offsetClipRect = clipRect.shift(offset);
if (needsCompositing) { if (needsCompositing) {
final ClipRectLayer layer = oldLayer ?? ClipRectLayer(); final ClipRectLayer layer = oldLayer ?? ClipRectLayer();
...@@ -526,6 +530,10 @@ class PaintingContext extends ClipContext { ...@@ -526,6 +530,10 @@ class PaintingContext extends ClipContext {
/// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer} /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
ClipRRectLayer? pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, RRect clipRRect, PaintingContextCallback painter, { Clip clipBehavior = Clip.antiAlias, ClipRRectLayer? oldLayer }) { ClipRRectLayer? pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, RRect clipRRect, PaintingContextCallback painter, { Clip clipBehavior = Clip.antiAlias, ClipRRectLayer? oldLayer }) {
assert(clipBehavior != null); assert(clipBehavior != null);
if (clipBehavior == Clip.none) {
painter(this, offset);
return null;
}
final Rect offsetBounds = bounds.shift(offset); final Rect offsetBounds = bounds.shift(offset);
final RRect offsetClipRRect = clipRRect.shift(offset); final RRect offsetClipRRect = clipRRect.shift(offset);
if (needsCompositing) { if (needsCompositing) {
...@@ -562,6 +570,10 @@ class PaintingContext extends ClipContext { ...@@ -562,6 +570,10 @@ class PaintingContext extends ClipContext {
/// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer} /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
ClipPathLayer? pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter, { Clip clipBehavior = Clip.antiAlias, ClipPathLayer? oldLayer }) { ClipPathLayer? pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter, { Clip clipBehavior = Clip.antiAlias, ClipPathLayer? oldLayer }) {
assert(clipBehavior != null); assert(clipBehavior != null);
if (clipBehavior == Clip.none) {
painter(this, offset);
return null;
}
final Rect offsetBounds = bounds.shift(offset); final Rect offsetBounds = bounds.shift(offset);
final Path offsetClipPath = clipPath.shift(offset); final Path offsetClipPath = clipPath.shift(offset);
if (needsCompositing) { if (needsCompositing) {
......
...@@ -1827,9 +1827,6 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> { ...@@ -1827,9 +1827,6 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> {
markNeedsPaint(); markNeedsPaint();
} }
@override
bool get alwaysNeedsCompositing => true;
@override @override
void describeSemanticsConfiguration(SemanticsConfiguration config) { void describeSemanticsConfiguration(SemanticsConfiguration config) {
super.describeSemanticsConfiguration(config); super.describeSemanticsConfiguration(config);
...@@ -1845,6 +1842,8 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> { ...@@ -1845,6 +1842,8 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> {
} }
} }
final Paint _transparentPaint = Paint()..color = const Color(0x00000000);
/// Creates a physical model layer that clips its child to a rounded /// Creates a physical model layer that clips its child to a rounded
/// rectangle. /// rectangle.
/// ///
...@@ -1873,9 +1872,6 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> { ...@@ -1873,9 +1872,6 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> {
_shape = shape, _shape = shape,
_borderRadius = borderRadius; _borderRadius = borderRadius;
@override
PhysicalModelLayer? get layer => super.layer as PhysicalModelLayer?;
/// The shape of the layer. /// The shape of the layer.
/// ///
/// Defaults to [BoxShape.rectangle]. The [borderRadius] affects the corners /// Defaults to [BoxShape.rectangle]. The [borderRadius] affects the corners
...@@ -1933,42 +1929,79 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> { ...@@ -1933,42 +1929,79 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> {
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (child != null) { 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 {
layer = 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 @override
...@@ -2006,9 +2039,6 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> { ...@@ -2006,9 +2039,6 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> {
assert(color != null), assert(color != null),
assert(shadowColor != null); assert(shadowColor != null);
@override
PhysicalModelLayer? get layer => super.layer as PhysicalModelLayer?;
@override @override
Path get _defaultClip => Path()..addRect(Offset.zero & size); Path get _defaultClip => Path()..addRect(Offset.zero & size);
...@@ -2025,41 +2055,78 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> { ...@@ -2025,41 +2055,78 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> {
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (child != null) { 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 {
layer = 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 @override
......
...@@ -799,20 +799,15 @@ class RenderConstraintsTransformBox extends RenderAligningShiftedBox with DebugO ...@@ -799,20 +799,15 @@ class RenderConstraintsTransformBox extends RenderAligningShiftedBox with DebugO
return; return;
} }
if (clipBehavior == Clip.none) { // We have overflow and the clipBehavior isn't none. Clip it.
_clipRectLayer.layer = null; _clipRectLayer.layer = context.pushClipRect(
super.paint(context, offset); needsCompositing,
} else { offset,
// We have overflow and the clipBehavior isn't none. Clip it. Offset.zero & size,
_clipRectLayer.layer = context.pushClipRect( super.paint,
needsCompositing, clipBehavior: clipBehavior,
offset, oldLayer: _clipRectLayer.layer,
Offset.zero & size, );
super.paint,
clipBehavior: clipBehavior,
oldLayer: _clipRectLayer.layer,
);
}
// Display the overflow indicator. // Display the overflow indicator.
assert(() { assert(() {
......
...@@ -64,6 +64,8 @@ void expectCheckmarkColor(Finder finder, Color color) { ...@@ -64,6 +64,8 @@ void expectCheckmarkColor(Finder finder, Color color) {
expect( expect(
finder, finder,
paints paints
// Physical model path
..path()
// The first path that is painted is the selection overlay. We do not care // 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 // how it is painted but it has to be added it to this pattern so that the
// check mark can be checked next. // check mark can be checked next.
......
...@@ -64,6 +64,8 @@ void expectCheckmarkColor(Finder finder, Color color) { ...@@ -64,6 +64,8 @@ void expectCheckmarkColor(Finder finder, Color color) {
expect( expect(
finder, finder,
paints paints
// Physical model layer path
..path()
// The first path that is painted is the selection overlay. We do not care // 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 // how it is painted but it has to be added it to this pattern so that the
// check mark can be checked next. // check mark can be checked next.
......
...@@ -852,10 +852,6 @@ void main() { ...@@ -852,10 +852,6 @@ void main() {
), ),
); );
} }
// 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); final Finder outlinedButton = find.byType(OutlinedButton);
BorderSide getBorderSide() { BorderSide getBorderSide() {
...@@ -873,12 +869,6 @@ void main() { ...@@ -873,12 +869,6 @@ void main() {
// Expect that the button is disabled and painted with the disabled border color. // Expect that the button is disabled and painted with the disabled border color.
expect(tester.widget<OutlinedButton>(outlinedButton).enabled, false); expect(tester.widget<OutlinedButton>(outlinedButton).enabled, false);
expect(getBorderSide(), disabledBorderSide); 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. // Pump a new button with a no-op onPressed callback to make it enabled.
await tester.pumpWidget( await tester.pumpWidget(
...@@ -896,23 +886,11 @@ void main() { ...@@ -896,23 +886,11 @@ void main() {
// Wait for the border's color to change to pressed // Wait for the border's color to change to pressed
await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200));
expect(getBorderSide(), pressedBorderSide); expect(getBorderSide(), pressedBorderSide);
_checkPhysicalLayer(
tester.element(outlinedButton),
fillColor,
clipPath: clipPath,
clipRect: clipRect,
);
// Tap gesture completes, button returns to its initial configuration. // Tap gesture completes, button returns to its initial configuration.
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(getBorderSide(), enabledBorderSide); expect(getBorderSide(), enabledBorderSide);
_checkPhysicalLayer(
tester.element(outlinedButton),
fillColor,
clipPath: clipPath,
clipRect: clipRect,
);
}); });
testWidgets('OutlinedButton has no clip by default', (WidgetTester tester) async { testWidgets('OutlinedButton has no clip by default', (WidgetTester tester) async {
...@@ -1748,29 +1726,6 @@ void main() { ...@@ -1748,29 +1726,6 @@ void main() {
}); });
} }
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) { TextStyle _iconStyle(WidgetTester tester, IconData icon) {
final RichText iconRichText = tester.widget<RichText>( final RichText iconRichText = tester.widget<RichText>(
find.descendant(of: find.byIcon(icon), matching: find.byType(RichText)), find.descendant(of: find.byIcon(icon), matching: find.byType(RichText)),
......
...@@ -1360,7 +1360,7 @@ void main() { ...@@ -1360,7 +1360,7 @@ void main() {
); );
// Represents the Raised Button and Range Slider. // Represents the Raised Button and Range Slider.
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 3)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 4));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 3)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 3));
await tester.tap(find.text('Next')); await tester.tap(find.text('Next'));
...@@ -1379,7 +1379,7 @@ void main() { ...@@ -1379,7 +1379,7 @@ void main() {
); );
// Represents the raised button with inner page text. // Represents the raised button with inner page text.
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 1)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1));
// Don't stop holding the value indicator. // Don't stop holding the value indicator.
......
...@@ -784,6 +784,7 @@ void main() { ...@@ -784,6 +784,7 @@ void main() {
expect( expect(
valueIndicatorBox, valueIndicatorBox,
paints paints
..rrect(color: const Color(0xfffafafa))
..rrect(color: customColor1) // active track ..rrect(color: customColor1) // active track
..rrect(color: customColor2) // inactive track ..rrect(color: customColor2) // inactive track
..circle(color: customColor1.withOpacity(0.12)) // overlay ..circle(color: customColor1.withOpacity(0.12)) // overlay
...@@ -2415,7 +2416,7 @@ void main() { ...@@ -2415,7 +2416,7 @@ void main() {
..paragraph(), ..paragraph(),
); );
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 3));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 2)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 2));
await tester.tap(find.text('Next')); await tester.tap(find.text('Next'));
...@@ -2432,7 +2433,7 @@ void main() { ...@@ -2432,7 +2433,7 @@ void main() {
); );
// Represents the ElevatedButton with inner Text, inner page. // Represents the ElevatedButton with inner Text, inner page.
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 1)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1)); expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1));
// Don't stop holding the value indicator. // Don't stop holding the value indicator.
......
...@@ -1134,6 +1134,8 @@ void main() { ...@@ -1134,6 +1134,8 @@ void main() {
expect( expect(
valueIndicatorBox, valueIndicatorBox,
paints paints
// physical model
..rrect()
..rrect(rrect: RRect.fromLTRBAndCorners( ..rrect(rrect: RRect.fromLTRBAndCorners(
24.0, 298.0, 24.0, 302.0, 24.0, 298.0, 24.0, 302.0,
topLeft: const Radius.circular(2.0), topLeft: const Radius.circular(2.0),
......
...@@ -1015,6 +1015,8 @@ void main() { ...@@ -1015,6 +1015,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12), color: theme.colorScheme.onSurface.withOpacity(0.12),
...@@ -1042,6 +1044,8 @@ void main() { ...@@ -1042,6 +1044,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12), color: theme.colorScheme.onSurface.withOpacity(0.12),
...@@ -1068,6 +1072,8 @@ void main() { ...@@ -1068,6 +1072,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12), color: theme.colorScheme.onSurface.withOpacity(0.12),
...@@ -1108,6 +1114,8 @@ void main() { ...@@ -1108,6 +1114,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: borderColor, color: borderColor,
...@@ -1137,6 +1145,8 @@ void main() { ...@@ -1137,6 +1145,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: selectedBorderColor, color: selectedBorderColor,
...@@ -1165,6 +1175,8 @@ void main() { ...@@ -1165,6 +1175,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: disabledBorderColor, color: disabledBorderColor,
...@@ -1432,6 +1444,8 @@ void main() { ...@@ -1432,6 +1444,8 @@ void main() {
expect( expect(
toggleButtonRenderObject[0], toggleButtonRenderObject[0],
paints paints
// physical model
..path()
// leading side, top and bottom - enabled // leading side, top and bottom - enabled
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
...@@ -1445,6 +1459,8 @@ void main() { ...@@ -1445,6 +1459,8 @@ void main() {
expect( expect(
toggleButtonRenderObject[1], toggleButtonRenderObject[1],
paints paints
// physical model
..path()
// leading side - selected // leading side - selected
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
...@@ -1464,6 +1480,8 @@ void main() { ...@@ -1464,6 +1480,8 @@ void main() {
expect( expect(
toggleButtonRenderObject[2], toggleButtonRenderObject[2],
paints paints
// physical model
..path()
// leading side - selected, since previous button is selected // leading side - selected, since previous button is selected
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
...@@ -1515,6 +1533,8 @@ void main() { ...@@ -1515,6 +1533,8 @@ void main() {
expect( expect(
toggleButtonRenderObject[0], toggleButtonRenderObject[0],
paints paints
// physical model
..path()
// left side, top and right - enabled. // left side, top and right - enabled.
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
...@@ -1528,6 +1548,8 @@ void main() { ...@@ -1528,6 +1548,8 @@ void main() {
expect( expect(
toggleButtonRenderObject[1], toggleButtonRenderObject[1],
paints paints
// physical model
..path()
// top side - selected. // top side - selected.
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
...@@ -1547,6 +1569,8 @@ void main() { ...@@ -1547,6 +1569,8 @@ void main() {
expect( expect(
toggleButtonRenderObject[2], toggleButtonRenderObject[2],
paints paints
// physical model
..path()
// top side - selected, since previous button is selected. // top side - selected, since previous button is selected.
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
...@@ -1712,6 +1736,8 @@ void main() { ...@@ -1712,6 +1736,8 @@ void main() {
expect( expect(
toggleButtonRenderObject[0], toggleButtonRenderObject[0],
paints paints
// physical model paints
..path()
// left side, top and right - enabled. // left side, top and right - enabled.
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
......
...@@ -543,6 +543,8 @@ void main() { ...@@ -543,6 +543,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model layer paint
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: borderColor, color: borderColor,
...@@ -576,6 +578,8 @@ void main() { ...@@ -576,6 +578,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model layer paint
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: selectedBorderColor, color: selectedBorderColor,
...@@ -608,6 +612,8 @@ void main() { ...@@ -608,6 +612,8 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// physical model layer paint
..path()
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: disabledBorderColor, color: disabledBorderColor,
......
...@@ -222,7 +222,7 @@ void main() { ...@@ -222,7 +222,7 @@ void main() {
); );
final RenderOpacity root = RenderOpacity( final RenderOpacity root = RenderOpacity(
opacity: .5, opacity: .5,
child: blackBox, child: RenderRepaintBoundary(child: blackBox),
); );
layout(root, phase: EnginePhase.compositingBits); layout(root, phase: EnginePhase.compositingBits);
......
...@@ -5,9 +5,8 @@ ...@@ -5,9 +5,8 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui' as ui show Gradient, Image, ImageFilter; import 'dart:ui' as ui show Gradient, Image, ImageFilter;
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -15,7 +14,6 @@ import 'rendering_tester.dart'; ...@@ -15,7 +14,6 @@ import 'rendering_tester.dart';
void main() { void main() {
TestRenderingFlutterBinding.ensureInitialized(); TestRenderingFlutterBinding.ensureInitialized();
test('RenderFittedBox handles applying paint transform and hit-testing with empty size', () { test('RenderFittedBox handles applying paint transform and hit-testing with empty size', () {
final RenderFittedBox fittedBox = RenderFittedBox( final RenderFittedBox fittedBox = RenderFittedBox(
child: RenderCustomPaint( child: RenderCustomPaint(
...@@ -61,47 +59,20 @@ void main() { ...@@ -61,47 +59,20 @@ void main() {
expect(painted, equals(false)); expect(painted, equals(false));
}); });
test('RenderPhysicalModel compositing on Fuchsia', () { test('RenderPhysicalModel compositing', () {
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
final RenderPhysicalModel root = RenderPhysicalModel(color: const Color(0xffff00ff)); final RenderPhysicalModel root = RenderPhysicalModel(color: const Color(0xffff00ff));
layout(root, phase: EnginePhase.composite); layout(root, phase: EnginePhase.composite);
expect(root.needsCompositing, isTrue); expect(root.needsCompositing, isFalse);
// On Fuchsia, the system compositor is responsible for drawing shadows // On Fuchsia, the system compositor is responsible for drawing shadows
// for physical model layers with non-zero elevation. // for physical model layers with non-zero elevation.
root.elevation = 1.0; root.elevation = 1.0;
pumpFrame(phase: EnginePhase.composite); pumpFrame(phase: EnginePhase.composite);
expect(root.needsCompositing, isTrue); expect(root.needsCompositing, isFalse);
root.elevation = 0.0; root.elevation = 0.0;
pumpFrame(phase: EnginePhase.composite); pumpFrame(phase: EnginePhase.composite);
expect(root.needsCompositing, isTrue); expect(root.needsCompositing, isFalse);
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;
}); });
test('RenderSemanticsGestureHandler adds/removes correct semantic actions', () { test('RenderSemanticsGestureHandler adds/removes correct semantic actions', () {
...@@ -128,9 +99,6 @@ void main() { ...@@ -128,9 +99,6 @@ void main() {
group('RenderPhysicalShape', () { group('RenderPhysicalShape', () {
test('shape change triggers repaint', () { test('shape change triggers repaint', () {
for (final TargetPlatform platform in TargetPlatform.values) { for (final TargetPlatform platform in TargetPlatform.values) {
if (platform == TargetPlatform.fuchsia) {
continue;
}
debugDefaultTargetPlatformOverride = platform; debugDefaultTargetPlatformOverride = platform;
final RenderPhysicalShape root = RenderPhysicalShape( final RenderPhysicalShape root = RenderPhysicalShape(
...@@ -151,27 +119,24 @@ void main() { ...@@ -151,27 +119,24 @@ void main() {
debugDefaultTargetPlatformOverride = null; debugDefaultTargetPlatformOverride = null;
}); });
test('compositing on non-Fuchsia', () { test('compositing', () {
for (final TargetPlatform platform in TargetPlatform.values) { for (final TargetPlatform platform in TargetPlatform.values) {
if (platform == TargetPlatform.fuchsia) {
continue;
}
debugDefaultTargetPlatformOverride = platform; debugDefaultTargetPlatformOverride = platform;
final RenderPhysicalShape root = RenderPhysicalShape( final RenderPhysicalShape root = RenderPhysicalShape(
color: const Color(0xffff00ff), color: const Color(0xffff00ff),
clipper: const ShapeBorderClipper(shape: CircleBorder()), clipper: const ShapeBorderClipper(shape: CircleBorder()),
); );
layout(root, phase: EnginePhase.composite); layout(root, phase: EnginePhase.composite);
expect(root.needsCompositing, isTrue); expect(root.needsCompositing, isFalse);
// On non-Fuchsia platforms, we composite physical shape layers // On non-Fuchsia platforms, we composite physical shape layers
root.elevation = 1.0; root.elevation = 1.0;
pumpFrame(phase: EnginePhase.composite); pumpFrame(phase: EnginePhase.composite);
expect(root.needsCompositing, isTrue); expect(root.needsCompositing, isFalse);
root.elevation = 0.0; root.elevation = 0.0;
pumpFrame(phase: EnginePhase.composite); pumpFrame(phase: EnginePhase.composite);
expect(root.needsCompositing, isTrue); expect(root.needsCompositing, isFalse);
} }
debugDefaultTargetPlatformOverride = null; debugDefaultTargetPlatformOverride = null;
}); });
...@@ -287,7 +252,9 @@ void main() { ...@@ -287,7 +252,9 @@ void main() {
test('RenderOpacity reuses its layer', () { test('RenderOpacity reuses its layer', () {
_testLayerReuse<OpacityLayer>(RenderOpacity( _testLayerReuse<OpacityLayer>(RenderOpacity(
opacity: 0.5, // must not be 0 or 1.0. Otherwise, it won't create a layer 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 @@ void main() { ...@@ -353,9 +320,7 @@ void main() {
test('RenderClipRect reuses its layer', () { test('RenderClipRect reuses its layer', () {
_testLayerReuse<ClipRectLayer>(RenderClipRect( _testLayerReuse<ClipRectLayer>(RenderClipRect(
clipper: _TestRectClipper(), clipper: _TestRectClipper(),
// Inject opacity under the clip to force compositing. child: RenderRepaintBoundary(
child: RenderOpacity(
opacity: 0.5,
child: RenderSizedBox(const Size(1.0, 1.0)), child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
...@@ -364,9 +329,7 @@ void main() { ...@@ -364,9 +329,7 @@ void main() {
test('RenderClipRRect reuses its layer', () { test('RenderClipRRect reuses its layer', () {
_testLayerReuse<ClipRRectLayer>(RenderClipRRect( _testLayerReuse<ClipRRectLayer>(RenderClipRRect(
clipper: _TestRRectClipper(), clipper: _TestRRectClipper(),
// Inject opacity under the clip to force compositing. child: RenderRepaintBoundary(
child: RenderOpacity(
opacity: 0.5,
child: RenderSizedBox(const Size(1.0, 1.0)), child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
...@@ -375,9 +338,7 @@ void main() { ...@@ -375,9 +338,7 @@ void main() {
test('RenderClipOval reuses its layer', () { test('RenderClipOval reuses its layer', () {
_testLayerReuse<ClipPathLayer>(RenderClipOval( _testLayerReuse<ClipPathLayer>(RenderClipOval(
clipper: _TestRectClipper(), clipper: _TestRectClipper(),
// Inject opacity under the clip to force compositing. child: RenderRepaintBoundary(
child: RenderOpacity(
opacity: 0.5,
child: RenderSizedBox(const Size(1.0, 1.0)), child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
...@@ -386,32 +347,28 @@ void main() { ...@@ -386,32 +347,28 @@ void main() {
test('RenderClipPath reuses its layer', () { test('RenderClipPath reuses its layer', () {
_testLayerReuse<ClipPathLayer>(RenderClipPath( _testLayerReuse<ClipPathLayer>(RenderClipPath(
clipper: _TestPathClipper(), clipper: _TestPathClipper(),
// Inject opacity under the clip to force compositing. child: RenderRepaintBoundary(
child: RenderOpacity(
opacity: 0.5,
child: RenderSizedBox(const Size(1.0, 1.0)), child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
}); });
test('RenderPhysicalModel reuses its layer', () { test('RenderPhysicalModel reuses its layer', () {
_testLayerReuse<PhysicalModelLayer>(RenderPhysicalModel( _testLayerReuse<ClipRRectLayer>(RenderPhysicalModel(
clipBehavior: Clip.hardEdge,
color: const Color.fromRGBO(0, 0, 0, 1.0), color: const Color.fromRGBO(0, 0, 0, 1.0),
// Inject opacity under the clip to force compositing. child: RenderRepaintBoundary(
child: RenderOpacity(
opacity: 0.5,
child: RenderSizedBox(const Size(1.0, 1.0)), child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
}); });
test('RenderPhysicalShape reuses its layer', () { test('RenderPhysicalShape reuses its layer', () {
_testLayerReuse<PhysicalModelLayer>(RenderPhysicalShape( _testLayerReuse<ClipPathLayer>(RenderPhysicalShape(
clipper: _TestPathClipper(), clipper: _TestPathClipper(),
clipBehavior: Clip.hardEdge,
color: const Color.fromRGBO(0, 0, 0, 1.0), color: const Color.fromRGBO(0, 0, 0, 1.0),
// Inject opacity under the clip to force compositing. child: RenderRepaintBoundary(
child: RenderOpacity(
opacity: 0.5,
child: RenderSizedBox(const Size(1.0, 1.0)), child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
...@@ -421,9 +378,7 @@ void main() { ...@@ -421,9 +378,7 @@ void main() {
_testLayerReuse<TransformLayer>(RenderTransform( _testLayerReuse<TransformLayer>(RenderTransform(
// Use a 3D transform to force compositing. // Use a 3D transform to force compositing.
transform: Matrix4.rotationX(0.1), transform: Matrix4.rotationX(0.1),
// Inject opacity under the clip to force compositing. child: RenderRepaintBoundary(
child: RenderOpacity(
opacity: 0.5,
child: RenderSizedBox(const Size(1.0, 1.0)), child: RenderSizedBox(const Size(1.0, 1.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
...@@ -434,8 +389,7 @@ void main() { ...@@ -434,8 +389,7 @@ void main() {
fit: BoxFit.cover, fit: BoxFit.cover,
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
// Inject opacity under the clip to force compositing. // Inject opacity under the clip to force compositing.
child: RenderOpacity( child: RenderRepaintBoundary(
opacity: 0.5,
child: RenderSizedBox(const Size(100.0, 200.0)), child: RenderSizedBox(const Size(100.0, 200.0)),
), // size doesn't matter ), // size doesn't matter
)); ));
...@@ -445,8 +399,7 @@ void main() { ...@@ -445,8 +399,7 @@ void main() {
_testLayerReuse<TransformLayer>(RenderFittedBox( _testLayerReuse<TransformLayer>(RenderFittedBox(
fit: BoxFit.fill, fit: BoxFit.fill,
// Inject opacity under the clip to force compositing. // Inject opacity under the clip to force compositing.
child: RenderOpacity( child: RenderRepaintBoundary(
opacity: 0.5,
child: RenderSizedBox(const Size(1, 1)), child: RenderSizedBox(const Size(1, 1)),
), // size doesn't matter ), // size doesn't matter
)); ));
...@@ -768,7 +721,7 @@ void _testLayerReuse<L extends Layer>(RenderBox renderObject) { ...@@ -768,7 +721,7 @@ void _testLayerReuse<L extends Layer>(RenderBox renderObject) {
expect(L, isNot(Layer)); expect(L, isNot(Layer));
expect(renderObject.debugLayer, null); expect(renderObject.debugLayer, null);
layout(renderObject, phase: EnginePhase.paint, constraints: BoxConstraints.tight(const Size(10, 10))); 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, isA<L>());
expect(layer, isNotNull); expect(layer, isNotNull);
......
...@@ -793,7 +793,7 @@ void main() { ...@@ -793,7 +793,7 @@ void main() {
await tester.pumpWidget( await tester.pumpWidget(
MouseRegion( MouseRegion(
onEnter: (PointerEnterEvent _) {}, onEnter: (PointerEnterEvent _) {},
child: const Opacity(opacity: 0.5, child: Placeholder()), child: const RepaintBoundary(child: Placeholder()),
), ),
); );
......
...@@ -591,35 +591,28 @@ void main() { ...@@ -591,35 +591,28 @@ void main() {
)), )),
); );
PhysicalModelLayer? _dfsFindPhysicalLayer(ContainerLayer layer) { Object? _dfsFindPhysicalLayer(RenderObject object) {
expect(layer, isNotNull); expect(object, isNotNull);
Layer? child = layer.firstChild; if (object is RenderPhysicalModel || object is RenderPhysicalShape) {
while (child != null) { return object;
if (child is PhysicalModelLayer) { }
return child; final List<RenderObject> children = <RenderObject>[];
} object.visitChildren(children.add);
if (child is ContainerLayer) { for (final RenderObject child in children) {
Layer? innerChild = child.firstChild; final Object? result = _dfsFindPhysicalLayer(child);
while (innerChild != null) { if (result != null) {
if (innerChild is ContainerLayer) { return result;
final PhysicalModelLayer? candidate = _dfsFindPhysicalLayer(innerChild);
if (candidate != null) {
return candidate;
}
}
innerChild = innerChild.nextSibling;
}
} }
child = child.nextSibling;
} }
return null; 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}) { void _checkPhysicalLayer({required double elevation}) {
final PhysicalModelLayer? layer = _dfsFindPhysicalLayer(nestedScrollViewLayer); final dynamic physicalModel = _dfsFindPhysicalLayer(nestedScrollViewLayer);
expect(layer, isNotNull); expect(physicalModel, isNotNull);
expect(layer!.elevation, equals(elevation)); // ignore: avoid_dynamic_calls
expect(physicalModel.elevation, equals(elevation));
} }
int expectedBuildCount = 0; int expectedBuildCount = 0;
......
...@@ -43,30 +43,6 @@ void main() { ...@@ -43,30 +43,6 @@ void main() {
expect(renderPhysicalShape.clipBehavior, equals(Clip.antiAlias)); 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 { testWidgets('PhysicalModel - clips when overflows and elevation is 0', (WidgetTester tester) async {
const Key key = Key('test'); const Key key = Key('test');
await tester.pumpWidget( await tester.pumpWidget(
......
...@@ -240,8 +240,7 @@ void main() { ...@@ -240,8 +240,7 @@ void main() {
child: ClipRect( child: ClipRect(
child: Transform( child: Transform(
transform: Matrix4.diagonal3Values(0.5, 0.5, 1.0), transform: Matrix4.diagonal3Values(0.5, 0.5, 1.0),
child: Opacity( child: RepaintBoundary(
opacity: 0.9,
child: Container( child: Container(
color: const Color(0xFF00FF00), color: const Color(0xFF00FF00),
), ),
...@@ -265,7 +264,7 @@ void main() { ...@@ -265,7 +264,7 @@ void main() {
await tester.pumpWidget( await tester.pumpWidget(
Transform.rotate( Transform.rotate(
angle: math.pi / 2.0, angle: math.pi / 2.0,
child: Opacity(opacity: 0.5, child: Container()), child: RepaintBoundary(child: Container()),
), ),
); );
...@@ -305,7 +304,7 @@ void main() { ...@@ -305,7 +304,7 @@ void main() {
await tester.pumpWidget( await tester.pumpWidget(
Transform.translate( Transform.translate(
offset: const Offset(100.0, 50.0), offset: const Offset(100.0, 50.0),
child: Opacity(opacity: 0.5, child: Container()), child: RepaintBoundary(child: Container()),
), ),
); );
...@@ -320,7 +319,7 @@ void main() { ...@@ -320,7 +319,7 @@ void main() {
await tester.pumpWidget( await tester.pumpWidget(
Transform.scale( Transform.scale(
scale: 2.0, scale: 2.0,
child: Opacity(opacity: 0.5, child: Container()), child: RepaintBoundary(child: Container()),
), ),
); );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment