Migrate Mutators to DisplayList/Impeller geometry (#164258)

Mutator types and MutatorsStack will now use DisplayList/Impeller
geometry objects.
This commit is contained in:
Jim Graham 2025-03-06 13:27:51 -08:00 committed by GitHub
parent eb07c51230
commit 66e910d27e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 1223 additions and 961 deletions

View File

@ -106,7 +106,7 @@ const SkPath& DlPath::GetSkPath() const {
return sk_path.value(); return sk_path.value();
} }
Path DlPath::GetPath() const { const Path& DlPath::GetPath() const {
auto& sk_path = data_->sk_path; auto& sk_path = data_->sk_path;
auto& path = data_->path; auto& path = data_->path;
if (path.has_value()) { if (path.has_value()) {

View File

@ -67,7 +67,7 @@ class DlPath {
DlPath& operator=(const DlPath&) = default; DlPath& operator=(const DlPath&) = default;
const SkPath& GetSkPath() const; const SkPath& GetSkPath() const;
impeller::Path GetPath() const; const impeller::Path& GetPath() const;
/// Intent to render an SkPath multiple times will make the path /// Intent to render an SkPath multiple times will make the path
/// non-volatile to enable caching in Skia. Calling this method /// non-volatile to enable caching in Skia. Calling this method

View File

@ -422,7 +422,7 @@ TEST(DisplayListSkConversions, ConicPathToQuads) {
sk_path.conicTo(20, 10, 20, 20, weight); sk_path.conicTo(20, 10, 20, 20, weight);
DlPath dl_path(sk_path); DlPath dl_path(sk_path);
impeller::Path i_path = dl_path.GetPath(); const impeller::Path& i_path = dl_path.GetPath();
auto it = i_path.begin(); auto it = i_path.begin();
ASSERT_EQ(it.type(), impeller::Path::ComponentType::kContour); ASSERT_EQ(it.type(), impeller::Path::ComponentType::kContour);

View File

@ -246,24 +246,31 @@ DlRect DisplayListMatrixClipState::GetLocalCullCoverage() const {
} }
bool DisplayListMatrixClipState::rect_covers_cull(const DlRect& content) const { bool DisplayListMatrixClipState::rect_covers_cull(const DlRect& content) const {
if (content.IsEmpty()) { return TransformedRectCoversBounds(content, matrix_, cull_rect_);
}
bool DisplayListMatrixClipState::TransformedRectCoversBounds(
const DlRect& local_rect,
const DlMatrix& matrix,
const DlRect& cull_bounds) {
if (local_rect.IsEmpty()) {
return false; return false;
} }
if (cull_rect_.IsEmpty()) { if (cull_bounds.IsEmpty()) {
return true; return true;
} }
if (matrix_.IsAligned2D()) { if (matrix.IsAligned2D()) {
// This transform-to-device calculation is faster and more accurate // This transform-to-device calculation is faster and more accurate
// for rect-to-rect aligned transformations, but not accurate under // for rect-to-rect aligned transformations, but not accurate under
// (non-quadrant) rotations and skews. // (non-quadrant) rotations and skews.
return content.TransformAndClipBounds(matrix_).Contains(cull_rect_); return local_rect.TransformAndClipBounds(matrix).Contains(cull_bounds);
} }
DlPoint corners[4]; DlPoint corners[4];
if (!getLocalCullCorners(corners)) { if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false; return false;
} }
for (auto corner : corners) { for (auto corner : corners) {
if (!content.ContainsInclusive(corner)) { if (!local_rect.ContainsInclusive(corner)) {
return false; return false;
} }
} }
@ -271,20 +278,27 @@ bool DisplayListMatrixClipState::rect_covers_cull(const DlRect& content) const {
} }
bool DisplayListMatrixClipState::oval_covers_cull(const DlRect& bounds) const { bool DisplayListMatrixClipState::oval_covers_cull(const DlRect& bounds) const {
if (bounds.IsEmpty()) { return TransformedOvalCoversBounds(bounds, matrix_, cull_rect_);
}
bool DisplayListMatrixClipState::TransformedOvalCoversBounds(
const DlRect& local_oval_bounds,
const DlMatrix& matrix,
const DlRect& cull_bounds) {
if (local_oval_bounds.IsEmpty()) {
return false; return false;
} }
if (cull_rect_.IsEmpty()) { if (cull_bounds.IsEmpty()) {
return true; return true;
} }
DlPoint corners[4]; DlPoint corners[4];
if (!getLocalCullCorners(corners)) { if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false; return false;
} }
DlPoint center = bounds.GetCenter(); DlPoint center = local_oval_bounds.GetCenter();
DlSize scale = 2.0 / bounds.GetSize(); DlSize scale = 2.0 / local_oval_bounds.GetSize();
for (auto corner : corners) { for (auto corner : corners) {
if (!bounds.Contains(corner)) { if (!local_oval_bounds.Contains(corner)) {
return false; return false;
} }
if (((corner - center) * scale).GetLengthSquared() >= 1.0) { if (((corner - center) * scale).GetLengthSquared() >= 1.0) {
@ -296,28 +310,37 @@ bool DisplayListMatrixClipState::oval_covers_cull(const DlRect& bounds) const {
bool DisplayListMatrixClipState::rrect_covers_cull( bool DisplayListMatrixClipState::rrect_covers_cull(
const DlRoundRect& content) const { const DlRoundRect& content) const {
if (content.IsEmpty()) { return TransformedRRectCoversBounds(content, matrix_, cull_rect_);
}
bool DisplayListMatrixClipState::TransformedRRectCoversBounds(
const DlRoundRect& local_rrect,
const DlMatrix& matrix,
const DlRect& cull_bounds) {
if (local_rrect.IsEmpty()) {
return false; return false;
} }
if (cull_rect_.IsEmpty()) { if (cull_bounds.IsEmpty()) {
return true; return true;
} }
if (content.IsRect()) { if (local_rrect.IsRect()) {
return rect_covers_cull(content.GetBounds()); return TransformedRectCoversBounds(local_rrect.GetBounds(), matrix,
cull_bounds);
} }
if (content.IsOval()) { if (local_rrect.IsOval()) {
return oval_covers_cull(content.GetBounds()); return TransformedOvalCoversBounds(local_rrect.GetBounds(), matrix,
cull_bounds);
} }
if (!content.GetRadii().AreAllCornersSame()) { if (!local_rrect.GetRadii().AreAllCornersSame()) {
return false; return false;
} }
DlPoint corners[4]; DlPoint corners[4];
if (!getLocalCullCorners(corners)) { if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false; return false;
} }
auto outer = content.GetBounds(); auto outer = local_rrect.GetBounds();
auto center = outer.GetCenter(); auto center = outer.GetCenter();
auto radii = content.GetRadii().top_left; auto radii = local_rrect.GetRadii().top_left;
auto inner = outer.GetSize() * 0.5 - radii; auto inner = outer.GetSize() * 0.5 - radii;
auto scale = 1.0 / radii; auto scale = 1.0 / radii;
for (auto corner : corners) { for (auto corner : corners) {
@ -335,25 +358,34 @@ bool DisplayListMatrixClipState::rrect_covers_cull(
bool DisplayListMatrixClipState::rsuperellipse_covers_cull( bool DisplayListMatrixClipState::rsuperellipse_covers_cull(
const DlRoundSuperellipse& content) const { const DlRoundSuperellipse& content) const {
if (content.IsEmpty()) { return TransformedRoundSuperellipseCoversBounds(content, matrix_, cull_rect_);
}
bool DisplayListMatrixClipState::TransformedRoundSuperellipseCoversBounds(
const DlRoundSuperellipse& local_rse,
const DlMatrix& matrix,
const DlRect& cull_bounds) {
if (local_rse.IsEmpty()) {
return false; return false;
} }
if (cull_rect_.IsEmpty()) { if (cull_bounds.IsEmpty()) {
return true; return true;
} }
if (content.IsRect()) { if (local_rse.IsRect()) {
return rect_covers_cull(content.GetBounds()); return TransformedRectCoversBounds(local_rse.GetBounds(), matrix,
cull_bounds);
} }
if (content.IsOval()) { if (local_rse.IsOval()) {
return oval_covers_cull(content.GetBounds()); return TransformedOvalCoversBounds(local_rse.GetBounds(), matrix,
cull_bounds);
} }
DlPoint corners[4]; DlPoint corners[4];
if (!getLocalCullCorners(corners)) { if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false; return false;
} }
auto outer = content.GetBounds(); auto outer = local_rse.GetBounds();
auto param = impeller::RoundSuperellipseParam::MakeBoundsRadii( auto param = impeller::RoundSuperellipseParam::MakeBoundsRadii(
outer, content.GetRadii()); outer, local_rse.GetRadii());
for (auto corner : corners) { for (auto corner : corners) {
if (!outer.Contains(corner)) { if (!outer.Contains(corner)) {
return false; return false;
@ -365,15 +397,17 @@ bool DisplayListMatrixClipState::rsuperellipse_covers_cull(
return true; return true;
} }
bool DisplayListMatrixClipState::getLocalCullCorners(DlPoint corners[4]) const { bool DisplayListMatrixClipState::GetLocalCorners(DlPoint corners[4],
if (!is_matrix_invertable()) { const DlRect& rect,
const DlMatrix& matrix) {
if (!matrix.IsInvertible()) {
return false; return false;
} }
DlMatrix inverse = matrix_.Invert(); DlMatrix inverse = matrix.Invert();
corners[0] = inverse * cull_rect_.GetLeftTop(); corners[0] = inverse * rect.GetLeftTop();
corners[1] = inverse * cull_rect_.GetRightTop(); corners[1] = inverse * rect.GetRightTop();
corners[2] = inverse * cull_rect_.GetRightBottom(); corners[2] = inverse * rect.GetRightBottom();
corners[3] = inverse * cull_rect_.GetLeftBottom(); corners[3] = inverse * rect.GetLeftBottom();
return true; return true;
} }

View File

@ -113,12 +113,60 @@ class DisplayListMatrixClipState {
bool is_aa); bool is_aa);
void clipPath(const DlPath& path, DlClipOp op, bool is_aa); void clipPath(const DlPath& path, DlClipOp op, bool is_aa);
/// @brief Checks if the local rect, when transformed by the matrix,
/// completely covers the indicated culling bounds.
///
/// This utility method helps answer the question of whether a clip
/// rectangle being intersected under a transform is essentially obsolete
/// because it will not reduce the already existing clip culling bounds.
[[nodiscard]]
static bool TransformedRectCoversBounds(const DlRect& local_rect,
const DlMatrix& matrix,
const DlRect& cull_bounds);
/// @brief Checks if an oval defined by the local bounds, when transformed
/// by the matrix, completely covers the indicated culling bounds.
///
/// This utility method helps answer the question of whether a clip
/// oval being intersected under a transform is essentially obsolete
/// because it will not reduce the already existing clip culling bounds.
[[nodiscard]]
static bool TransformedOvalCoversBounds(const DlRect& local_oval_bounds,
const DlMatrix& matrix,
const DlRect& cull_bounds);
/// @brief Checks if the local round rect, when transformed by the matrix,
/// completely covers the indicated culling bounds.
///
/// This utility method helps answer the question of whether a clip
/// rrect being intersected under a transform is essentially obsolete
/// because it will not reduce the already existing clip culling bounds.
[[nodiscard]]
static bool TransformedRRectCoversBounds(const DlRoundRect& local_rrect,
const DlMatrix& matrix,
const DlRect& cull_bounds);
/// @brief Checks if the local round superellipse, when transformed by the
/// matrix, completely covers the indicated culling bounds.
///
/// This utility method helps answer the question of whether a clip round
/// superellipse being intersected under a transform is essentially obsolete
/// because it will not reduce the already existing clip culling bounds.
[[nodiscard]]
static bool TransformedRoundSuperellipseCoversBounds(
const DlRoundSuperellipse& local_rse,
const DlMatrix& matrix,
const DlRect& cull_bounds);
private: private:
DlRect cull_rect_; DlRect cull_rect_;
DlMatrix matrix_; DlMatrix matrix_;
bool getLocalCullCorners(DlPoint corners[4]) const;
void adjustCullRect(const DlRect& clip, DlClipOp op, bool is_aa); void adjustCullRect(const DlRect& clip, DlClipOp op, bool is_aa);
static bool GetLocalCorners(DlPoint corners[4],
const DlRect& rect,
const DlMatrix& matrix);
}; };
} // namespace flutter } // namespace flutter

View File

@ -468,15 +468,23 @@ TEST(DisplayListMatrixClipState, RectCoverage) {
DlRect rect = DlRect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f); DlRect rect = DlRect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
DisplayListMatrixClipState state(rect); DisplayListMatrixClipState state(rect);
EXPECT_TRUE(state.rect_covers_cull(rect)); auto test_rect = [&state](const DlRect& test_rect, bool expect) {
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f))); EXPECT_EQ(state.rect_covers_cull(test_rect), expect) << test_rect;
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f))); EXPECT_EQ(DisplayListMatrixClipState::TransformedRectCoversBounds(
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f))); test_rect, state.matrix(), state.GetDeviceCullCoverage()),
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f))); expect)
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f))); << test_rect;
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, -0.1f, 0.0f, 0.0f))); };
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, -0.1f))); test_rect(rect, true);
test_rect(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f), true);
test_rect(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f), true);
test_rect(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f), true);
test_rect(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f), true);
test_rect(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f), false);
test_rect(rect.Expand(0.0f, -0.1f, 0.0f, 0.0f), false);
test_rect(rect.Expand(0.0f, 0.0f, -0.1f, 0.0f), false);
test_rect(rect.Expand(0.0f, 0.0f, 0.0f, -0.1f), false);
} }
TEST(DisplayListMatrixClipState, RectCoverageAccuracy) { TEST(DisplayListMatrixClipState, RectCoverageAccuracy) {
@ -495,15 +503,23 @@ TEST(DisplayListMatrixClipState, RectCoverageAccuracy) {
DisplayListMatrixClipState state(cull); DisplayListMatrixClipState state(cull);
state.scale(DPR, DPR); state.scale(DPR, DPR);
EXPECT_TRUE(state.rect_covers_cull(rect)); auto test_rect = [&state](const DlRect& test_rect, bool expect) {
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f))); EXPECT_EQ(state.rect_covers_cull(test_rect), expect) << test_rect;
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f))); EXPECT_EQ(DisplayListMatrixClipState::TransformedRectCoversBounds(
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f))); test_rect, state.matrix(), state.GetDeviceCullCoverage()),
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f))); expect)
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f))); << test_rect;
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, -0.1f, 0.0f, 0.0f))); };
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, -0.1f))); test_rect(rect, true);
test_rect(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f), true);
test_rect(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f), true);
test_rect(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f), true);
test_rect(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f), true);
test_rect(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f), false);
test_rect(rect.Expand(0.0f, -0.1f, 0.0f, 0.0f), false);
test_rect(rect.Expand(0.0f, 0.0f, -0.1f, 0.0f), false);
test_rect(rect.Expand(0.0f, 0.0f, 0.0f, -0.1f), false);
} }
TEST(DisplayListMatrixClipState, RectCoverageUnderScale) { TEST(DisplayListMatrixClipState, RectCoverageUnderScale) {
@ -511,16 +527,24 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderScale) {
DisplayListMatrixClipState state(rect); DisplayListMatrixClipState state(rect);
state.scale(2.0f, 2.0f); state.scale(2.0f, 2.0f);
EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(100, 100, 200, 200))); auto test_rect = [&state](const DlRect& test_rect, bool expect) {
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 100))); EXPECT_EQ(state.rect_covers_cull(test_rect), expect) << test_rect;
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(49, 50, 100, 100))); EXPECT_EQ(DisplayListMatrixClipState::TransformedRectCoversBounds(
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 49, 100, 100))); test_rect, state.matrix(), state.GetDeviceCullCoverage()),
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 101, 100))); expect)
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 101))); << test_rect;
EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(51, 50, 100, 100))); };
EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(50, 51, 100, 100)));
EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 99, 100))); test_rect(DlRect::MakeLTRB(100, 100, 200, 200), false);
EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 99))); test_rect(DlRect::MakeLTRB(50, 50, 100, 100), true);
test_rect(DlRect::MakeLTRB(49, 50, 100, 100), true);
test_rect(DlRect::MakeLTRB(50, 49, 100, 100), true);
test_rect(DlRect::MakeLTRB(50, 50, 101, 100), true);
test_rect(DlRect::MakeLTRB(50, 50, 100, 101), true);
test_rect(DlRect::MakeLTRB(51, 50, 100, 100), false);
test_rect(DlRect::MakeLTRB(50, 51, 100, 100), false);
test_rect(DlRect::MakeLTRB(50, 50, 99, 100), false);
test_rect(DlRect::MakeLTRB(50, 50, 100, 99), false);
} }
TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) { TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
@ -537,6 +561,11 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
<< " testing " << test_true << std::endl << " testing " << test_true << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl << " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees"; << " at " << i << " degrees";
EXPECT_TRUE(DisplayListMatrixClipState::TransformedRectCoversBounds(
test_true, DlMatrix::MakeRotationZ(DlDegrees(i)), cull))
<< " testing " << test_true << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees";
if ((i % 90) == 45) { if ((i % 90) == 45) {
// The cull rect is largest when viewed at multiples of 45 // The cull rect is largest when viewed at multiples of 45
// degrees so we will fail to contain it at those angles // degrees so we will fail to contain it at those angles
@ -544,6 +573,11 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
<< " testing " << test_false << std::endl << " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl << " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees"; << " at " << i << " degrees";
EXPECT_FALSE(DisplayListMatrixClipState::TransformedRectCoversBounds(
test_false, DlMatrix::MakeRotationZ(DlDegrees(i)), cull))
<< " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees";
} else { } else {
// At other angles, the cull rect is not quite so big as to encroach // At other angles, the cull rect is not quite so big as to encroach
// upon the expanded test rectangle. // upon the expanded test rectangle.
@ -551,6 +585,11 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
<< " testing " << test_false << std::endl << " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl << " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees"; << " at " << i << " degrees";
EXPECT_TRUE(DisplayListMatrixClipState::TransformedRectCoversBounds(
test_false, DlMatrix::MakeRotationZ(DlDegrees(i)), cull))
<< " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees";
} }
} }
} }
@ -564,15 +603,23 @@ TEST(DisplayListMatrixClipState, OvalCoverage) {
// then use larger expansion/contractions of 0.1f to cover/not-cover it. // then use larger expansion/contractions of 0.1f to cover/not-cover it.
DlRect test = cull.Scale(impeller::kSqrt2).Expand(0.02f); DlRect test = cull.Scale(impeller::kSqrt2).Expand(0.02f);
EXPECT_TRUE(state.oval_covers_cull(test)); auto test_oval = [&state](const DlRect& test_rect, bool expect) {
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.1f, 0.0f, 0.0f, 0.0f))); EXPECT_EQ(state.oval_covers_cull(test_rect), expect) << test_rect;
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.1f, 0.0f, 0.0f))); EXPECT_EQ(DisplayListMatrixClipState::TransformedOvalCoversBounds(
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.1f, 0.0f))); test_rect, state.matrix(), state.GetDeviceCullCoverage()),
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, 0.1f))); expect)
EXPECT_FALSE(state.oval_covers_cull(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f))); << test_rect;
EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, -0.1f, 0.0f, 0.0f))); };
EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, -0.1f))); test_oval(test, true);
test_oval(test.Expand(0.1f, 0.0f, 0.0f, 0.0f), true);
test_oval(test.Expand(0.0f, 0.1f, 0.0f, 0.0f), true);
test_oval(test.Expand(0.0f, 0.0f, 0.1f, 0.0f), true);
test_oval(test.Expand(0.0f, 0.0f, 0.0f, 0.1f), true);
test_oval(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f), false);
test_oval(test.Expand(0.0f, -0.1f, 0.0f, 0.0f), false);
test_oval(test.Expand(0.0f, 0.0f, -0.1f, 0.0f), false);
test_oval(test.Expand(0.0f, 0.0f, 0.0f, -0.1f), false);
} }
TEST(DisplayListMatrixClipState, OvalCoverageUnderScale) { TEST(DisplayListMatrixClipState, OvalCoverageUnderScale) {
@ -587,15 +634,23 @@ TEST(DisplayListMatrixClipState, OvalCoverageUnderScale) {
// the cull rect under a 2.0 scale. // the cull rect under a 2.0 scale.
DlRect test = cull.Scale(0.5f * impeller::kSqrt2).Expand(0.02f); DlRect test = cull.Scale(0.5f * impeller::kSqrt2).Expand(0.02f);
EXPECT_TRUE(state.oval_covers_cull(test)); auto test_oval = [&state](const DlRect& test_rect, bool expect) {
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.1f, 0.0f, 0.0f, 0.0f))); EXPECT_EQ(state.oval_covers_cull(test_rect), expect) << test_rect;
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.1f, 0.0f, 0.0f))); EXPECT_EQ(DisplayListMatrixClipState::TransformedOvalCoversBounds(
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.1f, 0.0f))); test_rect, state.matrix(), state.GetDeviceCullCoverage()),
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, 0.1f))); expect)
EXPECT_FALSE(state.oval_covers_cull(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f))); << test_rect;
EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, -0.1f, 0.0f, 0.0f))); };
EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, -0.1f, 0.0f)));
EXPECT_FALSE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, -0.1f))); test_oval(test, true);
test_oval(test.Expand(0.1f, 0.0f, 0.0f, 0.0f), true);
test_oval(test.Expand(0.0f, 0.1f, 0.0f, 0.0f), true);
test_oval(test.Expand(0.0f, 0.0f, 0.1f, 0.0f), true);
test_oval(test.Expand(0.0f, 0.0f, 0.0f, 0.1f), true);
test_oval(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f), false);
test_oval(test.Expand(0.0f, -0.1f, 0.0f, 0.0f), false);
test_oval(test.Expand(0.0f, 0.0f, -0.1f, 0.0f), false);
test_oval(test.Expand(0.0f, 0.0f, 0.0f, -0.1f), false);
} }
TEST(DisplayListMatrixClipState, OvalCoverageUnderRotation) { TEST(DisplayListMatrixClipState, OvalCoverageUnderRotation) {
@ -620,6 +675,17 @@ TEST(DisplayListMatrixClipState, OvalCoverageUnderRotation) {
<< " testing " << test_false << std::endl << " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl << " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees"; << " at " << i << " degrees";
EXPECT_TRUE(DisplayListMatrixClipState::TransformedOvalCoversBounds(
test_true, DlMatrix::MakeRotationZ(DlDegrees(i)), cull))
<< " testing " << test_true << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees";
EXPECT_FALSE(DisplayListMatrixClipState::TransformedOvalCoversBounds(
test_false, DlMatrix::MakeRotationZ(DlDegrees(i)), cull))
<< " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " at " << i << " degrees";
} }
} }
@ -632,13 +698,21 @@ TEST(DisplayListMatrixClipState, RRectCoverage) {
// RRect of cull with no corners covers // RRect of cull with no corners covers
EXPECT_TRUE( EXPECT_TRUE(
state.rrect_covers_cull(DlRoundRect::MakeRectXY(cull, 0.0f, 0.0f))); state.rrect_covers_cull(DlRoundRect::MakeRectXY(cull, 0.0f, 0.0f)));
EXPECT_TRUE(DisplayListMatrixClipState::TransformedRRectCoversBounds(
DlRoundRect::MakeRectXY(cull, 0.0f, 0.0f), DlMatrix(), cull));
// RRect of cull with even the tiniest corners does not cover // RRect of cull with even the tiniest corners does not cover
EXPECT_FALSE( EXPECT_FALSE(
state.rrect_covers_cull(DlRoundRect::MakeRectXY(cull, 0.01f, 0.01f))); state.rrect_covers_cull(DlRoundRect::MakeRectXY(cull, 0.01f, 0.01f)));
EXPECT_FALSE(DisplayListMatrixClipState::TransformedRRectCoversBounds(
DlRoundRect::MakeRectXY(cull, 0.01f, 0.01f), DlMatrix(), cull));
// Expanded by 2.0 and then with a corner of 2.0 obviously still covers // Expanded by 2.0 and then with a corner of 2.0 obviously still covers
EXPECT_TRUE( EXPECT_TRUE(
state.rrect_covers_cull(DlRoundRect::MakeRectXY(test, 2.0f, 2.0f))); state.rrect_covers_cull(DlRoundRect::MakeRectXY(test, 2.0f, 2.0f)));
EXPECT_TRUE(DisplayListMatrixClipState::TransformedRRectCoversBounds(
DlRoundRect::MakeRectXY(test, 2.0f, 2.0f), DlMatrix(), cull));
// The corner point of the cull rect is at (c-2, c-2) relative to the // The corner point of the cull rect is at (c-2, c-2) relative to the
// corner of the rrect bounds so we compute its distance to the center // corner of the rrect bounds so we compute its distance to the center
// of the circular part and compare it to the radius of the corner (c) // of the circular part and compare it to the radius of the corner (c)
@ -663,9 +737,14 @@ TEST(DisplayListMatrixClipState, RRectCoverage) {
// corners set to 6.82 should still cover the cull rect // corners set to 6.82 should still cover the cull rect
EXPECT_TRUE( EXPECT_TRUE(
state.rrect_covers_cull(DlRoundRect::MakeRectXY(test, 6.82f, 6.82f))); state.rrect_covers_cull(DlRoundRect::MakeRectXY(test, 6.82f, 6.82f)));
EXPECT_TRUE(DisplayListMatrixClipState::TransformedRRectCoversBounds(
DlRoundRect::MakeRectXY(test, 6.82f, 6.82f), DlMatrix(), cull));
// but corners set to 6.83 should not cover the cull rect // but corners set to 6.83 should not cover the cull rect
EXPECT_FALSE( EXPECT_FALSE(
state.rrect_covers_cull(DlRoundRect::MakeRectXY(test, 6.84f, 6.84f))); state.rrect_covers_cull(DlRoundRect::MakeRectXY(test, 6.84f, 6.84f)));
EXPECT_FALSE(DisplayListMatrixClipState::TransformedRRectCoversBounds(
DlRoundRect::MakeRectXY(test, 6.84f, 6.84f), DlMatrix(), cull));
} }
} // namespace testing } // namespace testing

