Skip to content

Commit

Permalink
[framework] make transform with filterQuality a rpb (#116792)
Browse files Browse the repository at this point in the history
* [framework] make transform with filterQuality a rpb

* fix tests

* ++
  • Loading branch information
jonahwilliams authored Dec 12, 2022
1 parent 15939b4 commit e331dcd
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 54 deletions.
104 changes: 51 additions & 53 deletions packages/flutter/lib/src/rendering/proxy_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2430,7 +2430,7 @@ class RenderTransform extends RenderProxyBox {
return;
}
_origin = value;
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

Expand All @@ -2452,7 +2452,7 @@ class RenderTransform extends RenderProxyBox {
return;
}
_alignment = value;
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

Expand All @@ -2467,10 +2467,13 @@ class RenderTransform extends RenderProxyBox {
return;
}
_textDirection = value;
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

@override
bool get isRepaintBoundary => alwaysNeedsCompositing;

@override
bool get alwaysNeedsCompositing => child != null && _filterQuality != null;

Expand All @@ -2495,7 +2498,7 @@ class RenderTransform extends RenderProxyBox {
return;
}
_transform = Matrix4.copy(value);
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

Expand All @@ -2513,48 +2516,48 @@ class RenderTransform extends RenderProxyBox {
if (didNeedCompositing != alwaysNeedsCompositing) {
markNeedsCompositingBitsUpdate();
}
markNeedsPaint();
markNeedsCompositedLayerUpdate();
}

/// Sets the transform to the identity matrix.
void setIdentity() {
_transform!.setIdentity();
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

/// Concatenates a rotation about the x axis into the transform.
void rotateX(double radians) {
_transform!.rotateX(radians);
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

/// Concatenates a rotation about the y axis into the transform.
void rotateY(double radians) {
_transform!.rotateY(radians);
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

/// Concatenates a rotation about the z axis into the transform.
void rotateZ(double radians) {
_transform!.rotateZ(radians);
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

/// Concatenates a translation by (x, y, z) into the transform.
void translate(double x, [ double y = 0.0, double z = 0.0 ]) {
_transform!.translate(x, y, z);
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

/// Concatenates a scale into the transform.
void scale(double x, [ double? y, double? z ]) {
_transform!.scale(x, y, z);
markNeedsPaint();
markNeedsCompositedLayerUpdate();
markNeedsSemanticsUpdate();
}

Expand Down Expand Up @@ -2603,51 +2606,46 @@ class RenderTransform extends RenderProxyBox {
);
}

@override
OffsetLayer updateCompositedLayer({required covariant ImageFilterLayer? oldLayer}) {
final ImageFilterLayer layer = oldLayer ?? ImageFilterLayer();
layer.imageFilter = ui.ImageFilter.matrix(
_effectiveTransform!.storage,
filterQuality: filterQuality!
);
return layer;
}

@override
void paint(PaintingContext context, Offset offset) {
if (child != null) {
final Matrix4 transform = _effectiveTransform!;
if (filterQuality == null) {
final Offset? childOffset = MatrixUtils.getAsTranslation(transform);
if (childOffset == null) {
// if the matrix is singular the children would be compressed to a line or
// single point, instead short-circuit and paint nothing.
final double det = transform.determinant();
if (det == 0 || !det.isFinite) {
layer = null;
return;
}
layer = context.pushTransform(
needsCompositing,
offset,
transform,
super.paint,
oldLayer: layer is TransformLayer ? layer as TransformLayer? : null,
);
} else {
super.paint(context, offset + childOffset);
layer = null;
}
} else {
final Matrix4 effectiveTransform = Matrix4.translationValues(offset.dx, offset.dy, 0.0)
..multiply(transform)..translate(-offset.dx, -offset.dy);
final ui.ImageFilter filter = ui.ImageFilter.matrix(
effectiveTransform.storage,
filterQuality: filterQuality!,
);
if (layer is ImageFilterLayer) {
final ImageFilterLayer filterLayer = layer! as ImageFilterLayer;
filterLayer.imageFilter = filter;
} else {
layer = ImageFilterLayer(imageFilter: filter);
}
context.pushLayer(layer!, super.paint, offset);
assert(() {
layer!.debugCreator = debugCreator;
return true;
}());
}
if (child == null) {
return;
}
if (isRepaintBoundary) {
return super.paint(context, offset);
}

final Matrix4 transform = _effectiveTransform!;
final Offset? childOffset = MatrixUtils.getAsTranslation(transform);
if (childOffset != null) {
super.paint(context, offset + childOffset);
layer = null;
return;
}
// if the matrix is singular the children would be compressed to a line or
// single point, instead short-circuit and paint nothing.
final double det = transform.determinant();
if (det == 0 || !det.isFinite) {
layer = null;
return;
}
layer = context.pushTransform(
needsCompositing,
offset,
transform,
super.paint,
oldLayer: layer is TransformLayer ? layer as TransformLayer? : null,
);
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,35 @@ void main() {

expect(RenderTestObject.paintCount, 1);
});

testWidgets('Transform with FilterQuality avoids repainting child as it animates', (WidgetTester tester) async {
RenderTestObject.paintCount = 0;
await tester.pumpWidget(
Container(
color: Colors.red,
child: Transform.translate(
offset: const Offset(5.0, 10.0),
filterQuality: FilterQuality.low,
child: const TestWidget(),
),
)
);

expect(RenderTestObject.paintCount, 1);

await tester.pumpWidget(
Container(
color: Colors.red,
child: Transform.translate(
offset: const Offset(25.0, 0.0),
filterQuality: FilterQuality.low,
child: const TestWidget(),
),
)
);

expect(RenderTestObject.paintCount, 1);
});
}

class TestWidget extends SingleChildRenderObjectWidget {
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter/test/widgets/transform_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ void main() {
moreOrLessEquals(0.7071067811865476), moreOrLessEquals(0.7071067811865475), 0.0, 0.0,
moreOrLessEquals(-0.7071067811865475), moreOrLessEquals(0.7071067811865476), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
moreOrLessEquals(329.28932188134524), moreOrLessEquals(-194.97474683058329), 0.0, 1.0,
moreOrLessEquals(50), moreOrLessEquals(-20.710678118654755), 0.0, 1.0,
]);
});

Expand Down

0 comments on commit e331dcd

Please sign in to comment.