Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a4777ff

Browse files
authored
[CP] [skwasm] Fix platform view occlusion logic. (#54871)
Cherry-pick of #54061
1 parent fcf10af commit a4777ff

File tree

4 files changed

+71
-59
lines changed

4 files changed

+71
-59
lines changed

lib/web_ui/lib/src/engine/layers.dart

Lines changed: 18 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ class BackdropFilterOperation implements LayerOperation {
2121
final ui.BlendMode mode;
2222

2323
@override
24-
ui.Rect cullRect(ui.Rect contentRect) => contentRect;
25-
26-
@override
27-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
24+
ui.Rect mapRect(ui.Rect contentRect) => contentRect;
2825

2926
@override
3027
void pre(SceneCanvas canvas, ui.Rect contentRect) {
@@ -50,10 +47,7 @@ class ClipPathOperation implements LayerOperation {
5047
final ui.Clip clip;
5148

5249
@override
53-
ui.Rect cullRect(ui.Rect contentRect) => contentRect.intersect(path.getBounds());
54-
55-
@override
56-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
50+
ui.Rect mapRect(ui.Rect contentRect) => contentRect.intersect(path.getBounds());
5751

5852
@override
5953
void pre(SceneCanvas canvas, ui.Rect contentRect) {
@@ -89,10 +83,7 @@ class ClipRectOperation implements LayerOperation {
8983
final ui.Clip clip;
9084

9185
@override
92-
ui.Rect cullRect(ui.Rect contentRect) => contentRect.intersect(rect);
93-
94-
@override
95-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
86+
ui.Rect mapRect(ui.Rect contentRect) => contentRect.intersect(rect);
9687

9788
@override
9889
void pre(SceneCanvas canvas, ui.Rect contentRect) {
@@ -128,10 +119,7 @@ class ClipRRectOperation implements LayerOperation {
128119
final ui.Clip clip;
129120

130121
@override
131-
ui.Rect cullRect(ui.Rect contentRect) => contentRect.intersect(rrect.outerRect);
132-
133-
@override
134-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
122+
ui.Rect mapRect(ui.Rect contentRect) => contentRect.intersect(rrect.outerRect);
135123

136124
@override
137125
void pre(SceneCanvas canvas, ui.Rect contentRect) {
@@ -166,10 +154,7 @@ class ColorFilterOperation implements LayerOperation {
166154
final ui.ColorFilter filter;
167155

168156
@override
169-
ui.Rect cullRect(ui.Rect contentRect) => contentRect;
170-
171-
@override
172-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
157+
ui.Rect mapRect(ui.Rect contentRect) => contentRect;
173158

174159
@override
175160
void pre(SceneCanvas canvas, ui.Rect contentRect) {
@@ -191,23 +176,19 @@ class ImageFilterLayer
191176
class ImageFilterOperation implements LayerOperation {
192177
ImageFilterOperation(this.filter, this.offset);
193178

194-
final ui.ImageFilter filter;
179+
final SceneImageFilter filter;
195180
final ui.Offset offset;
196181

197182
@override
198-
ui.Rect cullRect(ui.Rect contentRect) => (filter as SceneImageFilter).filterBounds(contentRect);
199-
200-
@override
201-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
183+
ui.Rect mapRect(ui.Rect contentRect) => filter.filterBounds(contentRect);
202184

203185
@override
204186
void pre(SceneCanvas canvas, ui.Rect contentRect) {
205187
if (offset != ui.Offset.zero) {
206188
canvas.save();
207189
canvas.translate(offset.dx, offset.dy);
208190
}
209-
final ui.Rect adjustedContentRect =
210-
(filter as SceneImageFilter).filterBounds(contentRect);
191+
final ui.Rect adjustedContentRect = filter.filterBounds(contentRect);
211192
canvas.saveLayer(adjustedContentRect, ui.Paint()..imageFilter = filter);
212193
}
213194

@@ -241,10 +222,7 @@ class OffsetOperation implements LayerOperation {
241222
final double dy;
242223

243224
@override
244-
ui.Rect cullRect(ui.Rect contentRect) => contentRect.shift(ui.Offset(dx, dy));
245-
246-
@override
247-
ui.Rect inverseMapRect(ui.Rect rect) => rect.shift(ui.Offset(-dx, -dy));
225+
ui.Rect mapRect(ui.Rect contentRect) => contentRect.shift(ui.Offset(dx, dy));
248226

249227
@override
250228
void pre(SceneCanvas canvas, ui.Rect cullRect) {
@@ -273,10 +251,7 @@ class OpacityOperation implements LayerOperation {
273251
final ui.Offset offset;
274252

275253
@override
276-
ui.Rect cullRect(ui.Rect contentRect) => contentRect.shift(offset);
277-
278-
@override
279-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
254+
ui.Rect mapRect(ui.Rect contentRect) => contentRect.shift(offset);
280255

281256
@override
282257
void pre(SceneCanvas canvas, ui.Rect cullRect) {
@@ -314,16 +289,11 @@ class TransformOperation implements LayerOperation {
314289

315290
final Float64List transform;
316291

317-
Matrix4 getMatrix() => Matrix4.fromFloat32List(toMatrix32(transform));
292+
Matrix4? _memoizedMatrix;
293+
Matrix4 get matrix => _memoizedMatrix ?? (_memoizedMatrix = Matrix4.fromFloat32List(toMatrix32(transform)));
318294

319295
@override
320-
ui.Rect cullRect(ui.Rect contentRect) => getMatrix().transformRect(contentRect);
321-
322-
@override
323-
ui.Rect inverseMapRect(ui.Rect rect) {
324-
final Matrix4 matrix = getMatrix()..invert();
325-
return matrix.transformRect(rect);
326-
}
296+
ui.Rect mapRect(ui.Rect contentRect) => matrix.transformRect(contentRect);
327297

328298
@override
329299
void pre(SceneCanvas canvas, ui.Rect cullRect) {
@@ -338,7 +308,7 @@ class TransformOperation implements LayerOperation {
338308

339309
@override
340310
PlatformViewStyling createPlatformViewStyling() => PlatformViewStyling(
341-
position: PlatformViewPosition.transform(getMatrix()),
311+
position: PlatformViewPosition.transform(matrix),
342312
);
343313
}
344314

@@ -353,10 +323,7 @@ class ShaderMaskOperation implements LayerOperation {
353323
final ui.BlendMode blendMode;
354324

355325
@override
356-
ui.Rect cullRect(ui.Rect contentRect) => contentRect;
357-
358-
@override
359-
ui.Rect inverseMapRect(ui.Rect rect) => rect;
326+
ui.Rect mapRect(ui.Rect contentRect) => contentRect;
360327

361328
@override
362329
void pre(SceneCanvas canvas, ui.Rect contentRect) {
@@ -444,11 +411,8 @@ abstract class LayerOperation {
444411
// Given an input content rectangle, this returns a conservative estimate of
445412
// the covering rectangle of the content after it has been processed by the
446413
// layer operation.
447-
ui.Rect cullRect(ui.Rect contentRect);
414+
ui.Rect mapRect(ui.Rect contentRect);
448415

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

@@ -636,7 +600,7 @@ class LayerBuilder {
636600
// Merge the existing draw commands into a single picture and add a slice
637601
// with that picture to the slice list.
638602
final ui.Rect drawnRect = picturesRect ?? ui.Rect.zero;
639-
final ui.Rect rect = operation?.cullRect(drawnRect) ?? drawnRect;
603+
final ui.Rect rect = operation?.mapRect(drawnRect) ?? drawnRect;
640604
final (ui.PictureRecorder recorder, SceneCanvas canvas) = _createRecorder(rect);
641605

642606
operation?.pre(canvas, rect);
@@ -660,7 +624,7 @@ class LayerBuilder {
660624
// slice.
661625
ui.Rect? occlusionRect = platformViewRect;
662626
if (occlusionRect != null && operation != null) {
663-
occlusionRect = operation!.inverseMapRect(occlusionRect);
627+
occlusionRect = operation!.mapRect(occlusionRect);
664628
}
665629
layer.slices.add(PlatformViewSlice(pendingPlatformViews, occlusionRect));
666630
}

lib/web_ui/lib/src/engine/scene_builder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class EngineSceneBuilder implements ui.SceneBuilder {
185185
ui.ImageFilterEngineLayer? oldLayer
186186
}) => pushLayer<ImageFilterLayer>(
187187
ImageFilterLayer(),
188-
ImageFilterOperation(filter, offset),
188+
ImageFilterOperation(filter as SceneImageFilter, offset),
189189
);
190190

191191
@override

lib/web_ui/test/engine/scene_builder_test.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,33 @@ void testMain() {
158158
))
159159
]));
160160
});
161+
162+
test('platform view sandwich (overlapping) with offset layers', () {
163+
final EngineSceneBuilder sceneBuilder = EngineSceneBuilder();
164+
165+
const ui.Rect pictureRect1 = ui.Rect.fromLTRB(100, 100, 200, 200);
166+
sceneBuilder.addPicture(ui.Offset.zero, StubPicture(pictureRect1));
167+
168+
sceneBuilder.pushOffset(150, 150);
169+
const ui.Rect platformViewRect = ui.Rect.fromLTRB(0, 0, 100, 100);
170+
sceneBuilder.addPlatformView(
171+
1,
172+
offset: platformViewRect.topLeft,
173+
width: platformViewRect.width,
174+
height: platformViewRect.height
175+
);
176+
sceneBuilder.pushOffset(50, 50);
177+
sceneBuilder.addPicture(ui.Offset.zero, StubPicture(const ui.Rect.fromLTRB(0, 0, 100, 100)));
178+
179+
final EngineScene scene = sceneBuilder.build() as EngineScene;
180+
final List<LayerSlice> slices = scene.rootLayer.slices;
181+
expect(slices.length, 3);
182+
expect(slices[0], pictureSliceWithRect(pictureRect1));
183+
expect(slices[1], platformViewSliceWithViews(<PlatformView>[
184+
PlatformView(1, platformViewRect.size, const PlatformViewStyling(position: PlatformViewPosition.offset(ui.Offset(150, 150))))
185+
]));
186+
expect(slices[2], pictureSliceWithRect(const ui.Rect.fromLTRB(200, 200, 300, 300)));
187+
});
161188
});
162189
}
163190

@@ -217,12 +244,15 @@ class PlatformViewSliceMatcher extends Matcher {
217244
final PlatformView expectedView = expectedPlatformViews[i];
218245
final PlatformView actualView = item.views[i];
219246
if (expectedView.viewId != actualView.viewId) {
247+
print('viewID mismatch');
220248
return false;
221249
}
222250
if (expectedView.size != actualView.size) {
251+
print('size mismatch');
223252
return false;
224253
}
225254
if (expectedView.styling != actualView.styling) {
255+
print('styling mismatch');
226256
return false;
227257
}
228258
}

lib/web_ui/test/engine/scene_builder_utils.dart

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,21 @@ class StubPictureRecorder implements ui.PictureRecorder {
6060
class StubSceneCanvas implements SceneCanvas {
6161
List<StubPicture> pictures = <StubPicture>[];
6262

63+
// We actually use offsets in some of the tests, so we need to track the
64+
// translate calls as they are made.
65+
List<ui.Offset> offsetStack = <ui.Offset>[ui.Offset.zero];
66+
67+
ui.Offset get currentOffset {
68+
return offsetStack.last;
69+
}
70+
71+
set currentOffset(ui.Offset offset) {
72+
offsetStack[offsetStack.length - 1] = offset;
73+
}
74+
6375
@override
6476
void drawPicture(ui.Picture picture) {
65-
pictures.add(picture as StubPicture);
77+
pictures.add(StubPicture((picture as StubPicture).cullRect.shift(currentOffset)));
6678
}
6779

6880
@override
@@ -155,7 +167,9 @@ class StubSceneCanvas implements SceneCanvas {
155167
}
156168

157169
@override
158-
void restore() {}
170+
void restore() {
171+
offsetStack.removeLast();
172+
}
159173

160174
@override
161175
void restoreToCount(int count) {}
@@ -164,7 +178,9 @@ class StubSceneCanvas implements SceneCanvas {
164178
void rotate(double radians) {}
165179

166180
@override
167-
void save() {}
181+
void save() {
182+
offsetStack.add(currentOffset);
183+
}
168184

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

184200
@override
185-
void translate(double dx, double dy) {}
201+
void translate(double dx, double dy) {
202+
currentOffset += ui.Offset(dx, dy);
203+
}
186204
}

0 commit comments

Comments
 (0)