View File

@ -23,10 +23,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithNoMutations) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) { TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix = SkMatrix::Scale(2, 2); DlMatrix matrix = DlMatrix::MakeScale({2, 2, 1});
stack.PushTransform(matrix); stack.PushTransform(matrix);
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack); EmbeddedViewParams params(ToSkMatrix(matrix), SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect(); const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0)); ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0)); ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
@ -36,10 +36,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) { TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix = SkMatrix::Translate(1, 1); DlMatrix matrix = DlMatrix::MakeTranslation({1, 1});
stack.PushTransform(matrix); stack.PushTransform(matrix);
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack); EmbeddedViewParams params(ToSkMatrix(matrix), SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect(); const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 1)); ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 1)); ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 1));
@ -49,11 +49,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) { TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix; DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(90));
matrix.setRotate(90);
stack.PushTransform(matrix); stack.PushTransform(matrix);
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack); EmbeddedViewParams params(ToSkMatrix(matrix), SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect(); const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1)); ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
@ -64,11 +63,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) { TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix; DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(45));
matrix.setRotate(45);
stack.PushTransform(matrix); stack.PushTransform(matrix);
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack); EmbeddedViewParams params(ToSkMatrix(matrix), SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect(); const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -sqrt(2) / 2)); ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -sqrt(2) / 2));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0)); ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
@ -78,14 +76,14 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) {
TEST(EmbeddedViewParams, TEST(EmbeddedViewParams,
GetBoundingRectAfterMutationsWithTranslateScaleAndRotation) { GetBoundingRectAfterMutationsWithTranslateScaleAndRotation) {
SkMatrix matrix = SkMatrix::Translate(2, 2); DlMatrix matrix = DlMatrix::MakeTranslation({2, 2}) *
matrix.preScale(3, 3); DlMatrix::MakeScale({3, 3, 1}) *
matrix.preRotate(90); DlMatrix::MakeRotationZ(DlDegrees(90));
MutatorsStack stack; MutatorsStack stack;
stack.PushTransform(matrix); stack.PushTransform(matrix);
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack); EmbeddedViewParams params(ToSkMatrix(matrix), SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect(); const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1)); ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 2)); ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 2));

View File

@ -58,34 +58,39 @@ bool ExternalViewEmbedder::SupportsDynamicThreadMerging() {
void ExternalViewEmbedder::Teardown() {} void ExternalViewEmbedder::Teardown() {}
void MutatorsStack::PushClipRect(const SkRect& rect) { void MutatorsStack::PushClipRect(const DlRect& rect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rect); std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rect);
vector_.push_back(element); vector_.push_back(element);
} }
void MutatorsStack::PushClipRRect(const SkRRect& rrect) { void MutatorsStack::PushClipRRect(const DlRoundRect& rrect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rrect); std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rrect);
vector_.push_back(element); vector_.push_back(element);
} }
void MutatorsStack::PushClipPath(const SkPath& path) { void MutatorsStack::PushClipRSE(const DlRoundSuperellipse& rrect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rrect);
vector_.push_back(element);
}
void MutatorsStack::PushClipPath(const DlPath& path) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(path); std::shared_ptr<Mutator> element = std::make_shared<Mutator>(path);
vector_.push_back(element); vector_.push_back(element);
} }
void MutatorsStack::PushTransform(const SkMatrix& matrix) { void MutatorsStack::PushTransform(const DlMatrix& matrix) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(matrix); std::shared_ptr<Mutator> element = std::make_shared<Mutator>(matrix);
vector_.push_back(element); vector_.push_back(element);
} }
void MutatorsStack::PushOpacity(const int& alpha) { void MutatorsStack::PushOpacity(const uint8_t& alpha) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(alpha); std::shared_ptr<Mutator> element = std::make_shared<Mutator>(alpha);
vector_.push_back(element); vector_.push_back(element);
} }
void MutatorsStack::PushBackdropFilter( void MutatorsStack::PushBackdropFilter(
const std::shared_ptr<DlImageFilter>& filter, const std::shared_ptr<DlImageFilter>& filter,
const SkRect& filter_rect) { const DlRect& filter_rect) {
std::shared_ptr<Mutator> element = std::shared_ptr<Mutator> element =
std::make_shared<Mutator>(filter, filter_rect); std::make_shared<Mutator>(filter, filter_rect);
vector_.push_back(element); vector_.push_back(element);

View File

@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <variant>
#include <vector> #include <vector>
#include "flutter/display_list/dl_builder.h" #include "flutter/display_list/dl_builder.h"
@ -14,11 +15,6 @@
#include "flutter/flow/surface_frame.h" #include "flutter/flow/surface_frame.h"
#include "flutter/fml/memory/ref_counted.h" #include "flutter/fml/memory/ref_counted.h"
#include "flutter/fml/raster_thread_merger.h" #include "flutter/fml/raster_thread_merger.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkSize.h"
#if IMPELLER_SUPPORTS_RENDERING #if IMPELLER_SUPPORTS_RENDERING
#include "flutter/impeller/display_list/aiks_context.h" // nogncheck #include "flutter/impeller/display_list/aiks_context.h" // nogncheck
@ -34,9 +30,10 @@ class GrDirectContext;
namespace flutter { namespace flutter {
enum MutatorType { enum class MutatorType {
kClipRect, kClipRect,
kClipRRect, kClipRRect,
kClipRSE,
kClipPath, kClipPath,
kTransform, kTransform,
kOpacity, kOpacity,
@ -46,16 +43,14 @@ enum MutatorType {
// Represents an image filter mutation. // Represents an image filter mutation.
// //
// Should be used for image_filter_layer and backdrop_filter_layer. // Should be used for image_filter_layer and backdrop_filter_layer.
// TODO(cyanglaz): Refactor this into a ImageFilterMutator class.
// https://github.com/flutter/flutter/issues/108470
class ImageFilterMutation { class ImageFilterMutation {
public: public:
ImageFilterMutation(std::shared_ptr<DlImageFilter> filter, ImageFilterMutation(std::shared_ptr<DlImageFilter> filter,
const SkRect& filter_rect) const DlRect& filter_rect)
: filter_(std::move(filter)), filter_rect_(filter_rect) {} : filter_(std::move(filter)), filter_rect_(filter_rect) {}
const DlImageFilter& GetFilter() const { return *filter_; } const DlImageFilter& GetFilter() const { return *filter_; }
const SkRect& GetFilterRect() const { return filter_rect_; } const DlRect& GetFilterRect() const { return filter_rect_; }
bool operator==(const ImageFilterMutation& other) const { bool operator==(const ImageFilterMutation& other) const {
return *filter_ == *other.filter_ && filter_rect_ == other.filter_rect_; return *filter_ == *other.filter_ && filter_rect_ == other.filter_rect_;
@ -67,7 +62,7 @@ class ImageFilterMutation {
private: private:
std::shared_ptr<DlImageFilter> filter_; std::shared_ptr<DlImageFilter> filter_;
const SkRect filter_rect_; const DlRect filter_rect_;
}; };
// Stores mutation information like clipping or kTransform. // Stores mutation information like clipping or kTransform.
@ -78,112 +73,65 @@ class ImageFilterMutation {
// clipped. One mutation object must only contain one type of mutation. // clipped. One mutation object must only contain one type of mutation.
class Mutator { class Mutator {
public: public:
Mutator(const Mutator& other) { Mutator(const Mutator& other) : data_(other.data_) {}
type_ = other.type_;
switch (other.type_) {
case kClipRect:
rect_ = other.rect_;
break;
case kClipRRect:
rrect_ = other.rrect_;
break;
case kClipPath:
path_ = new SkPath(*other.path_);
break;
case kTransform:
matrix_ = other.matrix_;
break;
case kOpacity:
alpha_ = other.alpha_;
break;
case kBackdropFilter:
filter_mutation_ = other.filter_mutation_;
break;
default:
break;
}
}
explicit Mutator(const SkRect& rect) : type_(kClipRect), rect_(rect) {} explicit Mutator(const DlRect& rect) : data_(rect) {}
explicit Mutator(const SkRRect& rrect) : type_(kClipRRect), rrect_(rrect) {} explicit Mutator(const DlRoundRect& rrect) : data_(rrect) {}
explicit Mutator(const SkPath& path) explicit Mutator(const DlRoundSuperellipse& rrect) : data_(rrect) {}
: type_(kClipPath), path_(new SkPath(path)) {} explicit Mutator(const DlPath& path) : data_(path) {}
explicit Mutator(const SkMatrix& matrix) explicit Mutator(const DlMatrix& matrix) : data_(matrix) {}
: type_(kTransform), matrix_(matrix) {} explicit Mutator(const uint8_t& alpha) : data_(alpha) {}
explicit Mutator(const int& alpha) : type_(kOpacity), alpha_(alpha) {}
explicit Mutator(const std::shared_ptr<DlImageFilter>& filter,
const SkRect& filter_rect)
: type_(kBackdropFilter),
filter_mutation_(
std::make_shared<ImageFilterMutation>(filter, filter_rect)) {}
explicit Mutator(const DlRect& rect) : Mutator(ToSkRect(rect)) {}
explicit Mutator(const DlRoundRect& rrect) : Mutator(ToSkRRect(rrect)) {}
explicit Mutator(const DlPath& path) : Mutator(path.GetSkPath()) {}
explicit Mutator(const DlMatrix& matrix) : Mutator(ToSkMatrix(matrix)) {}
explicit Mutator(const std::shared_ptr<DlImageFilter>& filter, explicit Mutator(const std::shared_ptr<DlImageFilter>& filter,
const DlRect& filter_rect) const DlRect& filter_rect)
: Mutator(filter, ToSkRect(filter_rect)) {} : data_(ImageFilterMutation(filter, filter_rect)) {}
const MutatorType& GetType() const { return type_; } MutatorType GetType() const {
const SkRect& GetRect() const { return rect_; } return static_cast<MutatorType>(data_.index());
const SkRRect& GetRRect() const { return rrect_; } }
const SkPath& GetPath() const { return *path_; }
const SkMatrix& GetMatrix() const { return matrix_; } const DlRect& GetRect() const { return std::get<DlRect>(data_); }
const DlRoundRect& GetRRect() const { return std::get<DlRoundRect>(data_); }
const DlRoundSuperellipse& GetRSE() const {
return std::get<DlRoundSuperellipse>(data_);
}
const DlRoundRect GetRSEApproximation() const {
return GetRSE().ToApproximateRoundRect();
}
const DlPath& GetPath() const { return std::get<DlPath>(data_); }
const DlMatrix& GetMatrix() const { return std::get<DlMatrix>(data_); }
const ImageFilterMutation& GetFilterMutation() const { const ImageFilterMutation& GetFilterMutation() const {
return *filter_mutation_; return std::get<ImageFilterMutation>(data_);
} }
const int& GetAlpha() const { return alpha_; } const uint8_t& GetAlpha() const { return std::get<uint8_t>(data_); }
float GetAlphaFloat() const { return (alpha_ / 255.0f); } float GetAlphaFloat() const { return DlColor::toOpacity(GetAlpha()); }
bool operator==(const Mutator& other) const { bool operator==(const Mutator& other) const { return data_ == other.data_; }
if (type_ != other.type_) {
return false;
}
switch (type_) {
case kClipRect:
return rect_ == other.rect_;
case kClipRRect:
return rrect_ == other.rrect_;
case kClipPath:
return *path_ == *other.path_;
case kTransform:
return matrix_ == other.matrix_;
case kOpacity:
return alpha_ == other.alpha_;
case kBackdropFilter:
return *filter_mutation_ == *other.filter_mutation_;
}
return false;
}
bool operator!=(const Mutator& other) const { return !operator==(other); } bool operator!=(const Mutator& other) const { return !operator==(other); }
bool IsClipType() { bool IsClipType() {
return type_ == kClipRect || type_ == kClipRRect || type_ == kClipPath; switch (GetType()) {
case MutatorType::kClipRect:
case MutatorType::kClipPath:
case MutatorType::kClipRRect:
case MutatorType::kClipRSE:
return true;
case MutatorType::kOpacity:
case MutatorType::kTransform:
case MutatorType::kBackdropFilter:
return false;
}
} }
~Mutator() {
if (type_ == kClipPath) {
delete path_;
}
};
private: private:
MutatorType type_; std::variant<DlRect,
DlRoundRect,
// TODO(cyanglaz): Remove union. DlRoundSuperellipse,
// https://github.com/flutter/flutter/issues/108470 DlPath,
union { DlMatrix,
SkRect rect_; uint8_t,
SkRRect rrect_; ImageFilterMutation>
SkMatrix matrix_; data_;
SkPath* path_;
int alpha_;
};
std::shared_ptr<ImageFilterMutation> filter_mutation_;
}; // Mutator }; // Mutator
// A stack of mutators that can be applied to an embedded platform view. // A stack of mutators that can be applied to an embedded platform view.
@ -199,14 +147,15 @@ class MutatorsStack {
public: public:
MutatorsStack() = default; MutatorsStack() = default;
void PushClipRect(const SkRect& rect); void PushClipRect(const DlRect& rect);
void PushClipRRect(const SkRRect& rrect); void PushClipRRect(const DlRoundRect& rrect);
void PushClipPath(const SkPath& path); void PushClipRSE(const DlRoundSuperellipse& rrect);
void PushTransform(const SkMatrix& matrix); void PushClipPath(const DlPath& path);
void PushOpacity(const int& alpha); void PushTransform(const DlMatrix& matrix);
void PushOpacity(const uint8_t& alpha);
// `filter_rect` is in global coordinates. // `filter_rect` is in global coordinates.
void PushBackdropFilter(const std::shared_ptr<DlImageFilter>& filter, void PushBackdropFilter(const std::shared_ptr<DlImageFilter>& filter,
const SkRect& filter_rect); const DlRect& filter_rect);
// Removes the `Mutator` on the top of the stack // Removes the `Mutator` on the top of the stack
// and destroys it. // and destroys it.
@ -306,7 +255,7 @@ class EmbeddedViewParams {
// `filter_rect` is in global coordinates. // `filter_rect` is in global coordinates.
void PushImageFilter(const std::shared_ptr<DlImageFilter>& filter, void PushImageFilter(const std::shared_ptr<DlImageFilter>& filter,
const SkRect& filter_rect) { const SkRect& filter_rect) {
mutators_stack_.PushBackdropFilter(filter, filter_rect); mutators_stack_.PushBackdropFilter(filter, ToDlRect(filter_rect));
} }
bool operator==(const EmbeddedViewParams& other) const { bool operator==(const EmbeddedViewParams& other) const {

View File

@ -93,7 +93,7 @@ TEST_F(ClipRSuperellipseLayerTest, PaintingCulledLayerDies) {
EXPECT_EQ(mock_layer->parent_cull_rect(), DlRect()); EXPECT_EQ(mock_layer->parent_cull_rect(), DlRect());
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(ToApproximateSkRRect(layer_rsuperellipse))})); std::vector({Mutator(layer_rsuperellipse)}));
auto mutator = paint_context().state_stack.save(); auto mutator = paint_context().state_stack.save();
mutator.clipRect(distant_bounds, false); mutator.clipRect(distant_bounds, false);
@ -145,7 +145,7 @@ TEST_F(ClipRSuperellipseLayerTest, ChildOutsideBounds) {
EXPECT_EQ(mock_layer->parent_cull_rect(), clip_cull_rect.value()); EXPECT_EQ(mock_layer->parent_cull_rect(), clip_cull_rect.value());
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(ToApproximateSkRRect(clip_rsuperellipse))})); std::vector({Mutator(clip_rsuperellipse)}));
EXPECT_FALSE(mock_layer->needs_painting(paint_context())); EXPECT_FALSE(mock_layer->needs_painting(paint_context()));
ASSERT_FALSE(layer->needs_painting(paint_context())); ASSERT_FALSE(layer->needs_painting(paint_context()));
@ -182,7 +182,7 @@ TEST_F(ClipRSuperellipseLayerTest, FullyContainedChild) {
EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(ToApproximateSkRRect(layer_rsuperellipse))})); std::vector({Mutator(layer_rsuperellipse)}));
layer->Paint(display_list_paint_context()); layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder; DisplayListBuilder expected_builder;
@ -238,7 +238,7 @@ TEST_F(ClipRSuperellipseLayerTest, PartiallyContainedChild) {
EXPECT_EQ(mock_layer->parent_cull_rect(), clip_cull_rect.value()); EXPECT_EQ(mock_layer->parent_cull_rect(), clip_cull_rect.value());
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(ToApproximateSkRRect(clip_rsuperellipse))})); std::vector({Mutator(clip_rsuperellipse)}));
layer->Paint(display_list_paint_context()); layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder; DisplayListBuilder expected_builder;

View File

@ -246,7 +246,7 @@ class SaveLayerEntry : public LayerStateStack::StateEntry {
class OpacityEntry : public LayerStateStack::StateEntry { class OpacityEntry : public LayerStateStack::StateEntry {
public: public:
OpacityEntry(const DlRect& bounds, OpacityEntry(const DlRect& bounds,
SkScalar opacity, DlScalar opacity,
const LayerStateStack::RenderingAttributes& prev) const LayerStateStack::RenderingAttributes& prev)
: bounds_(bounds), : bounds_(bounds),
opacity_(opacity), opacity_(opacity),
@ -376,18 +376,17 @@ class BackdropFilterEntry : public SaveLayerEntry {
class TranslateEntry : public LayerStateStack::StateEntry { class TranslateEntry : public LayerStateStack::StateEntry {
public: public:
TranslateEntry(SkScalar tx, SkScalar ty) : tx_(tx), ty_(ty) {} TranslateEntry(DlScalar tx, DlScalar ty) : translation_(tx, ty) {}
void apply(LayerStateStack* stack) const override { void apply(LayerStateStack* stack) const override {
stack->delegate_->translate(tx_, ty_); stack->delegate_->translate(translation_.x, translation_.y);
} }
void update_mutators(MutatorsStack* mutators_stack) const override { void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushTransform(SkMatrix::Translate(tx_, ty_)); mutators_stack->PushTransform(DlMatrix::MakeTranslation(translation_));
} }
private: private:
const SkScalar tx_; const DlPoint translation_;
const SkScalar ty_;
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TranslateEntry); FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TranslateEntry);
}; };
@ -400,7 +399,7 @@ class TransformMatrixEntry : public LayerStateStack::StateEntry {
stack->delegate_->transform(matrix_); stack->delegate_->transform(matrix_);
} }
void update_mutators(MutatorsStack* mutators_stack) const override { void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushTransform(ToSkMatrix(matrix_)); mutators_stack->PushTransform(matrix_);
} }
private: private:
@ -430,7 +429,7 @@ class ClipRectEntry : public LayerStateStack::StateEntry {
stack->delegate_->clipRect(clip_rect_, DlClipOp::kIntersect, is_aa_); stack->delegate_->clipRect(clip_rect_, DlClipOp::kIntersect, is_aa_);
} }
void update_mutators(MutatorsStack* mutators_stack) const override { void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushClipRect(ToSkRect(clip_rect_)); mutators_stack->PushClipRect(clip_rect_);
} }
private: private:
@ -449,7 +448,7 @@ class ClipRRectEntry : public LayerStateStack::StateEntry {
stack->delegate_->clipRRect(clip_rrect_, DlClipOp::kIntersect, is_aa_); stack->delegate_->clipRRect(clip_rrect_, DlClipOp::kIntersect, is_aa_);
} }
void update_mutators(MutatorsStack* mutators_stack) const override { void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushClipRRect(ToSkRRect(clip_rrect_)); mutators_stack->PushClipRRect(clip_rrect_);
} }
private: private:
@ -470,13 +469,7 @@ class ClipRSuperellipseEntry : public LayerStateStack::StateEntry {
DlClipOp::kIntersect, is_aa_); DlClipOp::kIntersect, is_aa_);
} }
void update_mutators(MutatorsStack* mutators_stack) const override { void update_mutators(MutatorsStack* mutators_stack) const override {
// MutatorsStack doesn't support non-Skia classes, and therefore this method mutators_stack->PushClipRSE(clip_rsuperellipse_);
// has to use approximate RRect, which might cause trouble for certain
// embedded apps.
// TODO(dkwingsmt): Make this method push a correct ClipRoundedSuperellipse
// mutator.
// https://github.com/flutter/flutter/issues/163716
mutators_stack->PushClipRRect(ToApproximateSkRRect(clip_rsuperellipse_));
} }
private: private:
@ -496,7 +489,7 @@ class ClipPathEntry : public LayerStateStack::StateEntry {
stack->delegate_->clipPath(clip_path_, DlClipOp::kIntersect, is_aa_); stack->delegate_->clipPath(clip_path_, DlClipOp::kIntersect, is_aa_);
} }
void update_mutators(MutatorsStack* mutators_stack) const override { void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushClipPath(clip_path_.GetSkPath()); mutators_stack->PushClipPath(clip_path_);
} }
private: private:

