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

Commit c6b2ced

Browse files
authored
Set nested clip nodes (#37850)
1 parent cefb954 commit c6b2ced

File tree

4 files changed

+365
-10
lines changed

4 files changed

+365
-10
lines changed

shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
#include "flatland_external_view_embedder.h"
6+
#include <algorithm>
67
#include <cstdint>
78

89
#include "flutter/fml/trace_event.h"
@@ -17,6 +18,24 @@ namespace {
1718
// overflows on operations (like FLT_MAX would).
1819
constexpr float kMaxHitRegionSize = 1'000'000.f;
1920

21+
void AttachClipTransformChild(
22+
FlatlandConnection* flatland,
23+
FlatlandExternalViewEmbedder::ClipTransform* parent_clip_transform,
24+
const fuchsia::ui::composition::TransformId& child_transform_id) {
25+
flatland->flatland()->AddChild(parent_clip_transform->transform_id,
26+
child_transform_id);
27+
parent_clip_transform->children.push_back(child_transform_id);
28+
}
29+
30+
void DetachClipTransformChildren(
31+
FlatlandConnection* flatland,
32+
FlatlandExternalViewEmbedder::ClipTransform* clip_transform) {
33+
for (auto& child : clip_transform->children) {
34+
flatland->flatland()->RemoveChild(clip_transform->transform_id, child);
35+
}
36+
clip_transform->children.clear();
37+
}
38+
2039
} // namespace
2140

2241
FlatlandExternalViewEmbedder::FlatlandExternalViewEmbedder(
@@ -263,15 +282,61 @@ void FlatlandExternalViewEmbedder::SubmitFrame(
263282
viewport.transform_id,
264283
{static_cast<int32_t>(view_mutators.transform.getTranslateX()),
265284
static_cast<int32_t>(view_mutators.transform.getTranslateY())});
266-
267285
flatland_->flatland()->SetScale(
268286
viewport.transform_id, {view_mutators.transform.getScaleX(),
269287
view_mutators.transform.getScaleY()});
270288
viewport.mutators.transform = view_mutators.transform;
271289
}
272290

273291
// TODO(fxbug.dev/94000): Set HitTestBehavior.
274-
// TODO(fxbug.dev/94000): Set ClipRegions.
292+
293+
// Set clip regions.
294+
if (view_mutators.clips != viewport.mutators.clips) {
295+
// Expand the clip_transforms array to fit any new transforms.
296+
while (viewport.clip_transforms.size() < view_mutators.clips.size()) {
297+
ClipTransform clip_transform;
298+
clip_transform.transform_id = flatland_->NextTransformId();
299+
flatland_->flatland()->CreateTransform(clip_transform.transform_id);
300+
viewport.clip_transforms.emplace_back(std::move(clip_transform));
301+
}
302+
FML_CHECK(viewport.clip_transforms.size() >=
303+
view_mutators.clips.size());
304+
305+
// Adjust and re-parent all clip transforms.
306+
for (auto& clip_transform : viewport.clip_transforms) {
307+
DetachClipTransformChildren(flatland_.get(), &clip_transform);
308+
}
309+
310+
for (size_t c = 0; c < view_mutators.clips.size(); c++) {
311+
const SkMatrix& clip_matrix = view_mutators.clips[c].transform;
312+
const SkRect& clip_rect = view_mutators.clips[c].rect;
313+
314+
flatland_->flatland()->SetTranslation(
315+
viewport.clip_transforms[c].transform_id,
316+
{static_cast<int32_t>(clip_matrix.getTranslateX()),
317+
static_cast<int32_t>(clip_matrix.getTranslateY())});
318+
flatland_->flatland()->SetScale(
319+
viewport.clip_transforms[c].transform_id,
320+
{clip_matrix.getScaleX(), clip_matrix.getScaleY()});
321+
fuchsia::math::Rect rect = {
322+
static_cast<int32_t>(clip_rect.x()),
323+
static_cast<int32_t>(clip_rect.y()),
324+
static_cast<int32_t>(clip_rect.width()),
325+
static_cast<int32_t>(clip_rect.height())};
326+
flatland_->flatland()->SetClipBoundary(
327+
viewport.clip_transforms[c].transform_id,
328+
std::make_unique<fuchsia::math::Rect>(std::move(rect)));
329+
330+
const auto child_transform_id =
331+
c != (view_mutators.clips.size() - 1)
332+
? viewport.clip_transforms[c + 1].transform_id
333+
: viewport.transform_id;
334+
AttachClipTransformChild(flatland_.get(),
335+
&(viewport.clip_transforms[c]),
336+
child_transform_id);
337+
}
338+
viewport.mutators.clips = view_mutators.clips;
339+
}
275340

276341
// Set opacity.
277342
if (view_mutators.opacity != viewport.mutators.opacity) {
@@ -299,9 +364,13 @@ void FlatlandExternalViewEmbedder::SubmitFrame(
299364
}
300365

301366
// Attach the FlatlandView to the main scene graph.
367+
const auto main_child_transform =
368+
viewport.mutators.clips.empty()
369+
? viewport.transform_id
370+
: viewport.clip_transforms[0].transform_id;
302371
flatland_->flatland()->AddChild(root_transform_id_,
303-
viewport.transform_id);
304-
child_transforms_.emplace_back(viewport.transform_id);
372+
main_child_transform);
373+
child_transforms_.emplace_back(main_child_transform);
305374
}
306375

