Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[skwasm] Fix platform view occlusion logic. #54061

Merged
merged 3 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 18 additions & 54 deletions lib/web_ui/lib/src/engine/layers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 21,7 @@ class BackdropFilterOperation implements LayerOperation {
final ui.BlendMode mode;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect;

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => contentRect;

@override
void pre(SceneCanvas canvas, ui.Rect contentRect) {
Expand All @@ -50,10 47,7 @@ class ClipPathOperation implements LayerOperation {
final ui.Clip clip;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect.intersect(path.getBounds());

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => contentRect.intersect(path.getBounds());

@override
void pre(SceneCanvas canvas, ui.Rect contentRect) {
Expand Down Expand Up @@ -89,10 83,7 @@ class ClipRectOperation implements LayerOperation {
final ui.Clip clip;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect.intersect(rect);

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => contentRect.intersect(rect);

@override
void pre(SceneCanvas canvas, ui.Rect contentRect) {
Expand Down Expand Up @@ -128,10 119,7 @@ class ClipRRectOperation implements LayerOperation {
final ui.Clip clip;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect.intersect(rrect.outerRect);

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => contentRect.intersect(rrect.outerRect);

@override
void pre(SceneCanvas canvas, ui.Rect contentRect) {
Expand Down Expand Up @@ -166,10 154,7 @@ class ColorFilterOperation implements LayerOperation {
final ui.ColorFilter filter;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect;

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => contentRect;

@override
void pre(SceneCanvas canvas, ui.Rect contentRect) {
Expand All @@ -191,23 176,19 @@ class ImageFilterLayer
class ImageFilterOperation implements LayerOperation {
ImageFilterOperation(this.filter, this.offset);

final ui.ImageFilter filter;
final SceneImageFilter filter;
final ui.Offset offset;

@override
ui.Rect cullRect(ui.Rect contentRect) => (filter as SceneImageFilter).filterBounds(contentRect);

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => filter.filterBounds(contentRect);

@override
void pre(SceneCanvas canvas, ui.Rect contentRect) {
if (offset != ui.Offset.zero) {
canvas.save();
canvas.translate(offset.dx, offset.dy);
}
final ui.Rect adjustedContentRect =
(filter as SceneImageFilter).filterBounds(contentRect);
final ui.Rect adjustedContentRect = filter.filterBounds(contentRect);
canvas.saveLayer(adjustedContentRect, ui.Paint()..imageFilter = filter);
}

Expand Down Expand Up @@ -241,10 222,7 @@ class OffsetOperation implements LayerOperation {
final double dy;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect.shift(ui.Offset(dx, dy));

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect.shift(ui.Offset(-dx, -dy));
ui.Rect mapRect(ui.Rect contentRect) => contentRect.shift(ui.Offset(dx, dy));

@override
void pre(SceneCanvas canvas, ui.Rect cullRect) {
Expand Down Expand Up @@ -273,10 251,7 @@ class OpacityOperation implements LayerOperation {
final ui.Offset offset;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect.shift(offset);

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => contentRect.shift(offset);

@override
void pre(SceneCanvas canvas, ui.Rect cullRect) {
Expand Down Expand Up @@ -314,16 289,11 @@ class TransformOperation implements LayerOperation {

final Float64List transform;

Matrix4 getMatrix() => Matrix4.fromFloat32List(toMatrix32(transform));
Matrix4? _memoizedMatrix;
Matrix4 get matrix => _memoizedMatrix ?? (_memoizedMatrix = Matrix4.fromFloat32List(toMatrix32(transform)));

@override
ui.Rect cullRect(ui.Rect contentRect) => getMatrix().transformRect(contentRect);

@override
ui.Rect inverseMapRect(ui.Rect rect) {
final Matrix4 matrix = getMatrix()..invert();
return matrix.transformRect(rect);
}
ui.Rect mapRect(ui.Rect contentRect) => matrix.transformRect(contentRect);

@override
void pre(SceneCanvas canvas, ui.Rect cullRect) {
Expand All @@ -338,7 308,7 @@ class TransformOperation implements LayerOperation {

@override
PlatformViewStyling createPlatformViewStyling() => PlatformViewStyling(
position: PlatformViewPosition.transform(getMatrix()),
position: PlatformViewPosition.transform(matrix),
);
}

Expand All @@ -353,10 323,7 @@ class ShaderMaskOperation implements LayerOperation {
final ui.BlendMode blendMode;

@override
ui.Rect cullRect(ui.Rect contentRect) => contentRect;

@override
ui.Rect inverseMapRect(ui.Rect rect) => rect;
ui.Rect mapRect(ui.Rect contentRect) => contentRect;

@override
void pre(SceneCanvas canvas, ui.Rect contentRect) {
Expand Down Expand Up @@ -444,11 411,8 @@ abstract class LayerOperation {
// Given an input content rectangle, this returns a conservative estimate of
// the covering rectangle of the content after it has been processed by the
// layer operation.
ui.Rect cullRect(ui.Rect contentRect);
ui.Rect mapRect(ui.Rect contentRect);

// Takes a rectangle in the layer's coordinate space and maps it to the parent
// coordinate space.
ui.Rect inverseMapRect(ui.Rect rect);
void pre(SceneCanvas canvas, ui.Rect contentRect);
void post(SceneCanvas canvas, ui.Rect contentRect);

Expand Down Expand Up @@ -625,7 589,7 @@ class LayerBuilder {
// Merge the existing draw commands into a single picture and add a slice
// with that picture to the slice list.
final ui.Rect drawnRect = picturesRect ?? ui.Rect.zero;
final ui.Rect rect = operation?.cullRect(drawnRect) ?? drawnRect;
final ui.Rect rect = operation?.mapRect(drawnRect) ?? drawnRect;
final (ui.PictureRecorder recorder, SceneCanvas canvas) = _createRecorder(rect);

operation?.pre(canvas, rect);
Expand All @@ -649,7 613,7 @@ class LayerBuilder {
// slice.
ui.Rect? occlusionRect = platformViewRect;
if (occlusionRect != null && operation != null) {
occlusionRect = operation!.inverseMapRect(occlusionRect);
occlusionRect = operation!.mapRect(occlusionRect);
}
layer.slices.add(PlatformViewSlice(pendingPlatformViews, occlusionRect));
}
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/scene_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 185,7 @@ class EngineSceneBuilder implements ui.SceneBuilder {
ui.ImageFilterEngineLayer? oldLayer
}) => pushLayer<ImageFilterLayer>(
ImageFilterLayer(),
ImageFilterOperation(filter, offset),
ImageFilterOperation(filter as SceneImageFilter, offset),
);

@override
Expand Down
30 changes: 30 additions & 0 deletions lib/web_ui/test/engine/scene_builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 150,33 @@ void testMain() {
PlatformView(1, platformViewRect, const PlatformViewStyling())
]));
});

test('platform view sandwich (overlapping) with offset layers', () {
final EngineSceneBuilder sceneBuilder = EngineSceneBuilder();

const ui.Rect pictureRect1 = ui.Rect.fromLTRB(100, 100, 200, 200);
sceneBuilder.addPicture(ui.Offset.zero, StubPicture(pictureRect1));

sceneBuilder.pushOffset(150, 150);
const ui.Rect platformViewRect = ui.Rect.fromLTRB(0, 0, 100, 100);
sceneBuilder.addPlatformView(
1,
offset: platformViewRect.topLeft,
width: platformViewRect.width,
height: platformViewRect.height
);
sceneBuilder.pushOffset(50, 50);
sceneBuilder.addPicture(ui.Offset.zero, StubPicture(const ui.Rect.fromLTRB(0, 0, 100, 100)));

final EngineScene scene = sceneBuilder.build() as EngineScene;
final List<LayerSlice> slices = scene.rootLayer.slices;
expect(slices.length, 3);
expect(slices[0], pictureSliceWithRect(pictureRect1));
expect(slices[1], platformViewSliceWithViews(<PlatformView>[
PlatformView(1, platformViewRect, const PlatformViewStyling(position: PlatformViewPosition.offset(ui.Offset(150, 150))))
]));
expect(slices[2], pictureSliceWithRect(const ui.Rect.fromLTRB(200, 200, 300, 300)));
});
});
}

Expand Down Expand Up @@ -209,12 236,15 @@ class PlatformViewSliceMatcher extends Matcher {
final PlatformView expectedView = expectedPlatformViews[i];
final PlatformView actualView = item.views[i];
if (expectedView.viewId != actualView.viewId) {
print('viewID mismatch');
return false;
}
if (expectedView.bounds != actualView.bounds) {
print('bounds mismatch');
return false;
}
if (expectedView.styling != actualView.styling) {
print('styling mismatch');
return false;
}
}
Expand Down
26 changes: 22 additions & 4 deletions lib/web_ui/test/engine/scene_builder_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 60,21 @@ class StubPictureRecorder implements ui.PictureRecorder {
class StubSceneCanvas implements SceneCanvas {
List<StubPicture> pictures = <StubPicture>[];

// We actually use offsets in some of the tests, so we need to track the
// translate calls as they are made.
List<ui.Offset> offsetStack = <ui.Offset>[ui.Offset.zero];

ui.Offset get currentOffset {
return offsetStack.last;
}

set currentOffset(ui.Offset offset) {
offsetStack[offsetStack.length - 1] = offset;
}

@override
void drawPicture(ui.Picture picture) {
pictures.add(picture as StubPicture);
pictures.add(StubPicture((picture as StubPicture).cullRect.shift(currentOffset)));
}

@override
Expand Down Expand Up @@ -155,7 167,9 @@ class StubSceneCanvas implements SceneCanvas {
}

@override
void restore() {}
void restore() {
offsetStack.removeLast();
}

@override
void restoreToCount(int count) {}
Expand All @@ -164,7 178,9 @@ class StubSceneCanvas implements SceneCanvas {
void rotate(double radians) {}

@override
void save() {}
void save() {
offsetStack.add(currentOffset);
}

@override
void saveLayer(ui.Rect? bounds, ui.Paint paint) {}
Expand All @@ -182,5 198,7 @@ class StubSceneCanvas implements SceneCanvas {
void transform(Float64List matrix4) {}

@override
void translate(double dx, double dy) {}
void translate(double dx, double dy) {
currentOffset = ui.Offset(dx, dy);
}
}