View File

@ -16,8 +16,8 @@ TEST(MutatorsStack, Initialization) {
TEST(MutatorsStack, CopyConstructor) { TEST(MutatorsStack, CopyConstructor) {
MutatorsStack stack; MutatorsStack stack;
auto rrect = SkRRect::MakeEmpty(); auto rrect = DlRoundRect();
auto rect = SkRect::MakeEmpty(); auto rect = DlRect();
stack.PushClipRect(rect); stack.PushClipRect(rect);
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
MutatorsStack copy = MutatorsStack(stack); MutatorsStack copy = MutatorsStack(stack);
@ -26,8 +26,8 @@ TEST(MutatorsStack, CopyConstructor) {
TEST(MutatorsStack, CopyAndUpdateTheCopy) { TEST(MutatorsStack, CopyAndUpdateTheCopy) {
MutatorsStack stack; MutatorsStack stack;
auto rrect = SkRRect::MakeEmpty(); auto rrect = DlRoundRect();
auto rect = SkRect::MakeEmpty(); auto rect = DlRect();
stack.PushClipRect(rect); stack.PushClipRect(rect);
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
MutatorsStack copy = MutatorsStack(stack); MutatorsStack copy = MutatorsStack(stack);
@ -46,7 +46,7 @@ TEST(MutatorsStack, CopyAndUpdateTheCopy) {
TEST(MutatorsStack, PushClipRect) { TEST(MutatorsStack, PushClipRect) {
MutatorsStack stack; MutatorsStack stack;
auto rect = SkRect::MakeEmpty(); auto rect = DlRect();
stack.PushClipRect(rect); stack.PushClipRect(rect);
auto iter = stack.Bottom(); auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kClipRect); ASSERT_TRUE(iter->get()->GetType() == MutatorType::kClipRect);
@ -55,16 +55,25 @@ TEST(MutatorsStack, PushClipRect) {
TEST(MutatorsStack, PushClipRRect) { TEST(MutatorsStack, PushClipRRect) {
MutatorsStack stack; MutatorsStack stack;
auto rrect = SkRRect::MakeEmpty(); auto rrect = DlRoundRect();
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
auto iter = stack.Bottom(); auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kClipRRect); ASSERT_TRUE(iter->get()->GetType() == MutatorType::kClipRRect);
ASSERT_TRUE(iter->get()->GetRRect() == rrect); ASSERT_TRUE(iter->get()->GetRRect() == rrect);
} }
TEST(MutatorsStack, PushClipRSE) {
MutatorsStack stack;
auto rse = DlRoundSuperellipse();
stack.PushClipRSE(rse);
auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kClipRSE);
ASSERT_TRUE(iter->get()->GetRSE() == rse);
}
TEST(MutatorsStack, PushClipPath) { TEST(MutatorsStack, PushClipPath) {
MutatorsStack stack; MutatorsStack stack;
SkPath path; DlPath path;
stack.PushClipPath(path); stack.PushClipPath(path);
auto iter = stack.Bottom(); auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == flutter::MutatorType::kClipPath); ASSERT_TRUE(iter->get()->GetType() == flutter::MutatorType::kClipPath);
@ -73,8 +82,7 @@ TEST(MutatorsStack, PushClipPath) {
TEST(MutatorsStack, PushTransform) { TEST(MutatorsStack, PushTransform) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix; DlMatrix matrix;
matrix.setIdentity();
stack.PushTransform(matrix); stack.PushTransform(matrix);
auto iter = stack.Bottom(); auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kTransform); ASSERT_TRUE(iter->get()->GetType() == MutatorType::kTransform);
@ -83,7 +91,7 @@ TEST(MutatorsStack, PushTransform) {
TEST(MutatorsStack, PushOpacity) { TEST(MutatorsStack, PushOpacity) {
MutatorsStack stack; MutatorsStack stack;
int alpha = 240; uint8_t alpha = 240;
stack.PushOpacity(alpha); stack.PushOpacity(alpha);
auto iter = stack.Bottom(); auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kOpacity); ASSERT_TRUE(iter->get()->GetType() == MutatorType::kOpacity);
@ -95,7 +103,7 @@ TEST(MutatorsStack, PushBackdropFilter) {
const int num_of_mutators = 10; const int num_of_mutators = 10;
for (int i = 0; i < num_of_mutators; i++) { for (int i = 0; i < num_of_mutators; i++) {
auto filter = DlImageFilter::MakeBlur(i, 5, DlTileMode::kClamp); auto filter = DlImageFilter::MakeBlur(i, 5, DlTileMode::kClamp);
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(i, i, i, i)); stack.PushBackdropFilter(filter, DlRect::MakeXYWH(i, i, i, i));
} }
auto iter = stack.Begin(); auto iter = stack.Begin();
@ -104,10 +112,10 @@ TEST(MutatorsStack, PushBackdropFilter) {
ASSERT_EQ(iter->get()->GetType(), MutatorType::kBackdropFilter); ASSERT_EQ(iter->get()->GetType(), MutatorType::kBackdropFilter);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilter().asBlur()->sigma_x(), ASSERT_EQ(iter->get()->GetFilterMutation().GetFilter().asBlur()->sigma_x(),
i); i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().x(), i); ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetX(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().x(), i); ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetY(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().width(), i); ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetWidth(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().height(), i); ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetHeight(), i);
++iter; ++iter;
++i; ++i;
} }
@ -116,8 +124,7 @@ TEST(MutatorsStack, PushBackdropFilter) {
TEST(MutatorsStack, Pop) { TEST(MutatorsStack, Pop) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix; DlMatrix matrix;
matrix.setIdentity();
stack.PushTransform(matrix); stack.PushTransform(matrix);
stack.Pop(); stack.Pop();
auto iter = stack.Bottom(); auto iter = stack.Bottom();
@ -126,12 +133,11 @@ TEST(MutatorsStack, Pop) {
TEST(MutatorsStack, Traversal) { TEST(MutatorsStack, Traversal) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix; DlMatrix matrix;
matrix.setIdentity();
stack.PushTransform(matrix); stack.PushTransform(matrix);
auto rect = SkRect::MakeEmpty(); auto rect = DlRect();
stack.PushClipRect(rect); stack.PushClipRect(rect);
auto rrect = SkRRect::MakeEmpty(); auto rrect = DlRoundRect();
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
auto iter = stack.Bottom(); auto iter = stack.Bottom();
int index = 0; int index = 0;
@ -159,153 +165,165 @@ TEST(MutatorsStack, Traversal) {
TEST(MutatorsStack, Equality) { TEST(MutatorsStack, Equality) {
MutatorsStack stack; MutatorsStack stack;
SkMatrix matrix = SkMatrix::Scale(1, 1); DlMatrix matrix = DlMatrix::MakeScale({1, 1, 1});
stack.PushTransform(matrix); stack.PushTransform(matrix);
SkRect rect = SkRect::MakeEmpty(); DlRect rect = DlRect();
stack.PushClipRect(rect); stack.PushClipRect(rect);
SkRRect rrect = SkRRect::MakeEmpty(); DlRoundRect rrect = DlRoundRect();
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
SkPath path; DlPath path;
stack.PushClipPath(path); stack.PushClipPath(path);
int alpha = 240; uint8_t alpha = 240;
stack.PushOpacity(alpha); stack.PushOpacity(alpha);
auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp); auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
stack.PushBackdropFilter(filter, SkRect::MakeEmpty()); stack.PushBackdropFilter(filter, DlRect());
MutatorsStack stack_other; MutatorsStack stack_other;
SkMatrix matrix_other = SkMatrix::Scale(1, 1); DlMatrix matrix_other = DlMatrix::MakeScale({1, 1, 1});
stack_other.PushTransform(matrix_other); stack_other.PushTransform(matrix_other);
SkRect rect_other = SkRect::MakeEmpty(); DlRect rect_other = DlRect();
stack_other.PushClipRect(rect_other); stack_other.PushClipRect(rect_other);
SkRRect rrect_other = SkRRect::MakeEmpty(); DlRoundRect rrect_other = DlRoundRect();
stack_other.PushClipRRect(rrect_other); stack_other.PushClipRRect(rrect_other);
SkPath other_path; DlPath other_path;
stack_other.PushClipPath(other_path); stack_other.PushClipPath(other_path);
int other_alpha = 240; uint8_t other_alpha = 240;
stack_other.PushOpacity(other_alpha); stack_other.PushOpacity(other_alpha);
auto other_filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp); auto other_filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
stack_other.PushBackdropFilter(other_filter, SkRect::MakeEmpty()); stack_other.PushBackdropFilter(other_filter, DlRect());
ASSERT_TRUE(stack == stack_other); ASSERT_TRUE(stack == stack_other);
} }
TEST(Mutator, Initialization) { TEST(Mutator, Initialization) {
SkRect rect = SkRect::MakeEmpty(); DlRect rect = DlRect();
Mutator mutator = Mutator(rect); Mutator mutator = Mutator(rect);
ASSERT_TRUE(mutator.GetType() == MutatorType::kClipRect); ASSERT_TRUE(mutator.GetType() == MutatorType::kClipRect);
ASSERT_TRUE(mutator.GetRect() == rect); ASSERT_TRUE(mutator.GetRect() == rect);
SkRRect rrect = SkRRect::MakeEmpty(); DlRoundRect rrect = DlRoundRect();
Mutator mutator2 = Mutator(rrect); Mutator mutator2 = Mutator(rrect);
ASSERT_TRUE(mutator2.GetType() == MutatorType::kClipRRect); ASSERT_TRUE(mutator2.GetType() == MutatorType::kClipRRect);
ASSERT_TRUE(mutator2.GetRRect() == rrect); ASSERT_TRUE(mutator2.GetRRect() == rrect);
SkPath path; DlRoundSuperellipse rse = DlRoundSuperellipse();
Mutator mutator2se = Mutator(rse);
ASSERT_TRUE(mutator2se.GetType() == MutatorType::kClipRSE);
ASSERT_TRUE(mutator2se.GetRSE() == rse);
DlPath path;
Mutator mutator3 = Mutator(path); Mutator mutator3 = Mutator(path);
ASSERT_TRUE(mutator3.GetType() == MutatorType::kClipPath); ASSERT_TRUE(mutator3.GetType() == MutatorType::kClipPath);
ASSERT_TRUE(mutator3.GetPath() == path); ASSERT_TRUE(mutator3.GetPath() == path);
SkMatrix matrix; DlMatrix matrix;
matrix.setIdentity();
Mutator mutator4 = Mutator(matrix); Mutator mutator4 = Mutator(matrix);
ASSERT_TRUE(mutator4.GetType() == MutatorType::kTransform); ASSERT_TRUE(mutator4.GetType() == MutatorType::kTransform);
ASSERT_TRUE(mutator4.GetMatrix() == matrix); ASSERT_TRUE(mutator4.GetMatrix() == matrix);
int alpha = 240; uint8_t alpha = 240;
Mutator mutator5 = Mutator(alpha); Mutator mutator5 = Mutator(alpha);
ASSERT_TRUE(mutator5.GetType() == MutatorType::kOpacity); ASSERT_TRUE(mutator5.GetType() == MutatorType::kOpacity);
auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp); auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter, SkRect::MakeEmpty()); Mutator mutator6 = Mutator(filter, DlRect());
ASSERT_TRUE(mutator6.GetType() == MutatorType::kBackdropFilter); ASSERT_TRUE(mutator6.GetType() == MutatorType::kBackdropFilter);
ASSERT_TRUE(mutator6.GetFilterMutation().GetFilter() == *filter); ASSERT_TRUE(mutator6.GetFilterMutation().GetFilter() == *filter);
} }
TEST(Mutator, CopyConstructor) { TEST(Mutator, CopyConstructor) {
SkRect rect = SkRect::MakeEmpty(); DlRect rect = DlRect();
Mutator mutator = Mutator(rect); Mutator mutator = Mutator(rect);
Mutator copy = Mutator(mutator); Mutator copy = Mutator(mutator);
ASSERT_TRUE(mutator == copy); ASSERT_TRUE(mutator == copy);
SkRRect rrect = SkRRect::MakeEmpty(); DlRoundRect rrect = DlRoundRect();
Mutator mutator2 = Mutator(rrect); Mutator mutator2 = Mutator(rrect);
Mutator copy2 = Mutator(mutator2); Mutator copy2 = Mutator(mutator2);
ASSERT_TRUE(mutator2 == copy2); ASSERT_TRUE(mutator2 == copy2);
SkPath path; DlRoundSuperellipse rse = DlRoundSuperellipse();
Mutator mutator2se = Mutator(rse);
Mutator copy2se = Mutator(mutator2se);
ASSERT_TRUE(mutator2se == copy2se);
DlPath path;
Mutator mutator3 = Mutator(path); Mutator mutator3 = Mutator(path);
Mutator copy3 = Mutator(mutator3); Mutator copy3 = Mutator(mutator3);
ASSERT_TRUE(mutator3 == copy3); ASSERT_TRUE(mutator3 == copy3);
SkMatrix matrix; DlMatrix matrix;
matrix.setIdentity();
Mutator mutator4 = Mutator(matrix); Mutator mutator4 = Mutator(matrix);
Mutator copy4 = Mutator(mutator4); Mutator copy4 = Mutator(mutator4);
ASSERT_TRUE(mutator4 == copy4); ASSERT_TRUE(mutator4 == copy4);
int alpha = 240; uint8_t alpha = 240;
Mutator mutator5 = Mutator(alpha); Mutator mutator5 = Mutator(alpha);
Mutator copy5 = Mutator(mutator5); Mutator copy5 = Mutator(mutator5);
ASSERT_TRUE(mutator5 == copy5); ASSERT_TRUE(mutator5 == copy5);
auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp); auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter, SkRect::MakeEmpty()); Mutator mutator6 = Mutator(filter, DlRect());
Mutator copy6 = Mutator(mutator6); Mutator copy6 = Mutator(mutator6);
ASSERT_TRUE(mutator6 == copy6); ASSERT_TRUE(mutator6 == copy6);
} }
TEST(Mutator, Equality) { TEST(Mutator, Equality) {
SkMatrix matrix; DlMatrix matrix;
matrix.setIdentity();
Mutator mutator = Mutator(matrix); Mutator mutator = Mutator(matrix);
Mutator other_mutator = Mutator(matrix); Mutator other_mutator = Mutator(matrix);
ASSERT_TRUE(mutator == other_mutator); ASSERT_TRUE(mutator == other_mutator);
SkRect rect = SkRect::MakeEmpty(); DlRect rect = DlRect();
Mutator mutator2 = Mutator(rect); Mutator mutator2 = Mutator(rect);
Mutator other_mutator2 = Mutator(rect); Mutator other_mutator2 = Mutator(rect);
ASSERT_TRUE(mutator2 == other_mutator2); ASSERT_TRUE(mutator2 == other_mutator2);
SkRRect rrect = SkRRect::MakeEmpty(); DlRoundRect rrect = DlRoundRect();
Mutator mutator3 = Mutator(rrect); Mutator mutator3 = Mutator(rrect);
Mutator other_mutator3 = Mutator(rrect); Mutator other_mutator3 = Mutator(rrect);
ASSERT_TRUE(mutator3 == other_mutator3); ASSERT_TRUE(mutator3 == other_mutator3);
SkPath path; DlRoundSuperellipse rse = DlRoundSuperellipse();
Mutator mutator3se = Mutator(rse);
Mutator other_mutator3se = Mutator(rse);
ASSERT_TRUE(mutator3se == other_mutator3se);
DlPath path;
flutter::Mutator mutator4 = flutter::Mutator(path); flutter::Mutator mutator4 = flutter::Mutator(path);
flutter::Mutator other_mutator4 = flutter::Mutator(path); flutter::Mutator other_mutator4 = flutter::Mutator(path);
ASSERT_TRUE(mutator4 == other_mutator4); ASSERT_TRUE(mutator4 == other_mutator4);
ASSERT_FALSE(mutator2 == mutator); ASSERT_FALSE(mutator2 == mutator);
int alpha = 240;
uint8_t alpha = 240;
Mutator mutator5 = Mutator(alpha); Mutator mutator5 = Mutator(alpha);
Mutator other_mutator5 = Mutator(alpha); Mutator other_mutator5 = Mutator(alpha);
ASSERT_TRUE(mutator5 == other_mutator5); ASSERT_TRUE(mutator5 == other_mutator5);
auto filter1 = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp); auto filter1 = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
auto filter2 = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp); auto filter2 = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter1, SkRect::MakeEmpty()); Mutator mutator6 = Mutator(filter1, DlRect());
Mutator other_mutator6 = Mutator(filter2, SkRect::MakeEmpty()); Mutator other_mutator6 = Mutator(filter2, DlRect());
ASSERT_TRUE(mutator6 == other_mutator6); ASSERT_TRUE(mutator6 == other_mutator6);
} }
TEST(Mutator, UnEquality) { TEST(Mutator, UnEquality) {
SkRect rect = SkRect::MakeEmpty(); DlRect rect = DlRect();
Mutator mutator = Mutator(rect); Mutator mutator = Mutator(rect);
SkMatrix matrix; DlMatrix matrix;
matrix.setIdentity();
Mutator not_equal_mutator = Mutator(matrix); Mutator not_equal_mutator = Mutator(matrix);
ASSERT_TRUE(not_equal_mutator != mutator); ASSERT_TRUE(not_equal_mutator != mutator);
int alpha = 240; uint8_t alpha = 240;
int alpha2 = 241; uint8_t alpha2 = 241;
Mutator mutator2 = Mutator(alpha); Mutator mutator2 = Mutator(alpha);
Mutator other_mutator2 = Mutator(alpha2); Mutator other_mutator2 = Mutator(alpha2);
ASSERT_TRUE(mutator2 != other_mutator2); ASSERT_TRUE(mutator2 != other_mutator2);
auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp); auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
auto filter2 = DlImageFilter::MakeBlur(10, 10, DlTileMode::kClamp); auto filter2 = DlImageFilter::MakeBlur(10, 10, DlTileMode::kClamp);
Mutator mutator3 = Mutator(filter, SkRect::MakeEmpty()); Mutator mutator3 = Mutator(filter, DlRect());
Mutator other_mutator3 = Mutator(filter2, SkRect::MakeEmpty()); Mutator other_mutator3 = Mutator(filter2, DlRect());
ASSERT_TRUE(mutator3 != other_mutator3); ASSERT_TRUE(mutator3 != other_mutator3);
} }

View File

@ -53,8 +53,7 @@ TEST_F(MockLayerTest, SimpleParams) {
EXPECT_EQ(preroll_context()->has_platform_view, false); EXPECT_EQ(preroll_context()->has_platform_view, false);
EXPECT_EQ(layer->paint_bounds(), path.GetBounds()); EXPECT_EQ(layer->paint_bounds(), path.GetBounds());
EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(layer->parent_mutators(), EXPECT_EQ(layer->parent_mutators(), std::vector{Mutator(scale_matrix)});
std::vector{Mutator(ToSkMatrix(scale_matrix))});
EXPECT_EQ(layer->parent_matrix(), combined_matrix); EXPECT_EQ(layer->parent_matrix(), combined_matrix);
EXPECT_EQ(layer->parent_cull_rect(), local_cull_rect); EXPECT_EQ(layer->parent_cull_rect(), local_cull_rect);
EXPECT_EQ(layer->parent_has_platform_view(), parent_has_platform_view); EXPECT_EQ(layer->parent_has_platform_view(), parent_has_platform_view);

View File

@ -1016,7 +1016,7 @@ TEST_F(ShellTest, PushBackdropFilterToVisitedPlatformViews) {
// Make sure the filterRect is in global coordinates (contains the (1,1) // Make sure the filterRect is in global coordinates (contains the (1,1)
// translation). // translation).
ASSERT_EQ(mutator->GetFilterMutation().GetFilterRect(), ASSERT_EQ(mutator->GetFilterMutation().GetFilterRect(),
SkRect::MakeLTRB(1, 1, 31, 31)); DlRect::MakeLTRB(1, 1, 31, 31));
DestroyShell(std::move(shell)); DestroyShell(std::move(shell));
#endif // OS_FUCHSIA #endif // OS_FUCHSIA

View File

@ -340,17 +340,15 @@ TEST(AndroidExternalViewEmbedder, SubmitFlutterView) {
// Add an Android view. // Add an Android view.
MutatorsStack stack1; MutatorsStack stack1;
SkMatrix matrix1; DlMatrix scale = DlMatrix::MakeScale({1.5, 1.5, 1});
matrix1.setIdentity(); DlMatrix trans = DlMatrix::MakeTranslation({100, 100});
SkMatrix scale = SkMatrix::Scale(1.5, 1.5); DlMatrix matrix1 = scale * trans;
SkMatrix trans = SkMatrix::Translate(100, 100);
matrix1.setConcat(scale, trans);
stack1.PushTransform(scale); stack1.PushTransform(scale);
stack1.PushTransform(trans); stack1.PushTransform(trans);
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to // TODO(egarciad): Investigate why Flow applies the device pixel ratio to
// the offsetPixels, but not the sizePoints. // the offsetPixels, but not the sizePoints.
auto view_params_1 = std::make_unique<EmbeddedViewParams>( auto view_params_1 = std::make_unique<EmbeddedViewParams>(
matrix1, SkSize::Make(200, 200), stack1); ToSkMatrix(matrix1), SkSize::Make(200, 200), stack1);
embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1)); embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
// This is the recording canvas flow writes to. // This is the recording canvas flow writes to.
@ -411,17 +409,15 @@ TEST(AndroidExternalViewEmbedder, SubmitFlutterView) {
// Add an Android view. // Add an Android view.
MutatorsStack stack1; MutatorsStack stack1;
SkMatrix matrix1; DlMatrix scale = DlMatrix::MakeScale({1.5, 1.5, 1});
matrix1.setIdentity(); DlMatrix trans = DlMatrix::MakeTranslation({100, 100});
SkMatrix scale = SkMatrix::Scale(1.5, 1.5); DlMatrix matrix1 = scale * trans;
SkMatrix trans = SkMatrix::Translate(100, 100);
matrix1.setConcat(scale, trans);
stack1.PushTransform(scale); stack1.PushTransform(scale);
stack1.PushTransform(trans); stack1.PushTransform(trans);
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to // TODO(egarciad): Investigate why Flow applies the device pixel ratio to
// the offsetPixels, but not the sizePoints. // the offsetPixels, but not the sizePoints.
auto view_params_1 = std::make_unique<EmbeddedViewParams>( auto view_params_1 = std::make_unique<EmbeddedViewParams>(
matrix1, SkSize::Make(200, 200), stack1); ToSkMatrix(matrix1), SkSize::Make(200, 200), stack1);
embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1)); embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
// This is the recording canvas flow writes to. // This is the recording canvas flow writes to.
@ -623,7 +619,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) {
// Add first Android view. // Add first Android view.
SkMatrix matrix; SkMatrix matrix;
MutatorsStack stack; MutatorsStack stack;
stack.PushTransform(SkMatrix::Translate(0, 0)); stack.PushTransform(DlMatrix::MakeTranslation({0, 0}));
embedder->PrerollCompositeEmbeddedView( embedder->PrerollCompositeEmbeddedView(
0, std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(200, 200), 0, std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(200, 200),
@ -644,7 +640,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) {
// Add second Android view. // Add second Android view.
SkMatrix matrix; SkMatrix matrix;
MutatorsStack stack; MutatorsStack stack;
stack.PushTransform(SkMatrix::Translate(0, 100)); stack.PushTransform(DlMatrix::MakeTranslation({0, 100}));
embedder->PrerollCompositeEmbeddedView( embedder->PrerollCompositeEmbeddedView(
1, std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(100, 100), 1, std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(100, 100),
@ -730,7 +726,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) {
// Add Android view. // Add Android view.
SkMatrix matrix; SkMatrix matrix;
MutatorsStack stack; MutatorsStack stack;
stack.PushTransform(SkMatrix::Translate(0, 0)); stack.PushTransform(DlMatrix::MakeTranslation({0, 0}));
embedder->PrerollCompositeEmbeddedView( embedder->PrerollCompositeEmbeddedView(
0, std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(200, 200), 0, std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(200, 200),

View File

@ -1637,10 +1637,13 @@ void PlatformViewAndroidJNIImpl::FlutterViewOnDisplayPlatformView(
mutators_stack.Begin(); mutators_stack.Begin();
while (iter != mutators_stack.End()) { while (iter != mutators_stack.End()) {
switch ((*iter)->GetType()) { switch ((*iter)->GetType()) {
case kTransform: { case MutatorType::kTransform: {
const SkMatrix& matrix = (*iter)->GetMatrix(); const DlMatrix& matrix = (*iter)->GetMatrix();
SkScalar matrix_array[9]; DlScalar matrix_array[9]{
matrix.get9(matrix_array); matrix.m[0], matrix.m[4], matrix.m[12], //
matrix.m[1], matrix.m[5], matrix.m[13], //
matrix.m[3], matrix.m[7], matrix.m[15],
};
fml::jni::ScopedJavaLocalRef<jfloatArray> transformMatrix( fml::jni::ScopedJavaLocalRef<jfloatArray> transformMatrix(
env, env->NewFloatArray(9)); env, env->NewFloatArray(9));
@ -1650,40 +1653,65 @@ void PlatformViewAndroidJNIImpl::FlutterViewOnDisplayPlatformView(
transformMatrix.obj()); transformMatrix.obj());
break; break;
} }
case kClipRect: { case MutatorType::kClipRect: {
const SkRect& rect = (*iter)->GetRect(); const DlRect& rect = (*iter)->GetRect();
env->CallVoidMethod( env->CallVoidMethod(mutatorsStack,
mutatorsStack, g_mutators_stack_push_cliprect_method, g_mutators_stack_push_cliprect_method,
static_cast<int>(rect.left()), static_cast<int>(rect.top()), static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.right()), static_cast<int>(rect.bottom())); static_cast<int>(rect.GetTop()), //
static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()));
break; break;
} }
case kClipRRect: { case MutatorType::kClipRRect: {
const SkRRect& rrect = (*iter)->GetRRect(); const DlRoundRect& rrect = (*iter)->GetRRect();
const SkRect& rect = rrect.rect(); const DlRect& rect = rrect.GetBounds();
const SkVector& upper_left = rrect.radii(SkRRect::kUpperLeft_Corner); const DlRoundingRadii radii = rrect.GetRadii();
const SkVector& upper_right = rrect.radii(SkRRect::kUpperRight_Corner);
const SkVector& lower_right = rrect.radii(SkRRect::kLowerRight_Corner);
const SkVector& lower_left = rrect.radii(SkRRect::kLowerLeft_Corner);
SkScalar radiis[8] = { SkScalar radiis[8] = {
upper_left.x(), upper_left.y(), upper_right.x(), upper_right.y(), radii.top_left.width, radii.top_left.height,
lower_right.x(), lower_right.y(), lower_left.x(), lower_left.y(), radii.top_right.width, radii.top_right.height,
radii.bottom_right.width, radii.bottom_right.height,
radii.bottom_left.width, radii.bottom_left.height,
}; };
fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray( fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray(
env, env->NewFloatArray(8)); env, env->NewFloatArray(8));
env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis); env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
env->CallVoidMethod( env->CallVoidMethod(mutatorsStack,
mutatorsStack, g_mutators_stack_push_cliprrect_method, g_mutators_stack_push_cliprrect_method,
static_cast<int>(rect.left()), static_cast<int>(rect.top()), static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.right()), static_cast<int>(rect.bottom()), static_cast<int>(rect.GetTop()), //
radiisArray.obj()); static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()), //
radiisArray.obj());
break;
}
case MutatorType::kClipRSE: {
const DlRoundRect& rrect = (*iter)->GetRSEApproximation();
const DlRect& rect = rrect.GetBounds();
const DlRoundingRadii radii = rrect.GetRadii();
SkScalar radiis[8] = {
radii.top_left.width, radii.top_left.height,
radii.top_right.width, radii.top_right.height,
radii.bottom_right.width, radii.bottom_right.height,
radii.bottom_left.width, radii.bottom_left.height,
};
fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray(
env, env->NewFloatArray(8));
env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
env->CallVoidMethod(mutatorsStack,
g_mutators_stack_push_cliprrect_method,
static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.GetTop()), //
static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()), //
radiisArray.obj());
break; break;
} }
// TODO(cyanglaz): Implement other mutators. // TODO(cyanglaz): Implement other mutators.
// https://github.com/flutter/flutter/issues/58426 // https://github.com/flutter/flutter/issues/58426
case kClipPath: case MutatorType::kClipPath:
case kOpacity: case MutatorType::kOpacity:
case kBackdropFilter: case MutatorType::kBackdropFilter:
break; break;
} }
++iter; ++iter;
@ -2017,10 +2045,13 @@ void PlatformViewAndroidJNIImpl::onDisplayPlatformView2(
mutators_stack.Begin(); mutators_stack.Begin();
while (iter != mutators_stack.End()) { while (iter != mutators_stack.End()) {
switch ((*iter)->GetType()) { switch ((*iter)->GetType()) {
case kTransform: { case MutatorType::kTransform: {
const SkMatrix& matrix = (*iter)->GetMatrix(); const DlMatrix& matrix = (*iter)->GetMatrix();
SkScalar matrix_array[9]; DlScalar matrix_array[9]{
matrix.get9(matrix_array); matrix.m[0], matrix.m[4], matrix.m[12], //
matrix.m[1], matrix.m[5], matrix.m[13], //
matrix.m[3], matrix.m[7], matrix.m[15],
};
fml::jni::ScopedJavaLocalRef<jfloatArray> transformMatrix( fml::jni::ScopedJavaLocalRef<jfloatArray> transformMatrix(
env, env->NewFloatArray(9)); env, env->NewFloatArray(9));
@ -2030,98 +2061,192 @@ void PlatformViewAndroidJNIImpl::onDisplayPlatformView2(
transformMatrix.obj()); transformMatrix.obj());
break; break;
} }
case kClipRect: { case MutatorType::kClipRect: {
const SkRect& rect = (*iter)->GetRect(); const DlRect& rect = (*iter)->GetRect();
env->CallVoidMethod( env->CallVoidMethod(mutatorsStack,
mutatorsStack, g_mutators_stack_push_cliprect_method, g_mutators_stack_push_cliprect_method,
static_cast<int>(rect.left()), static_cast<int>(rect.top()), static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.right()), static_cast<int>(rect.bottom())); static_cast<int>(rect.GetTop()), //
static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()));
break; break;
} }
case kClipRRect: { case MutatorType::kClipRRect: {
const SkRRect& rrect = (*iter)->GetRRect(); const DlRoundRect& rrect = (*iter)->GetRRect();
const SkRect& rect = rrect.rect(); const DlRect& rect = rrect.GetBounds();
const SkVector& upper_left = rrect.radii(SkRRect::kUpperLeft_Corner); const DlRoundingRadii& radii = rrect.GetRadii();
const SkVector& upper_right = rrect.radii(SkRRect::kUpperRight_Corner);
const SkVector& lower_right = rrect.radii(SkRRect::kLowerRight_Corner);
const SkVector& lower_left = rrect.radii(SkRRect::kLowerLeft_Corner);
SkScalar radiis[8] = { SkScalar radiis[8] = {
upper_left.x(), upper_left.y(), upper_right.x(), upper_right.y(), radii.top_left.width, radii.top_left.height,
lower_right.x(), lower_right.y(), lower_left.x(), lower_left.y(), radii.top_right.width, radii.top_right.height,
radii.bottom_right.width, radii.bottom_right.height,
radii.bottom_left.width, radii.bottom_left.height,
}; };
fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray( fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray(
env, env->NewFloatArray(8)); env, env->NewFloatArray(8));
env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis); env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
env->CallVoidMethod( env->CallVoidMethod(mutatorsStack,
mutatorsStack, g_mutators_stack_push_cliprrect_method, g_mutators_stack_push_cliprrect_method,
static_cast<int>(rect.left()), static_cast<int>(rect.top()), static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.right()), static_cast<int>(rect.bottom()), static_cast<int>(rect.GetTop()), //
radiisArray.obj()); static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()), //
radiisArray.obj());
break; break;
} }
case kOpacity: { case MutatorType::kClipRSE: {
const DlRoundRect& rrect = (*iter)->GetRSEApproximation();
const DlRect& rect = rrect.GetBounds();
const DlRoundingRadii& radii = rrect.GetRadii();
SkScalar radiis[8] = {
radii.top_left.width, radii.top_left.height,
radii.top_right.width, radii.top_right.height,
radii.bottom_right.width, radii.bottom_right.height,
radii.bottom_left.width, radii.bottom_left.height,
};
fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray(
env, env->NewFloatArray(8));
env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
env->CallVoidMethod(mutatorsStack,
g_mutators_stack_push_cliprrect_method,
static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.GetTop()), //
static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()), //
radiisArray.obj());
break;
}
case MutatorType::kOpacity: {
float opacity = (*iter)->GetAlphaFloat(); float opacity = (*iter)->GetAlphaFloat();
env->CallVoidMethod(mutatorsStack, g_mutators_stack_push_opacity_method, env->CallVoidMethod(mutatorsStack, g_mutators_stack_push_opacity_method,
opacity); opacity);
break; break;
} }
// TODO(cyanglaz): Implement other mutators. case MutatorType::kClipPath: {
// https://github.com/flutter/flutter/issues/58426 auto& dlPath = (*iter)->GetPath();
case kClipPath: { // Sometimes a kClipPath mutator is actually housing a simpler
const SkPath& path = (*iter)->GetPath(); // shape. This isn't usually an issue, but the impeller Path version
// of an oval or round rect may be too approximated to really match
// well between the rendering operations (which check for simpler
// shapes) and handing a raw path to the platform. To make things
// match better, we do the same shape reduction checks here as most
// renderers perform (we don't look for a Rect shape, though as
// those match pretty well on their own).
//
// This should eventually be handled at a higher level, as in the
// clip_path_layer.
// See https://github.com/flutter/flutter/issues/164666
std::optional<DlRoundRect> path_rrect;
{
DlRect rect;
if (dlPath.IsOval(&rect)) {
path_rrect = DlRoundRect::MakeOval(rect);
} else {
DlRoundRect rrect;
if (dlPath.IsRoundRect(&rrect)) {
path_rrect = rrect;
}
}
}
if (path_rrect.has_value()) {
const DlRect& rect = path_rrect->GetBounds();
const DlRoundingRadii& radii = path_rrect->GetRadii();
SkScalar radiis[8] = {
radii.top_left.width, radii.top_left.height,
radii.top_right.width, radii.top_right.height,
radii.bottom_right.width, radii.bottom_right.height,
radii.bottom_left.width, radii.bottom_left.height,
};
fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray(
env, env->NewFloatArray(8));
env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
env->CallVoidMethod(mutatorsStack,
g_mutators_stack_push_cliprrect_method,
static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.GetTop()), //
static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()), //
radiisArray.obj());
break;
}
// Define and populate an Android Path with data from the Skia SkPath // Define and populate an Android Path with data from the DlPath
jobject androidPath = jobject androidPath =
env->NewObject(path_class->obj(), path_constructor); env->NewObject(path_class->obj(), path_constructor);
SkPath::Iter pathIter(path, false); bool subpath_needs_close = false;
SkPoint points[4]; std::optional<flutter::DlPoint> pending_moveto;
SkPath::Verb verb;
while ((verb = pathIter.next(points)) != SkPath::kDone_Verb) { auto resolve_moveto = [&env, &pending_moveto, &androidPath]() {
switch (verb) { if (pending_moveto.has_value()) {
case SkPath::kMove_Verb: { env->CallVoidMethod(androidPath, path_move_to_method,
env->CallVoidMethod(androidPath, path_move_to_method, pending_moveto->x, pending_moveto->y);
points[0].fX, points[0].fY); pending_moveto.reset();
}
};
auto& path = dlPath.GetPath();
for (auto it = path.begin(), end = path.end(); it != end; ++it) {
switch (it.type()) {
case impeller::Path::ComponentType::kContour: {
const impeller::ContourComponent* contour = it.contour();
FML_DCHECK(contour != nullptr);
if (subpath_needs_close) {
env->CallVoidMethod(androidPath, path_close_method);
}
pending_moveto = contour->destination;
subpath_needs_close = contour->IsClosed();
break; break;
} }
case SkPath::kLine_Verb: { case impeller::Path::ComponentType::kLinear: {
const impeller::LinearPathComponent* linear = it.linear();
FML_DCHECK(linear != nullptr);
resolve_moveto();
env->CallVoidMethod(androidPath, path_line_to_method, env->CallVoidMethod(androidPath, path_line_to_method,
points[1].fX, points[1].fY); linear->p2.x, linear->p2.y);
break; break;
} }
case SkPath::kQuad_Verb: { case impeller::Path::ComponentType::kQuadratic: {
const impeller::QuadraticPathComponent* quadratic =
it.quadratic();
FML_DCHECK(quadratic != nullptr);
resolve_moveto();
env->CallVoidMethod(androidPath, path_quad_to_method, env->CallVoidMethod(androidPath, path_quad_to_method,
points[1].fX, points[1].fY, points[2].fX, quadratic->cp.x, quadratic->cp.y,
points[2].fY); quadratic->p2.x, quadratic->p2.y);
break; break;
} }
case SkPath::kCubic_Verb: { case impeller::Path::ComponentType::kConic: {
env->CallVoidMethod(androidPath, path_cubic_to_method, const impeller::ConicPathComponent* conic = it.conic();
points[1].fX, points[1].fY, points[2].fX, FML_DCHECK(conic != nullptr);
points[2].fY, points[3].fX, points[3].fY); resolve_moveto();
break;
}
case SkPath::kConic_Verb: {
FML_DCHECK(path_conic_to_method != nullptr); FML_DCHECK(path_conic_to_method != nullptr);
env->CallVoidMethod(androidPath, path_conic_to_method, env->CallVoidMethod(androidPath, path_conic_to_method,
points[1].fX, points[1].fY, points[2].fX, conic->cp.x, conic->cp.y, //
points[2].fY, pathIter.conicWeight()); conic->p2.x, conic->p2.y, conic->weight);
break; break;
} }
case impeller::Path::ComponentType::kCubic: {
case SkPath::kClose_Verb: { const impeller::CubicPathComponent* cubic = it.cubic();
env->CallVoidMethod(androidPath, path_close_method); FML_DCHECK(cubic != nullptr);
resolve_moveto();
env->CallVoidMethod(androidPath, path_cubic_to_method,
cubic->cp1.x, cubic->cp1.y, //
cubic->cp2.x, cubic->cp2.y, //
cubic->p2.x, cubic->p2.y);
break; break;
} }
default:
break;
} }
} }
if (subpath_needs_close) {
env->CallVoidMethod(androidPath, path_close_method);
}
env->CallVoidMethod(mutatorsStack, env->CallVoidMethod(mutatorsStack,
g_mutators_stack_push_clippath_method, androidPath); g_mutators_stack_push_clippath_method, androidPath);
} }
case kBackdropFilter: // TODO(cyanglaz): Implement other mutators.
// https://github.com/flutter/flutter/issues/58426
case MutatorType::kBackdropFilter:
break; break;
} }
++iter; ++iter;