307376
// Acquire the surface associated with the layer.
@@ -485,19 +554,29 @@ void FlatlandExternalViewEmbedder::DestroyView(
485554

486555
auto viewport_id = flatland_view->second.viewport_id;
487556
auto transform_id = flatland_view->second.transform_id;
557+
auto& clip_transforms = flatland_view->second.clip_transforms;
488558
if (!flatland_view->second.pending_create_viewport_callback) {
489559
flatland_->flatland()->ReleaseViewport(viewport_id, [](auto) {});
490560
}
491-
auto itr =
492-
std::find_if(child_transforms_.begin(), child_transforms_.end(),
493-
[transform_id](fuchsia::ui::composition::TransformId id) {
494-
return id.value == transform_id.value;
495-
});
561+
auto itr = std::find_if(
562+
child_transforms_.begin(), child_transforms_.end(),
563+
[transform_id,
564+
&clip_transforms](fuchsia::ui::composition::TransformId id) {
565+
return id.value == transform_id.value ||
566+
(!clip_transforms.empty() &&
567+
(id.value == clip_transforms[0].transform_id.value));
568+
});
496569
if (itr != child_transforms_.end()) {
497-
flatland_->flatland()->RemoveChild(root_transform_id_, transform_id);
570+
flatland_->flatland()->RemoveChild(root_transform_id_, *itr);
498571
child_transforms_.erase(itr);
499572
}
573+
for (auto& clip_transform : clip_transforms) {
574+
DetachClipTransformChildren(flatland_.get(), &clip_transform);
575+
}
500576
flatland_->flatland()->ReleaseTransform(transform_id);
577+
for (auto& clip_transform : clip_transforms) {
578+
flatland_->flatland()->ReleaseTransform(clip_transform.transform_id);
579+
}
501580

502581
flatland_views_.erase(flatland_view);
503582
on_view_unbound(viewport_id);

shell/platform/fuchsia/flutter/flatland_external_view_embedder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ class FlatlandExternalViewEmbedder final
114114
bool hit_testable,
115115
bool focusable);
116116

117+
// Holds the clip transform that may be applied on a FlatlandView.
118+
struct ClipTransform {
119+
fuchsia::ui::composition::TransformId transform_id;
120+
std::vector<fuchsia::ui::composition::TransformId> children;
121+
};
122+
117123
private:
118124
void Reset(); // Reset state for a new frame.
119125

@@ -173,6 +179,7 @@ class FlatlandExternalViewEmbedder final
173179
constexpr static EmbedderLayerId kRootLayerId = EmbedderLayerId{};
174180

175181
struct FlatlandView {
182+
std::vector<ClipTransform> clip_transforms;
176183
fuchsia::ui::composition::TransformId transform_id;
177184
fuchsia::ui::composition::ContentId viewport_id;
178185
ViewMutators mutators;

shell/platform/fuchsia/flutter/tests/fakes/scenic/fake_flatland_types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,16 @@ inline bool operator==(
124124
return true;
125125
}
126126

127+
inline bool operator==(const std::optional<fuchsia::math::Rect>& a,
128+
const std::optional<fuchsia::math::Rect>& b) {
129+
if (a.has_value() != b.has_value()) {
130+
return false;
131+
}
132+
if (!a.has_value()) {
133+
}
134+
return a.value() == b.value();
135+
}
136+
127137
namespace flutter_runner::testing {
128138

129139
constexpr static fuchsia::ui::composition::TransformId kInvalidTransformId{0};

0 commit comments

Comments
 (0)