View File

@ -12,26 +12,35 @@
FLUTTER_ASSERT_ARC FLUTTER_ASSERT_ARC
static constexpr int kMaxPointsInVerb = 4;
namespace { namespace {
CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { static CGRect GetCGRectFromDlRect(const flutter::DlRect& clipDlRect) {
return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, return CGRectMake(clipDlRect.GetX(), //
clipSkRect.fBottom - clipSkRect.fTop); clipDlRect.GetY(), //
clipDlRect.GetWidth(), //
clipDlRect.GetHeight());
} }
CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { CATransform3D GetCATransform3DFromDlMatrix(const flutter::DlMatrix& matrix) {
// Skia only supports 2D transform so we don't map z.
CATransform3D transform = CATransform3DIdentity; CATransform3D transform = CATransform3DIdentity;
transform.m11 = matrix.getScaleX(); transform.m11 = matrix.m[0];
transform.m21 = matrix.getSkewX(); transform.m12 = matrix.m[1];
transform.m41 = matrix.getTranslateX(); transform.m13 = matrix.m[2];
transform.m14 = matrix.getPerspX(); transform.m14 = matrix.m[3];
transform.m12 = matrix.getSkewY(); transform.m21 = matrix.m[4];
transform.m22 = matrix.getScaleY(); transform.m22 = matrix.m[5];
transform.m42 = matrix.getTranslateY(); transform.m23 = matrix.m[6];
transform.m24 = matrix.getPerspY(); transform.m24 = matrix.m[7];
transform.m31 = matrix.m[8];
transform.m32 = matrix.m[9];
transform.m33 = matrix.m[10];
transform.m34 = matrix.m[11];
transform.m41 = matrix.m[12];
transform.m42 = matrix.m[13];
transform.m43 = matrix.m[14];
transform.m44 = matrix.m[15];
return transform; return transform;
} }
} // namespace } // namespace
@ -278,12 +287,12 @@ static BOOL _preparedOnce = NO;
} }
} }
- (void)clipRect:(const SkRect&)clipSkRect matrix:(const SkMatrix&)matrix { - (void)clipRect:(const flutter::DlRect&)clipDlRect matrix:(const flutter::DlMatrix&)matrix {
CGRect clipRect = GetCGRectFromSkRect(clipSkRect); CGRect clipRect = GetCGRectFromDlRect(clipDlRect);
CGPathRef path = CGPathCreateWithRect(clipRect, nil); CGPathRef path = CGPathCreateWithRect(clipRect, nil);
// The `matrix` is based on the physical pixels, convert it to UIKit points. // The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints = CATransform3D matrixInPoints =
CATransform3DConcat(GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale); CATransform3DConcat(GetCATransform3DFromDlMatrix(matrix), _reverseScreenScale);
paths_.push_back([self getTransformedPath:path matrix:matrixInPoints]); paths_.push_back([self getTransformedPath:path matrix:matrixInPoints]);
CGAffineTransform affine = [self affineWithMatrix:matrixInPoints]; CGAffineTransform affine = [self affineWithMatrix:matrixInPoints];
// Make sure the rect is not rotated (only translated or scaled). // Make sure the rect is not rotated (only translated or scaled).
@ -294,139 +303,155 @@ static BOOL _preparedOnce = NO;
} }
} }
- (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix { - (void)clipRRect:(const flutter::DlRoundRect&)clipDlRRect matrix:(const flutter::DlMatrix&)matrix {
containsNonRectPath_ = YES; if (clipDlRRect.IsEmpty()) {
CGPathRef pathRef = nullptr; return;
switch (clipSkRRect.getType()) { } else if (clipDlRRect.IsRect()) {
case SkRRect::kEmpty_Type: { [self clipRect:clipDlRRect.GetBounds() matrix:matrix];
break; return;
} } else {
case SkRRect::kRect_Type: { CGPathRef pathRef = nullptr;
[self clipRect:clipSkRRect.rect() matrix:matrix]; containsNonRectPath_ = YES;
return;
} if (clipDlRRect.GetRadii().AreAllCornersSame()) {
case SkRRect::kOval_Type: CGRect clipRect = GetCGRectFromDlRect(clipDlRRect.GetBounds());
case SkRRect::kSimple_Type: { auto radii = clipDlRRect.GetRadii();
CGRect clipRect = GetCGRectFromSkRect(clipSkRRect.rect()); pathRef =
pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(), CGPathCreateWithRoundedRect(clipRect, radii.top_left.width, radii.top_left.height, nil);
clipSkRRect.getSimpleRadii().y(), nil); } else {
break;
}
case SkRRect::kNinePatch_Type:
case SkRRect::kComplex_Type: {
CGMutablePathRef mutablePathRef = CGPathCreateMutable(); CGMutablePathRef mutablePathRef = CGPathCreateMutable();
// Complex types, we manually add each corner. // Complex types, we manually add each corner.
SkRect clipSkRect = clipSkRRect.rect(); flutter::DlRect clipDlRect = clipDlRRect.GetBounds();
SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); auto left = clipDlRect.GetLeft();
SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner); auto top = clipDlRect.GetTop();
SkVector bottomRightRadii = clipSkRRect.radii(SkRRect::kLowerRight_Corner); auto right = clipDlRect.GetRight();
SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner); auto bottom = clipDlRect.GetBottom();
flutter::DlRoundingRadii radii = clipDlRRect.GetRadii();
auto& top_left = radii.top_left;
auto& top_right = radii.top_right;
auto& bottom_left = radii.bottom_left;
auto& bottom_right = radii.bottom_right;
// Start drawing RRect // Start drawing RRect
// These calculations are off, the AddCurve methods add a Bezier curve
// which, for round rects should be a "magic distance" from the end
// point of the horizontal/vertical section to the corner.
// Move point to the top left corner adding the top left radii's x. // Move point to the top left corner adding the top left radii's x.
CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); CGPathMoveToPoint(mutablePathRef, nil, //
left + top_left.width, top);
// Move point horizontally right to the top right corner and add the top right curve. // Move point horizontally right to the top right corner and add the top right curve.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(), CGPathAddLineToPoint(mutablePathRef, nil, //
clipSkRect.fTop); right - top_right.width, top);
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop, CGPathAddCurveToPoint(mutablePathRef, nil, //
clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(), right, top, //
clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y()); right, top + top_right.height, //
right, top + top_right.height);
// Move point vertically down to the bottom right corner and add the bottom right curve. // Move point vertically down to the bottom right corner and add the bottom right curve.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight, CGPathAddLineToPoint(mutablePathRef, nil, //
clipSkRect.fBottom - bottomRightRadii.y()); right, bottom - bottom_right.height);
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom, CGPathAddCurveToPoint(mutablePathRef, nil, //
clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom, right, bottom, //
clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom); right - bottom_right.width, bottom, //
right - bottom_right.width, bottom);
// Move point horizontally left to the bottom left corner and add the bottom left curve. // Move point horizontally left to the bottom left corner and add the bottom left curve.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(), CGPathAddLineToPoint(mutablePathRef, nil, //
clipSkRect.fBottom); left + bottom_left.width, bottom);
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom, CGPathAddCurveToPoint(mutablePathRef, nil, //
clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(), left, bottom, //
clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y()); left, bottom - bottom_left.height, //
left, bottom - bottom_left.height);
// Move point vertically up to the top left corner and add the top left curve. // Move point vertically up to the top left corner and add the top left curve.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, CGPathAddLineToPoint(mutablePathRef, nil, //
clipSkRect.fTop + topLeftRadii.y()); left, top + top_left.height);
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, CGPathAddCurveToPoint(mutablePathRef, nil, //
clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop, left, top, //
clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); left + top_left.width, top, //
left + top_left.width, top);
CGPathCloseSubpath(mutablePathRef); CGPathCloseSubpath(mutablePathRef);
pathRef = mutablePathRef; pathRef = mutablePathRef;
break;
} }
// The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints =
CATransform3DConcat(GetCATransform3DFromDlMatrix(matrix), _reverseScreenScale);
// TODO(cyanglaz): iOS does not seem to support hard edge on CAShapeLayer. It clearly stated
// that the CAShaperLayer will be drawn antialiased. Need to figure out a way to do the hard
// edge clipping on iOS.
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
} }
// The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints =
CATransform3DConcat(GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
// TODO(cyanglaz): iOS does not seem to support hard edge on CAShapeLayer. It clearly stated that
// the CAShaperLayer will be drawn antialiased. Need to figure out a way to do the hard edge
// clipping on iOS.
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
} }
- (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix { - (void)clipPath:(const flutter::DlPath&)dlPath matrix:(const flutter::DlMatrix&)matrix {
if (!path.isValid()) {
return;
}
if (path.isEmpty()) {
return;
}
containsNonRectPath_ = YES; containsNonRectPath_ = YES;
CGMutablePathRef pathRef = CGPathCreateMutable(); CGMutablePathRef pathRef = CGPathCreateMutable();
bool subpath_needs_close = false;
std::optional<flutter::DlPoint> pending_moveto;
// Loop through all verbs and translate them into CGPath auto resolve_moveto = [&pending_moveto, &pathRef]() {
SkPath::Iter iter(path, true); if (pending_moveto.has_value()) {
SkPoint pts[kMaxPointsInVerb]; CGPathMoveToPoint(pathRef, nil, pending_moveto->x, pending_moveto->y);
SkPath::Verb verb = iter.next(pts); pending_moveto.reset();
SkPoint last_pt_from_last_verb = SkPoint::Make(0, 0);
while (verb != SkPath::kDone_Verb) {
if (verb == SkPath::kLine_Verb || verb == SkPath::kQuad_Verb || verb == SkPath::kConic_Verb ||
verb == SkPath::kCubic_Verb) {
FML_DCHECK(last_pt_from_last_verb == pts[0]);
} }
switch (verb) { };
case SkPath::kMove_Verb: {
CGPathMoveToPoint(pathRef, nil, pts[0].x(), pts[0].y()); auto& path = dlPath.GetPath();
last_pt_from_last_verb = pts[0]; for (auto it = path.begin(), end = path.end(); it != end; ++it) {
switch (it.type()) {
case impeller::Path::ComponentType::kContour: {
const impeller::ContourComponent* contour = it.contour();
FML_DCHECK(contour != nullptr);
if (subpath_needs_close) {
CGPathCloseSubpath(pathRef);
}
pending_moveto = contour->destination;
subpath_needs_close = contour->IsClosed();
break; break;
} }
case SkPath::kLine_Verb: { case impeller::Path::ComponentType::kLinear: {
CGPathAddLineToPoint(pathRef, nil, pts[1].x(), pts[1].y()); const impeller::LinearPathComponent* linear = it.linear();
last_pt_from_last_verb = pts[1]; FML_DCHECK(linear != nullptr);
resolve_moveto();
CGPathAddLineToPoint(pathRef, nil, linear->p2.x, linear->p2.y);
break; break;
} }
case SkPath::kQuad_Verb: { case impeller::Path::ComponentType::kQuadratic: {
CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); const impeller::QuadraticPathComponent* quadratic = it.quadratic();
last_pt_from_last_verb = pts[2]; FML_DCHECK(quadratic != nullptr);
resolve_moveto();
CGPathAddQuadCurveToPoint(pathRef, nil, //
quadratic->cp.x, quadratic->cp.y, //
quadratic->p2.x, quadratic->p2.y);
break; break;
} }
case SkPath::kConic_Verb: { case impeller::Path::ComponentType::kConic: {
const impeller::ConicPathComponent* conic = it.conic();
FML_DCHECK(conic != nullptr);
resolve_moveto();
// Conic is not available in quartz, we use quad to approximate. // Conic is not available in quartz, we use quad to approximate.
// TODO(cyanglaz): Better approximate the conic path. // TODO(cyanglaz): Better approximate the conic path.
// https://github.com/flutter/flutter/issues/35062 // https://github.com/flutter/flutter/issues/35062
CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); CGPathAddQuadCurveToPoint(pathRef, nil, //
last_pt_from_last_verb = pts[2]; conic->cp.x, conic->cp.y, //
conic->p2.x, conic->p2.y);
break; break;
} }
case SkPath::kCubic_Verb: { case impeller::Path::ComponentType::kCubic: {
CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), const impeller::CubicPathComponent* cubic = it.cubic();
pts[3].x(), pts[3].y()); FML_DCHECK(cubic != nullptr);
last_pt_from_last_verb = pts[3]; resolve_moveto();
break; CGPathAddCurveToPoint(pathRef, nil, //
} cubic->cp1.x, cubic->cp1.y, //
case SkPath::kClose_Verb: { cubic->cp2.x, cubic->cp2.y, //
CGPathCloseSubpath(pathRef); cubic->p2.x, cubic->p2.y);
break;
}
case SkPath::kDone_Verb: {
break; break;
} }
} }
verb = iter.next(pts); }
if (subpath_needs_close) {
CGPathCloseSubpath(pathRef);
} }
// The `matrix` is based on the physical pixels, convert it to UIKit points. // The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints = CATransform3D matrixInPoints =
CATransform3DConcat(GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale); CATransform3DConcat(GetCATransform3DFromDlMatrix(matrix), _reverseScreenScale);
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]); paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
} }

View File

@ -5,6 +5,7 @@
#import "shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h" #import "shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h"
#include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h" #include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h"
#include "flutter/display_list/utils/dl_matrix_clip_tracker.h"
#include "flutter/flow/surface_frame.h" #include "flutter/flow/surface_frame.h"
#include "flutter/flow/view_slicer.h" #include "flutter/flow/view_slicer.h"
#include "flutter/fml/make_copyable.h" #include "flutter/fml/make_copyable.h"
@ -15,6 +16,10 @@
#include "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h" #include "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h" #import "flutter/shell/platform/darwin/ios/ios_surface.h"
using flutter::DlMatrix;
using flutter::DlRect;
using flutter::DlRoundRect;
static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5; static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5;
struct LayerData { struct LayerData {
@ -38,18 +43,27 @@ struct PlatformViewData {
// Converts a SkMatrix to CATransform3D. // Converts a SkMatrix to CATransform3D.
// //
// Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4. // Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4.
static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { static CATransform3D GetCATransform3DFromDlMatrix(const DlMatrix& matrix) {
// Skia only supports 2D transform so we don't map z.
CATransform3D transform = CATransform3DIdentity; CATransform3D transform = CATransform3DIdentity;
transform.m11 = matrix.getScaleX(); transform.m11 = matrix.m[0];
transform.m21 = matrix.getSkewX(); transform.m12 = matrix.m[1];
transform.m41 = matrix.getTranslateX(); transform.m13 = matrix.m[2];
transform.m14 = matrix.getPerspX(); transform.m14 = matrix.m[3];
transform.m12 = matrix.getSkewY(); transform.m21 = matrix.m[4];
transform.m22 = matrix.getScaleY(); transform.m22 = matrix.m[5];
transform.m42 = matrix.getTranslateY(); transform.m23 = matrix.m[6];
transform.m24 = matrix.getPerspY(); transform.m24 = matrix.m[7];
transform.m31 = matrix.m[8];
transform.m32 = matrix.m[9];
transform.m33 = matrix.m[10];
transform.m34 = matrix.m[11];
transform.m41 = matrix.m[12];
transform.m42 = matrix.m[13];
transform.m43 = matrix.m[14];
transform.m44 = matrix.m[15];
return transform; return transform;
} }
@ -62,57 +76,11 @@ static void ResetAnchor(CALayer* layer) {
layer.position = CGPointZero; layer.position = CGPointZero;
} }
static CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { static CGRect GetCGRectFromDlRect(const DlRect& clipDlRect) {
return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, return CGRectMake(clipDlRect.GetLeft(), //
clipSkRect.fBottom - clipSkRect.fTop); clipDlRect.GetTop(), //
} clipDlRect.GetWidth(), //
clipDlRect.GetHeight());
// Determines if the `clip_rect` from a clipRect mutator contains the
// `platformview_boundingrect`.
//
// `clip_rect` is in its own coordinate space. The rect needs to be transformed by
// `transform_matrix` to be in the coordinate space where the PlatformView is displayed.
//
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate
// space where the PlatformView is displayed.
static bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect,
const SkRect& platformview_boundingrect,
const SkMatrix& transform_matrix) {
SkRect transformed_rect = transform_matrix.mapRect(clip_rect);
return transformed_rect.contains(platformview_boundingrect);
}
// Determines if the `clipRRect` from a clipRRect mutator contains the
// `platformview_boundingrect`.
//
// `clip_rrect` is in its own coordinate space. The rrect needs to be transformed by
// `transform_matrix` to be in the coordinate space where the PlatformView is displayed.
//
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate
// space where the PlatformView is displayed.
static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
const SkRect& platformview_boundingrect,
const SkMatrix& transform_matrix) {
SkVector upper_left = clip_rrect.radii(SkRRect::Corner::kUpperLeft_Corner);
SkVector upper_right = clip_rrect.radii(SkRRect::Corner::kUpperRight_Corner);
SkVector lower_right = clip_rrect.radii(SkRRect::Corner::kLowerRight_Corner);
SkVector lower_left = clip_rrect.radii(SkRRect::Corner::kLowerLeft_Corner);
SkScalar transformed_upper_left_x = transform_matrix.mapRadius(upper_left.x());
SkScalar transformed_upper_left_y = transform_matrix.mapRadius(upper_left.y());
SkScalar transformed_upper_right_x = transform_matrix.mapRadius(upper_right.x());
SkScalar transformed_upper_right_y = transform_matrix.mapRadius(upper_right.y());
SkScalar transformed_lower_right_x = transform_matrix.mapRadius(lower_right.x());
SkScalar transformed_lower_right_y = transform_matrix.mapRadius(lower_right.y());
SkScalar transformed_lower_left_x = transform_matrix.mapRadius(lower_left.x());
SkScalar transformed_lower_left_y = transform_matrix.mapRadius(lower_left.y());
SkRect transformed_clip_rect = transform_matrix.mapRect(clip_rrect.rect());
SkRRect transformed_rrect;
SkVector corners[] = {{transformed_upper_left_x, transformed_upper_left_y},
{transformed_upper_right_x, transformed_upper_right_y},
{transformed_lower_right_x, transformed_lower_right_y},
{transformed_lower_left_x, transformed_lower_left_y}};
transformed_rrect.setRectRadii(transformed_clip_rect, corners);
return transformed_rrect.contains(platformview_boundingrect);
} }
@interface FlutterPlatformViewsController () @interface FlutterPlatformViewsController ()
@ -531,7 +499,8 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
ResetAnchor(embeddedView.layer); ResetAnchor(embeddedView.layer);
ChildClippingView* clipView = (ChildClippingView*)embeddedView.superview; ChildClippingView* clipView = (ChildClippingView*)embeddedView.superview;
SkMatrix transformMatrix; DlMatrix transformMatrix;
const DlRect& dlBoundingRect = flutter::ToDlRect(boundingRect);
NSMutableArray* blurFilters = [[NSMutableArray alloc] init]; NSMutableArray* blurFilters = [[NSMutableArray alloc] init];
FML_DCHECK(!clipView.maskView || FML_DCHECK(!clipView.maskView ||
[clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]); [clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]);
@ -543,13 +512,13 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
auto iter = mutatorsStack.Begin(); auto iter = mutatorsStack.Begin();
while (iter != mutatorsStack.End()) { while (iter != mutatorsStack.End()) {
switch ((*iter)->GetType()) { switch ((*iter)->GetType()) {
case flutter::kTransform: { case flutter::MutatorType::kTransform: {
transformMatrix.preConcat((*iter)->GetMatrix()); transformMatrix = transformMatrix * (*iter)->GetMatrix();
break; break;
} }
case flutter::kClipRect: { case flutter::MutatorType::kClipRect: {
if (ClipRectContainsPlatformViewBoundingRect((*iter)->GetRect(), boundingRect, if (flutter::DisplayListMatrixClipState::TransformedRectCoversBounds(
transformMatrix)) { (*iter)->GetRect(), transformMatrix, dlBoundingRect)) {
break; break;
} }
[self clipViewSetMaskView:clipView]; [self clipViewSetMaskView:clipView];
@ -557,9 +526,9 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
matrix:transformMatrix]; matrix:transformMatrix];
break; break;
} }
case flutter::kClipRRect: { case flutter::MutatorType::kClipRRect: {
if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), boundingRect, if (flutter::DisplayListMatrixClipState::TransformedRRectCoversBounds(
transformMatrix)) { (*iter)->GetRRect(), transformMatrix, dlBoundingRect)) {
break; break;
} }
[self clipViewSetMaskView:clipView]; [self clipViewSetMaskView:clipView];
@ -567,7 +536,17 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
matrix:transformMatrix]; matrix:transformMatrix];
break; break;
} }
case flutter::kClipPath: { case flutter::MutatorType::kClipRSE: {
if (flutter::DisplayListMatrixClipState::TransformedRoundSuperellipseCoversBounds(
(*iter)->GetRSE(), transformMatrix, dlBoundingRect)) {
break;
}
[self clipViewSetMaskView:clipView];
[(FlutterClippingMaskView*)clipView.maskView clipRRect:(*iter)->GetRRect()
matrix:transformMatrix];
break;
}
case flutter::MutatorType::kClipPath: {
// TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning // TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning
// rect. See `ClipRRectContainsPlatformViewBoundingRect`. // rect. See `ClipRRectContainsPlatformViewBoundingRect`.
// https://github.com/flutter/flutter/issues/118650 // https://github.com/flutter/flutter/issues/118650
@ -576,15 +555,15 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
matrix:transformMatrix]; matrix:transformMatrix];
break; break;
} }
case flutter::kOpacity: case flutter::MutatorType::kOpacity:
embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha; embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha;
break; break;
case flutter::kBackdropFilter: { case flutter::MutatorType::kBackdropFilter: {
// Only support DlBlurImageFilter for BackdropFilter. // Only support DlBlurImageFilter for BackdropFilter.
if (!self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) { if (!self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
break; break;
} }
CGRect filterRect = GetCGRectFromSkRect((*iter)->GetFilterMutation().GetFilterRect()); CGRect filterRect = GetCGRectFromDlRect((*iter)->GetFilterMutation().GetFilterRect());
// `filterRect` is in global coordinates. We need to convert to local space. // `filterRect` is in global coordinates. We need to convert to local space.
filterRect = CGRectApplyAffineTransform( filterRect = CGRectApplyAffineTransform(
filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale)); filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale));
@ -626,7 +605,8 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
// However, flow is based on the physical resolution. For example, 1000 pixels in flow equals // However, flow is based on the physical resolution. For example, 1000 pixels in flow equals
// 500 points in UIKit for devices that has screenScale of 2. We need to scale the transformMatrix // 500 points in UIKit for devices that has screenScale of 2. We need to scale the transformMatrix
// down to the logical resoltion before applying it to the layer of PlatformView. // down to the logical resoltion before applying it to the layer of PlatformView.
transformMatrix.postScale(1 / screenScale, 1 / screenScale); flutter::DlScalar pointScale = 1.0 / screenScale;
transformMatrix = DlMatrix::MakeScale({pointScale, pointScale, 1}) * transformMatrix;
// Reverse the offset of the clipView. // Reverse the offset of the clipView.
// The clipView's frame includes the final translate of the final transform matrix. // The clipView's frame includes the final translate of the final transform matrix.
@ -635,9 +615,10 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
// //
// Note that the transforms are not applied to the clipping paths because clipping paths happen on // Note that the transforms are not applied to the clipping paths because clipping paths happen on
// the mask view, whose origin is always (0,0) to the _flutterView. // the mask view, whose origin is always (0,0) to the _flutterView.
transformMatrix.postTranslate(-clipView.frame.origin.x, -clipView.frame.origin.y); impeller::Vector3 origin = impeller::Vector3(clipView.frame.origin.x, clipView.frame.origin.y);
transformMatrix = DlMatrix::MakeTranslation(-origin) * transformMatrix;
embeddedView.layer.transform = GetCATransform3DFromSkMatrix(transformMatrix); embeddedView.layer.transform = GetCATransform3DFromDlMatrix(transformMatrix);
} }
- (void)compositeView:(int64_t)viewId withParams:(const flutter::EmbeddedViewParams&)params { - (void)compositeView:(int64_t)viewId withParams:(const flutter::EmbeddedViewParams&)params {

View File

@ -354,17 +354,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a translate matrix // Push a translate matrix
SkMatrix translateMatrix = SkMatrix::Translate(100, 100); flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
stack.PushTransform(translateMatrix); stack.PushTransform(translateMatrix);
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
finalMatrix.setConcat(screenScaleMatrix, translateMatrix);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -514,15 +513,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a backdrop filter // Push a backdrop filter
auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp); auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -598,15 +598,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a backdrop filter // Push a backdrop filter
auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp); auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 8, screenScale * 8)); stack.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 8, screenScale * 8));
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(5, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(5, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -682,17 +683,18 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push backdrop filters // Push backdrop filters
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
auto filter = flutter::DlBlurImageFilter::Make(i, 2, flutter::DlTileMode::kClamp); auto filter = flutter::DlBlurImageFilter::Make(i, 2, flutter::DlTileMode::kClamp);
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(20, 20), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(20, 20), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -767,15 +769,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a backdrop filter // Push a backdrop filter
auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp); auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -812,11 +815,12 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
stack2.PushTransform(screenScaleMatrix); stack2.PushTransform(screenScaleMatrix);
// Push backdrop filters // Push backdrop filters
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack2.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -897,17 +901,18 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push backdrop filters // Push backdrop filters
auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp); auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -942,11 +947,12 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
stack2.PushTransform(screenScaleMatrix); stack2.PushTransform(screenScaleMatrix);
// Push backdrop filters // Push backdrop filters
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack2.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -988,8 +994,8 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
} }
// No backdrop filters in the stack, so no nothing to push // No backdrop filters in the stack, so no nothing to push
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1054,17 +1060,18 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push backdrop filters // Push backdrop filters
auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp); auto filter = flutter::DlBlurImageFilter::Make(5, 2, flutter::DlTileMode::kClamp);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1102,16 +1109,17 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
if (i == 3) { if (i == 3) {
auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp); auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp);
stack2.PushBackdropFilter(filter2, stack2.PushBackdropFilter(
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); filter2, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
continue; continue;
} }
stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack2.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1159,16 +1167,17 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
if (i == 0) { if (i == 0) {
auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp); auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp);
stack2.PushBackdropFilter(filter2, stack2.PushBackdropFilter(
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); filter2, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
continue; continue;
} }
stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack2.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1214,16 +1223,17 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
if (i == 4) { if (i == 4) {
auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp); auto filter2 = flutter::DlBlurImageFilter::Make(2, 5, flutter::DlTileMode::kClamp);
stack2.PushBackdropFilter(filter2, stack2.PushBackdropFilter(
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); filter2, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
continue; continue;
} }
stack2.PushBackdropFilter(filter, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack2.PushBackdropFilter(filter,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1271,11 +1281,12 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
auto filter2 = flutter::DlBlurImageFilter::Make(i, 2, flutter::DlTileMode::kClamp); auto filter2 = flutter::DlBlurImageFilter::Make(i, 2, flutter::DlTileMode::kClamp);
stack2.PushBackdropFilter(filter2, SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); stack2.PushBackdropFilter(filter2,
flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1356,15 +1367,15 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a dilate backdrop filter // Push a dilate backdrop filter
auto dilateFilter = flutter::DlDilateImageFilter::Make(5, 2); auto dilateFilter = flutter::DlDilateImageFilter::Make(5, 2);
stack.PushBackdropFilter(dilateFilter, SkRect::MakeEmpty()); stack.PushBackdropFilter(dilateFilter, flutter::DlRect());
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1398,17 +1409,17 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
if (i == 2) { if (i == 2) {
stack2.PushBackdropFilter(dilateFilter, stack2.PushBackdropFilter(
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); dilateFilter, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
continue; continue;
} }
stack2.PushBackdropFilter(blurFilter, stack2.PushBackdropFilter(blurFilter,
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1441,17 +1452,17 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Push backdrop filters and dilate filter // Push backdrop filters and dilate filter
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
if (i == 0) { if (i == 0) {
stack2.PushBackdropFilter(dilateFilter, stack2.PushBackdropFilter(
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); dilateFilter, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
continue; continue;
} }
stack2.PushBackdropFilter(blurFilter, stack2.PushBackdropFilter(blurFilter,
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1484,17 +1495,17 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Push backdrop filters and dilate filter // Push backdrop filters and dilate filter
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
if (i == 4) { if (i == 4) {
stack2.PushBackdropFilter(dilateFilter, stack2.PushBackdropFilter(
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); dilateFilter, flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
continue; continue;
} }
stack2.PushBackdropFilter(blurFilter, stack2.PushBackdropFilter(blurFilter,
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1527,11 +1538,11 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Push dilate filters // Push dilate filters
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
stack2.PushBackdropFilter(dilateFilter, stack2.PushBackdropFilter(dilateFilter,
SkRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10)); flutter::DlRect::MakeXYWH(0, 0, screenScale * 10, screenScale * 10));
} }
embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1690,17 +1701,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a translate matrix // Push a translate matrix
SkMatrix translateMatrix = SkMatrix::Translate(100, 100); flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
stack.PushTransform(translateMatrix); stack.PushTransform(translateMatrix);
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
finalMatrix.setConcat(screenScaleMatrix, translateMatrix);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1758,12 +1768,12 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)];
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
@ -1800,8 +1810,8 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
XCTAssertEqual(numberOfExpectedVisualEffectView, 1u); XCTAssertEqual(numberOfExpectedVisualEffectView, 1u);
// New frame, with no filter pushed. // New frame, with no filter pushed.
auto embeddedViewParams2 = auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(0, 0)];
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams2)]; withParams:std::move(embeddedViewParams2)];
@ -1869,18 +1879,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a rotate matrix // Push a rotate matrix
SkMatrix rotateMatrix; flutter::DlMatrix rotateMatrix = flutter::DlMatrix::MakeRotationZ(flutter::DlDegrees(10));
rotateMatrix.setRotate(10);
stack.PushTransform(rotateMatrix); stack.PushTransform(rotateMatrix);
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix = screenScaleMatrix * rotateMatrix;
finalMatrix.setConcat(screenScaleMatrix, rotateMatrix);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -1952,23 +1960,23 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params. // Create embedded view params.
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack. // Layer tree always pushes a screen scale factor to the stack.
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
SkMatrix translateMatrix = SkMatrix::Translate(5, 5); flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({5, 5});
// The platform view's rect for this test will be (5, 5, 10, 10). // The platform view's rect for this test will be (5, 5, 10, 10).
stack.PushTransform(translateMatrix); stack.PushTransform(translateMatrix);
// Push a clip rect, big enough to contain the entire platform view bound. // Push a clip rect, big enough to contain the entire platform view bound.
SkRect rect = SkRect::MakeXYWH(0, 0, 25, 25); flutter::DlRect rect = flutter::DlRect::MakeXYWH(0, 0, 25, 25);
stack.PushClipRect(rect); stack.PushClipRect(rect);
// Push a clip rrect, big enough to contain the entire platform view bound without clipping it. // Push a clip rrect, big enough to contain the entire platform view bound without clipping it.
// Make the origin (-1, -1) so that the top left rounded corner isn't clipping the PlatformView. // Make the origin (-1, -1) so that the top left rounded corner isn't clipping the PlatformView.
SkRect rect_for_rrect = SkRect::MakeXYWH(-1, -1, 25, 25); flutter::DlRect rect_for_rrect = flutter::DlRect::MakeXYWH(-1, -1, 25, 25);
SkRRect rrect = SkRRect::MakeRectXY(rect_for_rrect, 1, 1); flutter::DlRoundRect rrect = flutter::DlRoundRect::MakeRectXY(rect_for_rrect, 1, 1);
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack); flutter::ToSkMatrix(screenScaleMatrix * translateMatrix), SkSize::Make(5, 5), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -2031,21 +2039,21 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack. // Layer tree always pushes a screen scale factor to the stack.
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
SkMatrix translateMatrix = SkMatrix::Translate(5, 5); flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({5, 5});
// The platform view's rect for this test will be (5, 5, 10, 10). // The platform view's rect for this test will be (5, 5, 10, 10).
stack.PushTransform(translateMatrix); stack.PushTransform(translateMatrix);
// Push a clip rrect, the rect of the rrect is the same as the PlatformView of the corner should. // Push a clip rrect, the rect of the rrect is the same as the PlatformView of the corner should.
// clip the PlatformView. // clip the PlatformView.
SkRect rect_for_rrect = SkRect::MakeXYWH(0, 0, 10, 10); flutter::DlRect rect_for_rrect = flutter::DlRect::MakeXYWH(0, 0, 10, 10);
SkRRect rrect = SkRRect::MakeRectXY(rect_for_rrect, 1, 1); flutter::DlRoundRect rrect = flutter::DlRoundRect::MakeRectXY(rect_for_rrect, 1, 1);
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack); flutter::ToSkMatrix(screenScaleMatrix * translateMatrix), SkSize::Make(5, 5), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -2109,15 +2117,15 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a clip rect // Push a clip rect
SkRect rect = SkRect::MakeXYWH(2, 2, 3, 3); flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
stack.PushClipRect(rect); stack.PushClipRect(rect);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -2192,18 +2200,18 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a clip rect // Push a clip rect
SkRect rect1 = SkRect::MakeXYWH(2, 2, 3, 3); flutter::DlRect rect1 = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
stack.PushClipRect(rect1); stack.PushClipRect(rect1);
// Push another clip rect // Push another clip rect
SkRect rect2 = SkRect::MakeXYWH(3, 3, 3, 3); flutter::DlRect rect2 = flutter::DlRect::MakeXYWH(3, 3, 3, 3);
stack.PushClipRect(rect2); stack.PushClipRect(rect2);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -2295,15 +2303,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a clip rrect // Push a clip rrect
SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeXYWH(2, 2, 6, 6), 1, 1); flutter::DlRoundRect rrect =
flutter::DlRoundRect::MakeRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -2405,18 +2414,19 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a clip rrect // Push a clip rrect
SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeXYWH(2, 2, 6, 6), 1, 1); flutter::DlRoundRect rrect =
flutter::DlRoundRect::MakeRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
stack.PushClipRRect(rrect); stack.PushClipRRect(rrect);
// Push a clip rect // Push a clip rect
SkRect rect = SkRect::MakeXYWH(4, 2, 6, 6); flutter::DlRect rect = flutter::DlRect::MakeXYWH(4, 2, 6, 6);
stack.PushClipRect(rect); stack.PushClipRect(rect);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -2532,16 +2542,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a clip path // Push a clip path
SkPath path; flutter::DlPath path =
path.addRoundRect(SkRect::MakeXYWH(2, 2, 6, 6), 1, 1); flutter::DlPath::MakeRoundRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
stack.PushClipPath(path); stack.PushClipPath(path);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -2643,19 +2653,19 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a clip path // Push a clip path
SkPath path; flutter::DlPath path =
path.addRoundRect(SkRect::MakeXYWH(2, 2, 6, 6), 1, 1); flutter::DlPath::MakeRoundRectXY(flutter::DlRect::MakeXYWH(2, 2, 6, 6), 1, 1);
stack.PushClipPath(path); stack.PushClipPath(path);
// Push a clip rect // Push a clip rect
SkRect rect = SkRect::MakeXYWH(4, 2, 6, 6); flutter::DlRect rect = flutter::DlRect::MakeXYWH(4, 2, 6, 6);
stack.PushClipRect(rect); stack.PushClipRect(rect);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -3495,10 +3505,10 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams_1 = auto embeddedViewParams_1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams_1)]; withParams:std::move(embeddedViewParams_1)];
@ -3516,8 +3526,8 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
submitFrame:std::move(mock_surface) submitFrame:std::move(mock_surface)
withIosContext:std::make_shared<flutter::IOSContextNoop>()]); withIosContext:std::make_shared<flutter::IOSContextNoop>()]);
auto embeddedViewParams_2 = auto embeddedViewParams_2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams_2)]; withParams:std::move(embeddedViewParams_2)];
[flutterPlatformViewsController [flutterPlatformViewsController
@ -3576,9 +3586,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
result:result]; result:result];
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -3636,9 +3646,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// First frame, |embeddedViewCount| is not empty after composite. // First frame, |embeddedViewCount| is not empty after composite.
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams1 = auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
[flutterPlatformViewsController [flutterPlatformViewsController
@ -3651,8 +3661,8 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 0UL); XCTAssertEqual(flutterPlatformViewsController.embeddedViewCount, 0UL);
auto embeddedViewParams2 = auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams2)]; withParams:std::move(embeddedViewParams2)];
[flutterPlatformViewsController [flutterPlatformViewsController
@ -3717,14 +3727,14 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams1 = auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
auto embeddedViewParams2 = auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(500, 500), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(500, 500), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams2)]; withParams:std::move(embeddedViewParams2)];
@ -3748,13 +3758,13 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Need to recreate these params since they are `std::move`ed. // Need to recreate these params since they are `std::move`ed.
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
// Process the second frame in the opposite order. // Process the second frame in the opposite order.
embeddedViewParams2 = embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(500, 500), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(500, 500), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams2)]; withParams:std::move(embeddedViewParams2)];
embeddedViewParams1 = embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
@ -3827,14 +3837,14 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams1 = auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
auto embeddedViewParams2 = auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(500, 500), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(500, 500), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams2)]; withParams:std::move(embeddedViewParams2)];
@ -3858,13 +3868,13 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Need to recreate these params since they are `std::move`ed. // Need to recreate these params since they are `std::move`ed.
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
// Process the second frame in the same order. // Process the second frame in the same order.
embeddedViewParams1 = embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
embeddedViewParams2 = embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(500, 500), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(500, 500), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams2)]; withParams:std::move(embeddedViewParams2)];
@ -4012,15 +4022,15 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack1; flutter::MutatorsStack stack1;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack1.PushTransform(screenScaleMatrix); stack1.PushTransform(screenScaleMatrix);
// Push a clip rect // Push a clip rect
SkRect rect = SkRect::MakeXYWH(2, 2, 3, 3); flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
stack1.PushClipRect(rect); stack1.PushClipRect(rect);
auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack1); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack1);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
@ -4036,9 +4046,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(100, 100)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(100, 100)];
flutter::MutatorsStack stack2; flutter::MutatorsStack stack2;
auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
auto embeddedViewParams3 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams3 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams3)]; withParams:std::move(embeddedViewParams3)];
[flutterPlatformViewsController [flutterPlatformViewsController
@ -4057,7 +4067,7 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
result:result]; result:result];
auto embeddedViewParams4 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams4 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack1); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack1);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams4)]; withParams:std::move(embeddedViewParams4)];
[flutterPlatformViewsController [flutterPlatformViewsController
@ -4128,20 +4138,20 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack1; flutter::MutatorsStack stack1;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack1.PushTransform(screenScaleMatrix); stack1.PushTransform(screenScaleMatrix);
// Push a clip rect // Push a clip rect
SkRect rect = SkRect::MakeXYWH(2, 2, 3, 3); flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
stack1.PushClipRect(rect); stack1.PushClipRect(rect);
auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack1); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack1);
flutter::MutatorsStack stack2; flutter::MutatorsStack stack2;
stack2.PushClipRect(rect); stack2.PushClipRect(rect);
auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
@ -4208,20 +4218,20 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack1; flutter::MutatorsStack stack1;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack1.PushTransform(screenScaleMatrix); stack1.PushTransform(screenScaleMatrix);
// Push a clip rect // Push a clip rect
SkRect rect = SkRect::MakeXYWH(2, 2, 3, 3); flutter::DlRect rect = flutter::DlRect::MakeXYWH(2, 2, 3, 3);
stack1.PushClipRect(rect); stack1.PushClipRect(rect);
auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack1); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack1);
flutter::MutatorsStack stack2; flutter::MutatorsStack stack2;
stack2.PushClipRect(rect); stack2.PushClipRect(rect);
auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>( auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
screenScaleMatrix, SkSize::Make(10, 10), stack2); flutter::ToSkMatrix(screenScaleMatrix), SkSize::Make(10, 10), stack2);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
@ -4317,14 +4327,14 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// No view should be disposed, or removed from the composition order. // No view should be disposed, or removed from the composition order.
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams0 = auto embeddedViewParams0 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams0)]; withParams:std::move(embeddedViewParams0)];
auto embeddedViewParams1 = auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
@ -4362,9 +4372,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// View 0 is removed from the composition order in this frame, hence also disposed. // View 0 is removed from the composition order in this frame, hence also disposed.
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams1 = auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
@ -4426,17 +4436,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a translate matrix // Push a translate matrix
SkMatrix translateMatrix = SkMatrix::Translate(100, 100); flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
stack.PushTransform(translateMatrix); stack.PushTransform(translateMatrix);
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
finalMatrix.setConcat(screenScaleMatrix, translateMatrix);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -4500,17 +4509,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a translate matrix // Push a translate matrix
SkMatrix translateMatrix = SkMatrix::Translate(100, 100); flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
stack.PushTransform(translateMatrix); stack.PushTransform(translateMatrix);
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
finalMatrix.setConcat(screenScaleMatrix, translateMatrix);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -4577,17 +4585,16 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
// Create embedded view params // Create embedded view params
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack // Layer tree always pushes a screen scale factor to the stack
CGFloat screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale; flutter::DlScalar screenScale = [mockFlutterViewController flutterScreenIfViewLoaded].scale;
SkMatrix screenScaleMatrix = SkMatrix::Scale(screenScale, screenScale); flutter::DlMatrix screenScaleMatrix = flutter::DlMatrix::MakeScale({screenScale, screenScale, 1});
stack.PushTransform(screenScaleMatrix); stack.PushTransform(screenScaleMatrix);
// Push a translate matrix // Push a translate matrix
SkMatrix translateMatrix = SkMatrix::Translate(100, 100); flutter::DlMatrix translateMatrix = flutter::DlMatrix::MakeTranslation({100, 100});
stack.PushTransform(translateMatrix); stack.PushTransform(translateMatrix);
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix = screenScaleMatrix * translateMatrix;
finalMatrix.setConcat(screenScaleMatrix, translateMatrix);
auto embeddedViewParams = auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:2 [flutterPlatformViewsController prerollCompositeEmbeddedView:2
withParams:std::move(embeddedViewParams)]; withParams:std::move(embeddedViewParams)];
@ -4688,14 +4695,14 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)]; [flutterPlatformViewsController beginFrameWithSize:SkISize::Make(300, 300)];
flutter::MutatorsStack stack; flutter::MutatorsStack stack;
SkMatrix finalMatrix; flutter::DlMatrix finalMatrix;
auto embeddedViewParams1 = auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(300, 300), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:0 [flutterPlatformViewsController prerollCompositeEmbeddedView:0
withParams:std::move(embeddedViewParams1)]; withParams:std::move(embeddedViewParams1)];
auto embeddedViewParams2 = auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(500, 500), stack); flutter::ToSkMatrix(finalMatrix), SkSize::Make(500, 500), stack);
[flutterPlatformViewsController prerollCompositeEmbeddedView:1 [flutterPlatformViewsController prerollCompositeEmbeddedView:1
withParams:std::move(embeddedViewParams2)]; withParams:std::move(embeddedViewParams2)];

View File

@ -37,17 +37,17 @@
// Adds a clip rect operation to the queue. // Adds a clip rect operation to the queue.
// //
// The `clipSkRect` is transformed with the `matrix` before adding to the queue. // The `clipSkRect` is transformed with the `matrix` before adding to the queue.
- (void)clipRect:(const SkRect&)clipSkRect matrix:(const SkMatrix&)matrix; - (void)clipRect:(const flutter::DlRect&)clipDlRect matrix:(const flutter::DlMatrix&)matrix;
// Adds a clip rrect operation to the queue. // Adds a clip rrect operation to the queue.
// //
// The `clipSkRRect` is transformed with the `matrix` before adding to the queue. // The `clipSkRRect` is transformed with the `matrix` before adding to the queue.
- (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix; - (void)clipRRect:(const flutter::DlRoundRect&)clipDlRRect matrix:(const flutter::DlMatrix&)matrix;
// Adds a clip path operation to the queue. // Adds a clip path operation to the queue.
// //
// The `path` is transformed with the `matrix` before adding to the queue. // The `path` is transformed with the `matrix` before adding to the queue.
- (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix; - (void)clipPath:(const flutter::DlPath&)path matrix:(const flutter::DlMatrix&)matrix;
@end @end

View File

@ -145,42 +145,42 @@ struct PlatformView {
view_identifier = view->GetViewIdentifier(); view_identifier = view->GetViewIdentifier();
params = view->GetEmbeddedViewParams(); params = view->GetEmbeddedViewParams();
clipped_frame = view->GetEmbeddedViewParams()->finalBoundingRect(); DlRect clip = ToDlRect(view->GetEmbeddedViewParams()->finalBoundingRect());
SkMatrix transform; DlMatrix matrix;
for (auto i = params->mutatorsStack().Begin(); for (auto i = params->mutatorsStack().Begin();
i != params->mutatorsStack().End(); ++i) { i != params->mutatorsStack().End(); ++i) {
const auto& m = *i; const auto& m = *i;
switch (m->GetType()) { switch (m->GetType()) {
case kClipRect: { case MutatorType::kClipRect: {
auto rect = transform.mapRect(m->GetRect()); auto rect = m->GetRect().TransformAndClipBounds(matrix);
if (!clipped_frame.intersect(rect)) { clip = clip.IntersectionOrEmpty(rect);
clipped_frame = SkRect::MakeEmpty();
}
break; break;
} }
case kClipRRect: { case MutatorType::kClipRRect: {
auto rect = transform.mapRect(m->GetRRect().getBounds()); auto rect = m->GetRRect().GetBounds().TransformAndClipBounds(matrix);
if (!clipped_frame.intersect(rect)) { clip = clip.IntersectionOrEmpty(rect);
clipped_frame = SkRect::MakeEmpty();
}
break; break;
} }
case kClipPath: { case MutatorType::kClipRSE: {
auto rect = transform.mapRect(m->GetPath().getBounds()); auto rect = m->GetRSE().GetBounds().TransformAndClipBounds(matrix);
if (!clipped_frame.intersect(rect)) { clip = clip.IntersectionOrEmpty(rect);
clipped_frame = SkRect::MakeEmpty();
}
break; break;
} }
case kTransform: { case MutatorType::kClipPath: {
transform.preConcat(m->GetMatrix()); auto rect = m->GetPath().GetBounds().TransformAndClipBounds(matrix);
clip = clip.IntersectionOrEmpty(rect);
break; break;
} }
case kOpacity: case MutatorType::kTransform: {
case kBackdropFilter: matrix = matrix * m->GetMatrix();
break;
}
case MutatorType::kOpacity:
case MutatorType::kBackdropFilter:
break; break;
} }
} }
clipped_frame = ToSkRect(clip);
} }
}; };

View File

@ -79,56 +79,57 @@ static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
} }
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation( static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkRect& rect) { const DlRect& rect) {
FlutterPlatformViewMutation mutation = {}; FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeClipRect; mutation.type = kFlutterPlatformViewMutationTypeClipRect;
mutation.clip_rect.left = rect.left(); mutation.clip_rect.left = rect.GetLeft();
mutation.clip_rect.top = rect.top(); mutation.clip_rect.top = rect.GetTop();
mutation.clip_rect.right = rect.right(); mutation.clip_rect.right = rect.GetRight();
mutation.clip_rect.bottom = rect.bottom(); mutation.clip_rect.bottom = rect.GetBottom();
return std::make_unique<FlutterPlatformViewMutation>(mutation); return std::make_unique<FlutterPlatformViewMutation>(mutation);
} }
static FlutterSize VectorToSize(const SkVector& vector) { static FlutterSize ConvertSize(const DlSize& vector) {
FlutterSize size = {}; FlutterSize size = {};
size.width = vector.x(); size.width = vector.width;
size.height = vector.y(); size.height = vector.height;
return size; return size;
} }
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation( static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkRRect& rrect) { const DlRoundRect& rrect) {
FlutterPlatformViewMutation mutation = {}; FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeClipRoundedRect; mutation.type = kFlutterPlatformViewMutationTypeClipRoundedRect;
const auto& rect = rrect.rect(); const auto& rect = rrect.GetBounds();
mutation.clip_rounded_rect.rect.left = rect.left(); mutation.clip_rounded_rect.rect.left = rect.GetLeft();
mutation.clip_rounded_rect.rect.top = rect.top(); mutation.clip_rounded_rect.rect.top = rect.GetTop();
mutation.clip_rounded_rect.rect.right = rect.right(); mutation.clip_rounded_rect.rect.right = rect.GetRight();
mutation.clip_rounded_rect.rect.bottom = rect.bottom(); mutation.clip_rounded_rect.rect.bottom = rect.GetBottom();
const auto& radii = rrect.GetRadii();
mutation.clip_rounded_rect.upper_left_corner_radius = mutation.clip_rounded_rect.upper_left_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kUpperLeft_Corner)); ConvertSize(radii.top_left);
mutation.clip_rounded_rect.upper_right_corner_radius = mutation.clip_rounded_rect.upper_right_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kUpperRight_Corner)); ConvertSize(radii.top_right);
mutation.clip_rounded_rect.lower_right_corner_radius = mutation.clip_rounded_rect.lower_right_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kLowerRight_Corner)); ConvertSize(radii.bottom_right);
mutation.clip_rounded_rect.lower_left_corner_radius = mutation.clip_rounded_rect.lower_left_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kLowerLeft_Corner)); ConvertSize(radii.bottom_left);
return std::make_unique<FlutterPlatformViewMutation>(mutation); return std::make_unique<FlutterPlatformViewMutation>(mutation);
} }
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation( static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkMatrix& matrix) { const DlMatrix& matrix) {
FlutterPlatformViewMutation mutation = {}; FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeTransformation; mutation.type = kFlutterPlatformViewMutationTypeTransformation;
mutation.transformation.scaleX = matrix[SkMatrix::kMScaleX]; mutation.transformation.scaleX = matrix.m[0];
mutation.transformation.skewX = matrix[SkMatrix::kMSkewX]; mutation.transformation.skewX = matrix.m[4];
mutation.transformation.transX = matrix[SkMatrix::kMTransX]; mutation.transformation.transX = matrix.m[12];
mutation.transformation.skewY = matrix[SkMatrix::kMSkewY]; mutation.transformation.skewY = matrix.m[1];
mutation.transformation.scaleY = matrix[SkMatrix::kMScaleY]; mutation.transformation.scaleY = matrix.m[5];
mutation.transformation.transY = matrix[SkMatrix::kMTransY]; mutation.transformation.transY = matrix.m[13];
mutation.transformation.pers0 = matrix[SkMatrix::kMPersp0]; mutation.transformation.pers0 = matrix.m[3];
mutation.transformation.pers1 = matrix[SkMatrix::kMPersp1]; mutation.transformation.pers1 = matrix.m[7];
mutation.transformation.pers2 = matrix[SkMatrix::kMPersp2]; mutation.transformation.pers2 = matrix.m[15];
return std::make_unique<FlutterPlatformViewMutation>(mutation); return std::make_unique<FlutterPlatformViewMutation>(mutation);
} }
@ -159,12 +160,18 @@ void EmbedderLayers::PushPlatformViewLayer(
.emplace_back(ConvertMutation(mutator->GetRRect())) .emplace_back(ConvertMutation(mutator->GetRRect()))
.get()); .get());
} break; } break;
case MutatorType::kClipRSE: {
mutations_array.push_back(
mutations_referenced_
.emplace_back(ConvertMutation(mutator->GetRSEApproximation()))
.get());
} break;
case MutatorType::kClipPath: { case MutatorType::kClipPath: {
// Unsupported mutation. // Unsupported mutation.
} break; } break;
case MutatorType::kTransform: { case MutatorType::kTransform: {
const auto& matrix = mutator->GetMatrix(); const auto& matrix = mutator->GetMatrix();
if (!matrix.isIdentity()) { if (!matrix.IsIdentity()) {
mutations_array.push_back( mutations_array.push_back(
mutations_referenced_.emplace_back(ConvertMutation(matrix)) mutations_referenced_.emplace_back(ConvertMutation(matrix))
.get()); .get());
@ -188,10 +195,9 @@ void EmbedderLayers::PushPlatformViewLayer(
// If there are going to be any mutations, they must first take into // If there are going to be any mutations, they must first take into
// account the root surface transformation. // account the root surface transformation.
if (!root_surface_transformation_.isIdentity()) { if (!root_surface_transformation_.isIdentity()) {
auto matrix = ToDlMatrix(root_surface_transformation_);
mutations_array.push_back( mutations_array.push_back(
mutations_referenced_ mutations_referenced_.emplace_back(ConvertMutation(matrix)).get());
.emplace_back(ConvertMutation(root_surface_transformation_))
.get());
} }
auto mutations = auto mutations =

View File

@ -609,8 +609,8 @@ void ExternalViewEmbedder::Reset() {
ExternalViewEmbedder::ViewMutators ExternalViewEmbedder::ParseMutatorStack( ExternalViewEmbedder::ViewMutators ExternalViewEmbedder::ParseMutatorStack(
const flutter::MutatorsStack& mutators_stack) { const flutter::MutatorsStack& mutators_stack) {
ViewMutators mutators; ViewMutators mutators;
SkMatrix total_transform = SkMatrix::I(); flutter::DlMatrix total_transform;
SkMatrix transform_accumulator = SkMatrix::I(); flutter::DlMatrix transform_accumulator;
for (auto i = mutators_stack.Begin(); i != mutators_stack.End(); ++i) { for (auto i = mutators_stack.Begin(); i != mutators_stack.End(); ++i) {
const auto& mutator = *i; const auto& mutator = *i;
@ -619,37 +619,44 @@ ExternalViewEmbedder::ViewMutators ExternalViewEmbedder::ParseMutatorStack(
mutators.opacity *= std::clamp(mutator->GetAlphaFloat(), 0.f, 1.f); mutators.opacity *= std::clamp(mutator->GetAlphaFloat(), 0.f, 1.f);
} break; } break;
case flutter::MutatorType::kTransform: { case flutter::MutatorType::kTransform: {
total_transform.preConcat(mutator->GetMatrix()); total_transform = total_transform * mutator->GetMatrix();
transform_accumulator.preConcat(mutator->GetMatrix()); transform_accumulator = transform_accumulator * mutator->GetMatrix();
} break; } break;
case flutter::MutatorType::kClipRect: { case flutter::MutatorType::kClipRect: {
mutators.clips.emplace_back(TransformedClip{ mutators.clips.emplace_back(TransformedClip{
.transform = transform_accumulator, .transform = flutter::ToSkMatrix(transform_accumulator),
.rect = mutator->GetRect(), .rect = flutter::ToSkRect(mutator->GetRect()),
}); });
transform_accumulator = SkMatrix::I(); transform_accumulator = flutter::DlMatrix();
} break; } break;
case flutter::MutatorType::kClipRRect: { case flutter::MutatorType::kClipRRect: {
mutators.clips.emplace_back(TransformedClip{ mutators.clips.emplace_back(TransformedClip{
.transform = transform_accumulator, .transform = flutter::ToSkMatrix(transform_accumulator),
.rect = mutator->GetRRect().getBounds(), .rect = flutter::ToSkRect(mutator->GetRRect().GetBounds()),
}); });
transform_accumulator = SkMatrix::I(); transform_accumulator = flutter::DlMatrix();
} break;
case flutter::MutatorType::kClipRSE: {
mutators.clips.emplace_back(TransformedClip{
.transform = flutter::ToSkMatrix(transform_accumulator),
.rect = flutter::ToSkRect(mutator->GetRSE().GetBounds()),
});
transform_accumulator = flutter::DlMatrix();
} break; } break;
case flutter::MutatorType::kClipPath: { case flutter::MutatorType::kClipPath: {
mutators.clips.emplace_back(TransformedClip{ mutators.clips.emplace_back(TransformedClip{
.transform = transform_accumulator, .transform = flutter::ToSkMatrix(transform_accumulator),
.rect = mutator->GetPath().getBounds(), .rect = flutter::ToSkRect(mutator->GetPath().GetBounds()),
}); });
transform_accumulator = SkMatrix::I(); transform_accumulator = flutter::DlMatrix();
} break; } break;
default: { default: {
break; break;
} }
} }
} }
mutators.total_transform = total_transform; mutators.total_transform = flutter::ToSkMatrix(total_transform);
mutators.transform = transform_accumulator; mutators.transform = flutter::ToSkMatrix(transform_accumulator);
mutators.opacity = std::clamp(mutators.opacity, 0.f, 1.f); mutators.opacity = std::clamp(mutators.opacity, 0.f, 1.f);
return mutators; return mutators;

View File

@ -34,6 +34,8 @@
#include "gmock/gmock.h" // For EXPECT_THAT and matchers #include "gmock/gmock.h" // For EXPECT_THAT and matchers
#include "gtest/gtest.h" #include "gtest/gtest.h"
using flutter::DlColor;
using flutter::DlMatrix;
using flutter::DlRect; using flutter::DlRect;
using flutter::DlSize; using flutter::DlSize;
using fuchsia::scenic::scheduling::FramePresentedInfo; using fuchsia::scenic::scheduling::FramePresentedInfo;
@ -607,20 +609,18 @@ TEST_F(ExternalViewEmbedderTest, SceneWithOneView) {
auto [child_view_token, child_viewport_token] = ViewTokenPair::New(); auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
const uint32_t child_view_id = child_viewport_token.value.get(); const uint32_t child_view_id = child_viewport_token.value.get();
const int kOpacity = 200; const uint8_t kOpacity = 200u;
const float kOpacityFloat = 200 / 255.0f; const float kOpacityFloat = DlColor::toOpacity(kOpacity);
const fuchsia::math::VecF kScale{3.0f, 4.0f}; const fuchsia::math::VecF kScale{3.0f, 4.0f};
auto matrix = SkMatrix::I(); DlMatrix matrix = DlMatrix::MakeScale({kScale.x, kScale.y, 1});
matrix.setScaleX(kScale.x);
matrix.setScaleY(kScale.y);
auto mutators_stack = flutter::MutatorsStack(); auto mutators_stack = flutter::MutatorsStack();
mutators_stack.PushOpacity(kOpacity); mutators_stack.PushOpacity(kOpacity);
mutators_stack.PushTransform(matrix); mutators_stack.PushTransform(matrix);
flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed, flutter::EmbeddedViewParams child_view_params(
mutators_stack); flutter::ToSkMatrix(matrix), child_view_size_signed, mutators_stack);
external_view_embedder.CreateView( external_view_embedder.CreateView(
child_view_id, []() {}, child_view_id, []() {},
[](fuchsia::ui::composition::ContentId, [](fuchsia::ui::composition::ContentId,
@ -830,33 +830,31 @@ TEST_F(ExternalViewEmbedderTest, SceneWithOneClippedView) {
auto [child_view_token, child_viewport_token] = ViewTokenPair::New(); auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
const uint32_t child_view_id = child_viewport_token.value.get(); const uint32_t child_view_id = child_viewport_token.value.get();
const int kOpacity = 200; const uint8_t kOpacity = 200u;
const float kOpacityFloat = 200 / 255.0f; const float kOpacityFloat = DlColor::toOpacity(kOpacity);
const fuchsia::math::VecF kScale{3.0f, 4.0f}; const fuchsia::math::VecF kScale{3.0f, 4.0f};
const int kTranslateX = 10; const int kTranslateX = 10;
const int kTranslateY = 20; const int kTranslateY = 20;
auto matrix = SkMatrix::I(); DlMatrix matrix = DlMatrix::MakeTranslation({kTranslateX, kTranslateY}) *
matrix.setScaleX(kScale.x); DlMatrix::MakeScale({kScale.x, kScale.y, 1});
matrix.setScaleY(kScale.y);
matrix.setTranslateX(kTranslateX);
matrix.setTranslateY(kTranslateY);
SkRect kClipRect = DlRect kClipRect =
SkRect::MakeXYWH(30, 40, child_view_size_signed.width() - 50, DlRect::MakeXYWH(30, 40, child_view_size_signed.width() - 50,
child_view_size_signed.height() - 60); child_view_size_signed.height() - 60);
fuchsia::math::Rect kClipInMathRect = { fuchsia::math::Rect kClipInMathRect = {
static_cast<int32_t>(kClipRect.x()), static_cast<int32_t>(kClipRect.y()), static_cast<int32_t>(kClipRect.GetX()),
static_cast<int32_t>(kClipRect.width()), static_cast<int32_t>(kClipRect.GetY()),
static_cast<int32_t>(kClipRect.height())}; static_cast<int32_t>(kClipRect.GetWidth()),
static_cast<int32_t>(kClipRect.GetHeight())};
auto mutators_stack = flutter::MutatorsStack(); auto mutators_stack = flutter::MutatorsStack();
mutators_stack.PushOpacity(kOpacity); mutators_stack.PushOpacity(kOpacity);
mutators_stack.PushTransform(matrix); mutators_stack.PushTransform(matrix);
mutators_stack.PushClipRect(kClipRect); mutators_stack.PushClipRect(kClipRect);
flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed, flutter::EmbeddedViewParams child_view_params(
mutators_stack); flutter::ToSkMatrix(matrix), child_view_size_signed, mutators_stack);
external_view_embedder.CreateView( external_view_embedder.CreateView(
child_view_id, []() {}, child_view_id, []() {},
[](fuchsia::ui::composition::ContentId, [](fuchsia::ui::composition::ContentId,
@ -939,14 +937,13 @@ TEST_F(ExternalViewEmbedderTest, SceneWithOneClippedView) {
// Draw another frame with view, but get rid of the clips this time. This // Draw another frame with view, but get rid of the clips this time. This
// should remove all ClipTransformLayer instances. // should remove all ClipTransformLayer instances.
auto new_matrix = SkMatrix::I(); DlMatrix new_matrix = DlMatrix::MakeScale({kScale.x, kScale.y, 1});
new_matrix.setScaleX(kScale.x);
new_matrix.setScaleY(kScale.y);
auto new_mutators_stack = flutter::MutatorsStack(); auto new_mutators_stack = flutter::MutatorsStack();
new_mutators_stack.PushOpacity(kOpacity); new_mutators_stack.PushOpacity(kOpacity);
new_mutators_stack.PushTransform(new_matrix); new_mutators_stack.PushTransform(new_matrix);
flutter::EmbeddedViewParams new_child_view_params( flutter::EmbeddedViewParams new_child_view_params(
new_matrix, child_view_size_signed, new_mutators_stack); flutter::ToSkMatrix(new_matrix), child_view_size_signed,
new_mutators_stack);
DrawFrameWithView( DrawFrameWithView(
external_view_embedder, frame_size_signed, kDPR, child_view_id, external_view_embedder, frame_size_signed, kDPR, child_view_id,
new_child_view_params, new_child_view_params,
@ -1071,20 +1068,18 @@ TEST_F(ExternalViewEmbedderTest, SceneWithOneView_NoOverlay) {
auto [child_view_token, child_viewport_token] = ViewTokenPair::New(); auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
const uint32_t child_view_id = child_viewport_token.value.get(); const uint32_t child_view_id = child_viewport_token.value.get();
const int kOpacity = 125; const uint8_t kOpacity = 125u;
const float kOpacityFloat = 125 / 255.0f; const float kOpacityFloat = DlColor::toOpacity(kOpacity);
const fuchsia::math::VecF kScale{2.f, 3.0f}; const fuchsia::math::VecF kScale{2.f, 3.0f};
auto matrix = SkMatrix::I(); DlMatrix matrix = DlMatrix::MakeScale({kScale.x, kScale.y, 1});
matrix.setScaleX(kScale.x);
matrix.setScaleY(kScale.y);
auto mutators_stack = flutter::MutatorsStack(); auto mutators_stack = flutter::MutatorsStack();
mutators_stack.PushOpacity(kOpacity); mutators_stack.PushOpacity(kOpacity);
mutators_stack.PushTransform(matrix); mutators_stack.PushTransform(matrix);
flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed, flutter::EmbeddedViewParams child_view_params(
mutators_stack); flutter::ToSkMatrix(matrix), child_view_size_signed, mutators_stack);
external_view_embedder.CreateView( external_view_embedder.CreateView(
child_view_id, []() {}, child_view_id, []() {},
[](fuchsia::ui::composition::ContentId, [](fuchsia::ui::composition::ContentId,
@ -1587,20 +1582,18 @@ TEST_F(ExternalViewEmbedderTest, ViewportCoveredWithInputInterceptor) {
auto [child_view_token, child_viewport_token] = ViewTokenPair::New(); auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
const uint32_t child_view_id = child_viewport_token.value.get(); const uint32_t child_view_id = child_viewport_token.value.get();
const int kOpacity = 200; const uint8_t kOpacity = 200u;
const float kOpacityFloat = 200 / 255.0f; const float kOpacityFloat = DlColor::toOpacity(kOpacity);
const fuchsia::math::VecF kScale{3.0f, 4.0f}; const fuchsia::math::VecF kScale{3.0f, 4.0f};
auto matrix = SkMatrix::I(); DlMatrix matrix = DlMatrix::MakeScale({kScale.x, kScale.y, 1});
matrix.setScaleX(kScale.x);
matrix.setScaleY(kScale.y);
auto mutators_stack = flutter::MutatorsStack(); auto mutators_stack = flutter::MutatorsStack();
mutators_stack.PushOpacity(kOpacity); mutators_stack.PushOpacity(kOpacity);
mutators_stack.PushTransform(matrix); mutators_stack.PushTransform(matrix);
flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed, flutter::EmbeddedViewParams child_view_params(
mutators_stack); flutter::ToSkMatrix(matrix), child_view_size_signed, mutators_stack);
external_view_embedder.CreateView( external_view_embedder.CreateView(
child_view_id, []() {}, child_view_id, []() {},
[](fuchsia::ui::composition::ContentId, [](fuchsia::ui::composition::ContentId,
@ -1624,24 +1617,23 @@ TEST_F(ExternalViewEmbedderTest, ViewportCoveredWithInputInterceptor) {
const fuchsia::math::SizeU frame_size{ const fuchsia::math::SizeU frame_size{
static_cast<uint32_t>(frame_size_signed.width()), static_cast<uint32_t>(frame_size_signed.width()),
static_cast<uint32_t>(frame_size_signed.height())}; static_cast<uint32_t>(frame_size_signed.height())};
DrawFrameWithView( auto background_draw_callback = [](flutter::DlCanvas* canvas) {
external_view_embedder, frame_size_signed, kDPR, child_view_id, const DlSize canvas_size(canvas->GetBaseLayerDimensions());
child_view_params, flutter::DlPaint rect_paint;
[](flutter::DlCanvas* canvas) { rect_paint.setColor(flutter::DlColor::kGreen());
const DlSize canvas_size(canvas->GetBaseLayerDimensions()); canvas->Translate(canvas_size.width / 4.f, canvas_size.height / 2.f);
flutter::DlPaint rect_paint; canvas->DrawRect(DlRect::MakeSize(canvas_size / 32.f), rect_paint);
rect_paint.setColor(flutter::DlColor::kGreen()); };
canvas->Translate(canvas_size.width / 4.f, canvas_size.height / 2.f); auto overlay_draw_callback = [](flutter::DlCanvas* canvas) {
canvas->DrawRect(DlRect::MakeSize(canvas_size / 32.f), rect_paint); const DlSize canvas_size(canvas->GetBaseLayerDimensions());
}, flutter::DlPaint rect_paint;
[](flutter::DlCanvas* canvas) { rect_paint.setColor(flutter::DlColor::kRed());
const DlSize canvas_size(canvas->GetBaseLayerDimensions()); canvas->Translate(canvas_size.width * 3.f / 4.f, canvas_size.height / 2.f);
flutter::DlPaint rect_paint; canvas->DrawRect(DlRect::MakeSize(canvas_size / 32.f), rect_paint);
rect_paint.setColor(flutter::DlColor::kRed()); };
canvas->Translate(canvas_size.width * 3.f / 4.f, DrawFrameWithView(external_view_embedder, frame_size_signed, kDPR,
canvas_size.height / 2.f); child_view_id, child_view_params, background_draw_callback,
canvas->DrawRect(DlRect::MakeSize(canvas_size / 32.f), rect_paint); overlay_draw_callback);
});
EXPECT_THAT(fake_flatland().graph(), EXPECT_THAT(fake_flatland().graph(),
IsFlutterGraph(parent_viewport_watcher, viewport_creation_token, IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
view_ref_clone, {IsInputShield()})); view_ref_clone, {IsInputShield()}));