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();
}
Path DlPath::GetPath() const {
const Path& DlPath::GetPath() const {
auto& sk_path = data_->sk_path;
auto& path = data_->path;
if (path.has_value()) {

View File

@ -67,7 +67,7 @@ class DlPath {
DlPath& operator=(const DlPath&) = default;
const SkPath& GetSkPath() const;
impeller::Path GetPath() const;
const impeller::Path& GetPath() const;
/// Intent to render an SkPath multiple times will make the path
/// 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);
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();
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 {
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;
}
if (cull_rect_.IsEmpty()) {
if (cull_bounds.IsEmpty()) {
return true;
}
if (matrix_.IsAligned2D()) {
if (matrix.IsAligned2D()) {
// This transform-to-device calculation is faster and more accurate
// for rect-to-rect aligned transformations, but not accurate under
// (non-quadrant) rotations and skews.
return content.TransformAndClipBounds(matrix_).Contains(cull_rect_);
return local_rect.TransformAndClipBounds(matrix).Contains(cull_bounds);
}
DlPoint corners[4];
if (!getLocalCullCorners(corners)) {
if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false;
}
for (auto corner : corners) {
if (!content.ContainsInclusive(corner)) {
if (!local_rect.ContainsInclusive(corner)) {
return false;
}
}
@ -271,20 +278,27 @@ bool DisplayListMatrixClipState::rect_covers_cull(const DlRect& content) 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;
}
if (cull_rect_.IsEmpty()) {
if (cull_bounds.IsEmpty()) {
return true;
}
DlPoint corners[4];
if (!getLocalCullCorners(corners)) {
if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false;
}
DlPoint center = bounds.GetCenter();
DlSize scale = 2.0 / bounds.GetSize();
DlPoint center = local_oval_bounds.GetCenter();
DlSize scale = 2.0 / local_oval_bounds.GetSize();
for (auto corner : corners) {
if (!bounds.Contains(corner)) {
if (!local_oval_bounds.Contains(corner)) {
return false;
}
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(
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;
}
if (cull_rect_.IsEmpty()) {
if (cull_bounds.IsEmpty()) {
return true;
}
if (content.IsRect()) {
return rect_covers_cull(content.GetBounds());
if (local_rrect.IsRect()) {
return TransformedRectCoversBounds(local_rrect.GetBounds(), matrix,
cull_bounds);
}
if (content.IsOval()) {
return oval_covers_cull(content.GetBounds());
if (local_rrect.IsOval()) {
return TransformedOvalCoversBounds(local_rrect.GetBounds(), matrix,
cull_bounds);
}
if (!content.GetRadii().AreAllCornersSame()) {
if (!local_rrect.GetRadii().AreAllCornersSame()) {
return false;
}
DlPoint corners[4];
if (!getLocalCullCorners(corners)) {
if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false;
}
auto outer = content.GetBounds();
auto outer = local_rrect.GetBounds();
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 scale = 1.0 / radii;
for (auto corner : corners) {
@ -335,25 +358,34 @@ bool DisplayListMatrixClipState::rrect_covers_cull(
bool DisplayListMatrixClipState::rsuperellipse_covers_cull(
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;
}
if (cull_rect_.IsEmpty()) {
if (cull_bounds.IsEmpty()) {
return true;
}
if (content.IsRect()) {
return rect_covers_cull(content.GetBounds());
if (local_rse.IsRect()) {
return TransformedRectCoversBounds(local_rse.GetBounds(), matrix,
cull_bounds);
}
if (content.IsOval()) {
return oval_covers_cull(content.GetBounds());
if (local_rse.IsOval()) {
return TransformedOvalCoversBounds(local_rse.GetBounds(), matrix,
cull_bounds);
}
DlPoint corners[4];
if (!getLocalCullCorners(corners)) {
if (!GetLocalCorners(corners, cull_bounds, matrix)) {
return false;
}
auto outer = content.GetBounds();
auto outer = local_rse.GetBounds();
auto param = impeller::RoundSuperellipseParam::MakeBoundsRadii(
outer, content.GetRadii());
outer, local_rse.GetRadii());
for (auto corner : corners) {
if (!outer.Contains(corner)) {
return false;
@ -365,15 +397,17 @@ bool DisplayListMatrixClipState::rsuperellipse_covers_cull(
return true;
}
bool DisplayListMatrixClipState::getLocalCullCorners(DlPoint corners[4]) const {
if (!is_matrix_invertable()) {
bool DisplayListMatrixClipState::GetLocalCorners(DlPoint corners[4],
const DlRect& rect,
const DlMatrix& matrix) {
if (!matrix.IsInvertible()) {
return false;
}
DlMatrix inverse = matrix_.Invert();
corners[0] = inverse * cull_rect_.GetLeftTop();
corners[1] = inverse * cull_rect_.GetRightTop();
corners[2] = inverse * cull_rect_.GetRightBottom();
corners[3] = inverse * cull_rect_.GetLeftBottom();
DlMatrix inverse = matrix.Invert();
corners[0] = inverse * rect.GetLeftTop();
corners[1] = inverse * rect.GetRightTop();
corners[2] = inverse * rect.GetRightBottom();
corners[3] = inverse * rect.GetLeftBottom();
return true;
}

View File

@ -113,12 +113,60 @@ class DisplayListMatrixClipState {
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:
DlRect cull_rect_;
DlMatrix matrix_;
bool getLocalCullCorners(DlPoint corners[4]) const;
void adjustCullRect(const DlRect& clip, DlClipOp op, bool is_aa);
static bool GetLocalCorners(DlPoint corners[4],
const DlRect& rect,
const DlMatrix& matrix);
};
} // namespace flutter

View File

@ -468,15 +468,23 @@ TEST(DisplayListMatrixClipState, RectCoverage) {
DlRect rect = DlRect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
DisplayListMatrixClipState state(rect);
EXPECT_TRUE(state.rect_covers_cull(rect));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
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)));
auto test_rect = [&state](const DlRect& test_rect, bool expect) {
EXPECT_EQ(state.rect_covers_cull(test_rect), expect) << test_rect;
EXPECT_EQ(DisplayListMatrixClipState::TransformedRectCoversBounds(
test_rect, state.matrix(), state.GetDeviceCullCoverage()),
expect)
<< test_rect;
};
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) {
@ -495,15 +503,23 @@ TEST(DisplayListMatrixClipState, RectCoverageAccuracy) {
DisplayListMatrixClipState state(cull);
state.scale(DPR, DPR);
EXPECT_TRUE(state.rect_covers_cull(rect));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
EXPECT_TRUE(state.rect_covers_cull(rect.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
EXPECT_FALSE(state.rect_covers_cull(rect.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
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)));
auto test_rect = [&state](const DlRect& test_rect, bool expect) {
EXPECT_EQ(state.rect_covers_cull(test_rect), expect) << test_rect;
EXPECT_EQ(DisplayListMatrixClipState::TransformedRectCoversBounds(
test_rect, state.matrix(), state.GetDeviceCullCoverage()),
expect)
<< test_rect;
};
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) {
@ -511,16 +527,24 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderScale) {
DisplayListMatrixClipState state(rect);
state.scale(2.0f, 2.0f);
EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(100, 100, 200, 200)));
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 100)));
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(49, 50, 100, 100)));
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 49, 100, 100)));
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 101, 100)));
EXPECT_TRUE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 101)));
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)));
EXPECT_FALSE(state.rect_covers_cull(DlRect::MakeLTRB(50, 50, 100, 99)));
auto test_rect = [&state](const DlRect& test_rect, bool expect) {
EXPECT_EQ(state.rect_covers_cull(test_rect), expect) << test_rect;
EXPECT_EQ(DisplayListMatrixClipState::TransformedRectCoversBounds(
test_rect, state.matrix(), state.GetDeviceCullCoverage()),
expect)
<< test_rect;
};
test_rect(DlRect::MakeLTRB(100, 100, 200, 200), false);
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) {
@ -537,6 +561,11 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
<< " testing " << test_true << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " 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) {
// The cull rect is largest when viewed at multiples of 45
// degrees so we will fail to contain it at those angles
@ -544,6 +573,11 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
<< " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " 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 {
// At other angles, the cull rect is not quite so big as to encroach
// upon the expanded test rectangle.
@ -551,6 +585,11 @@ TEST(DisplayListMatrixClipState, RectCoverageUnderRotation) {
<< " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " 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.
DlRect test = cull.Scale(impeller::kSqrt2).Expand(0.02f);
EXPECT_TRUE(state.oval_covers_cull(test));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
EXPECT_FALSE(state.oval_covers_cull(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
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)));
auto test_oval = [&state](const DlRect& test_rect, bool expect) {
EXPECT_EQ(state.oval_covers_cull(test_rect), expect) << test_rect;
EXPECT_EQ(DisplayListMatrixClipState::TransformedOvalCoversBounds(
test_rect, state.matrix(), state.GetDeviceCullCoverage()),
expect)
<< test_rect;
};
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) {
@ -587,15 +634,23 @@ TEST(DisplayListMatrixClipState, OvalCoverageUnderScale) {
// the cull rect under a 2.0 scale.
DlRect test = cull.Scale(0.5f * impeller::kSqrt2).Expand(0.02f);
EXPECT_TRUE(state.oval_covers_cull(test));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.1f, 0.0f, 0.0f, 0.0f)));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.1f, 0.0f, 0.0f)));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.1f, 0.0f)));
EXPECT_TRUE(state.oval_covers_cull(test.Expand(0.0f, 0.0f, 0.0f, 0.1f)));
EXPECT_FALSE(state.oval_covers_cull(test.Expand(-0.1f, 0.0f, 0.0f, 0.0f)));
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)));
auto test_oval = [&state](const DlRect& test_rect, bool expect) {
EXPECT_EQ(state.oval_covers_cull(test_rect), expect) << test_rect;
EXPECT_EQ(DisplayListMatrixClipState::TransformedOvalCoversBounds(
test_rect, state.matrix(), state.GetDeviceCullCoverage()),
expect)
<< test_rect;
};
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) {
@ -620,6 +675,17 @@ TEST(DisplayListMatrixClipState, OvalCoverageUnderRotation) {
<< " testing " << test_false << std::endl
<< " contains " << state.GetLocalCullCoverage() << std::endl
<< " 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
EXPECT_TRUE(
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
EXPECT_FALSE(
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
EXPECT_TRUE(
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
// 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)
@ -663,9 +737,14 @@ TEST(DisplayListMatrixClipState, RRectCoverage) {
// corners set to 6.82 should still cover the cull rect
EXPECT_TRUE(
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
EXPECT_FALSE(
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

View File

@ -23,10 +23,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithNoMutations) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) {
MutatorsStack stack;
SkMatrix matrix = SkMatrix::Scale(2, 2);
DlMatrix matrix = DlMatrix::MakeScale({2, 2, 1});
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();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
@ -36,10 +36,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) {
MutatorsStack stack;
SkMatrix matrix = SkMatrix::Translate(1, 1);
DlMatrix matrix = DlMatrix::MakeTranslation({1, 1});
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();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 1));
@ -49,11 +49,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) {
MutatorsStack stack;
SkMatrix matrix;
matrix.setRotate(90);
DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(90));
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();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
@ -64,11 +63,10 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) {
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) {
MutatorsStack stack;
SkMatrix matrix;
matrix.setRotate(45);
DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(45));
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();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -sqrt(2) / 2));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
@ -78,14 +76,14 @@ TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) {
TEST(EmbeddedViewParams,
GetBoundingRectAfterMutationsWithTranslateScaleAndRotation) {
SkMatrix matrix = SkMatrix::Translate(2, 2);
matrix.preScale(3, 3);
matrix.preRotate(90);
DlMatrix matrix = DlMatrix::MakeTranslation({2, 2}) *
DlMatrix::MakeScale({3, 3, 1}) *
DlMatrix::MakeRotationZ(DlDegrees(90));
MutatorsStack stack;
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();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 2));

View File

@ -58,34 +58,39 @@ bool ExternalViewEmbedder::SupportsDynamicThreadMerging() {
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);
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);
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);
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);
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);
vector_.push_back(element);
}
void MutatorsStack::PushBackdropFilter(
const std::shared_ptr<DlImageFilter>& filter,
const SkRect& filter_rect) {
const DlRect& filter_rect) {
std::shared_ptr<Mutator> element =
std::make_shared<Mutator>(filter, filter_rect);
vector_.push_back(element);

View File

@ -7,6 +7,7 @@
#include <memory>
#include <utility>
#include <variant>
#include <vector>
#include "flutter/display_list/dl_builder.h"
@ -14,11 +15,6 @@
#include "flutter/flow/surface_frame.h"
#include "flutter/fml/memory/ref_counted.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
#include "flutter/impeller/display_list/aiks_context.h" // nogncheck
@ -34,9 +30,10 @@ class GrDirectContext;
namespace flutter {
enum MutatorType {
enum class MutatorType {
kClipRect,
kClipRRect,
kClipRSE,
kClipPath,
kTransform,
kOpacity,
@ -46,16 +43,14 @@ enum MutatorType {
// Represents an image filter mutation.
//
// 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 {
public:
ImageFilterMutation(std::shared_ptr<DlImageFilter> filter,
const SkRect& filter_rect)
const DlRect& filter_rect)
: filter_(std::move(filter)), filter_rect_(filter_rect) {}
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 {
return *filter_ == *other.filter_ && filter_rect_ == other.filter_rect_;
@ -67,7 +62,7 @@ class ImageFilterMutation {
private:
std::shared_ptr<DlImageFilter> filter_;
const SkRect filter_rect_;
const DlRect filter_rect_;
};
// Stores mutation information like clipping or kTransform.
@ -78,112 +73,65 @@ class ImageFilterMutation {
// clipped. One mutation object must only contain one type of mutation.
class Mutator {
public:
Mutator(const Mutator& other) {
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;
}
}
Mutator(const Mutator& other) : data_(other.data_) {}
explicit Mutator(const SkRect& rect) : type_(kClipRect), rect_(rect) {}
explicit Mutator(const SkRRect& rrect) : type_(kClipRRect), rrect_(rrect) {}
explicit Mutator(const SkPath& path)
: type_(kClipPath), path_(new SkPath(path)) {}
explicit Mutator(const SkMatrix& matrix)
: type_(kTransform), matrix_(matrix) {}
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 DlRect& rect) : data_(rect) {}
explicit Mutator(const DlRoundRect& rrect) : data_(rrect) {}
explicit Mutator(const DlRoundSuperellipse& rrect) : data_(rrect) {}
explicit Mutator(const DlPath& path) : data_(path) {}
explicit Mutator(const DlMatrix& matrix) : data_(matrix) {}
explicit Mutator(const uint8_t& alpha) : data_(alpha) {}
explicit Mutator(const std::shared_ptr<DlImageFilter>& filter,
const DlRect& filter_rect)
: Mutator(filter, ToSkRect(filter_rect)) {}
: data_(ImageFilterMutation(filter, filter_rect)) {}
const MutatorType& GetType() const { return type_; }
const SkRect& GetRect() const { return rect_; }
const SkRRect& GetRRect() const { return rrect_; }
const SkPath& GetPath() const { return *path_; }
const SkMatrix& GetMatrix() const { return matrix_; }
MutatorType GetType() const {
return static_cast<MutatorType>(data_.index());
}
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 {
return *filter_mutation_;
return std::get<ImageFilterMutation>(data_);
}
const int& GetAlpha() const { return alpha_; }
float GetAlphaFloat() const { return (alpha_ / 255.0f); }
const uint8_t& GetAlpha() const { return std::get<uint8_t>(data_); }
float GetAlphaFloat() const { return DlColor::toOpacity(GetAlpha()); }
bool operator==(const Mutator& other) const {
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 data_ == other.data_; }
bool operator!=(const Mutator& other) const { return !operator==(other); }
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:
MutatorType type_;
// TODO(cyanglaz): Remove union.
// https://github.com/flutter/flutter/issues/108470
union {
SkRect rect_;
SkRRect rrect_;
SkMatrix matrix_;
SkPath* path_;
int alpha_;
};
std::shared_ptr<ImageFilterMutation> filter_mutation_;
std::variant<DlRect,
DlRoundRect,
DlRoundSuperellipse,
DlPath,
DlMatrix,
uint8_t,
ImageFilterMutation>
data_;
}; // Mutator
// A stack of mutators that can be applied to an embedded platform view.
@ -199,14 +147,15 @@ class MutatorsStack {
public:
MutatorsStack() = default;
void PushClipRect(const SkRect& rect);
void PushClipRRect(const SkRRect& rrect);
void PushClipPath(const SkPath& path);
void PushTransform(const SkMatrix& matrix);
void PushOpacity(const int& alpha);
void PushClipRect(const DlRect& rect);
void PushClipRRect(const DlRoundRect& rrect);
void PushClipRSE(const DlRoundSuperellipse& rrect);
void PushClipPath(const DlPath& path);
void PushTransform(const DlMatrix& matrix);
void PushOpacity(const uint8_t& alpha);
// `filter_rect` is in global coordinates.
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
// and destroys it.
@ -306,7 +255,7 @@ class EmbeddedViewParams {
// `filter_rect` is in global coordinates.
void PushImageFilter(const std::shared_ptr<DlImageFilter>& filter,
const SkRect& filter_rect) {
mutators_stack_.PushBackdropFilter(filter, filter_rect);
mutators_stack_.PushBackdropFilter(filter, ToDlRect(filter_rect));
}
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_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(ToApproximateSkRRect(layer_rsuperellipse))}));
std::vector({Mutator(layer_rsuperellipse)}));
auto mutator = paint_context().state_stack.save();
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_matrix(), initial_matrix);
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()));
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_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(ToApproximateSkRRect(layer_rsuperellipse))}));
std::vector({Mutator(layer_rsuperellipse)}));
layer->Paint(display_list_paint_context());
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_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(ToApproximateSkRRect(clip_rsuperellipse))}));
std::vector({Mutator(clip_rsuperellipse)}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;

View File

@ -246,7 +246,7 @@ class SaveLayerEntry : public LayerStateStack::StateEntry {
class OpacityEntry : public LayerStateStack::StateEntry {
public:
OpacityEntry(const DlRect& bounds,
SkScalar opacity,
DlScalar opacity,
const LayerStateStack::RenderingAttributes& prev)
: bounds_(bounds),
opacity_(opacity),
@ -376,18 +376,17 @@ class BackdropFilterEntry : public SaveLayerEntry {
class TranslateEntry : public LayerStateStack::StateEntry {
public:
TranslateEntry(SkScalar tx, SkScalar ty) : tx_(tx), ty_(ty) {}
TranslateEntry(DlScalar tx, DlScalar ty) : translation_(tx, ty) {}
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 {
mutators_stack->PushTransform(SkMatrix::Translate(tx_, ty_));
mutators_stack->PushTransform(DlMatrix::MakeTranslation(translation_));
}
private:
const SkScalar tx_;
const SkScalar ty_;
const DlPoint translation_;
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TranslateEntry);
};
@ -400,7 +399,7 @@ class TransformMatrixEntry : public LayerStateStack::StateEntry {
stack->delegate_->transform(matrix_);
}
void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushTransform(ToSkMatrix(matrix_));
mutators_stack->PushTransform(matrix_);
}
private:
@ -430,7 +429,7 @@ class ClipRectEntry : public LayerStateStack::StateEntry {
stack->delegate_->clipRect(clip_rect_, DlClipOp::kIntersect, is_aa_);
}
void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushClipRect(ToSkRect(clip_rect_));
mutators_stack->PushClipRect(clip_rect_);
}
private:
@ -449,7 +448,7 @@ class ClipRRectEntry : public LayerStateStack::StateEntry {
stack->delegate_->clipRRect(clip_rrect_, DlClipOp::kIntersect, is_aa_);
}
void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushClipRRect(ToSkRRect(clip_rrect_));
mutators_stack->PushClipRRect(clip_rrect_);
}
private:
@ -470,13 +469,7 @@ class ClipRSuperellipseEntry : public LayerStateStack::StateEntry {
DlClipOp::kIntersect, is_aa_);
}
void update_mutators(MutatorsStack* mutators_stack) const override {
// MutatorsStack doesn't support non-Skia classes, and therefore this method
// 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_));
mutators_stack->PushClipRSE(clip_rsuperellipse_);
}
private:
@ -496,7 +489,7 @@ class ClipPathEntry : public LayerStateStack::StateEntry {
stack->delegate_->clipPath(clip_path_, DlClipOp::kIntersect, is_aa_);
}
void update_mutators(MutatorsStack* mutators_stack) const override {
mutators_stack->PushClipPath(clip_path_.GetSkPath());
mutators_stack->PushClipPath(clip_path_);
}
private:

View File

@ -16,8 +16,8 @@ TEST(MutatorsStack, Initialization) {
TEST(MutatorsStack, CopyConstructor) {
MutatorsStack stack;
auto rrect = SkRRect::MakeEmpty();
auto rect = SkRect::MakeEmpty();
auto rrect = DlRoundRect();
auto rect = DlRect();
stack.PushClipRect(rect);
stack.PushClipRRect(rrect);
MutatorsStack copy = MutatorsStack(stack);
@ -26,8 +26,8 @@ TEST(MutatorsStack, CopyConstructor) {
TEST(MutatorsStack, CopyAndUpdateTheCopy) {
MutatorsStack stack;
auto rrect = SkRRect::MakeEmpty();
auto rect = SkRect::MakeEmpty();
auto rrect = DlRoundRect();
auto rect = DlRect();
stack.PushClipRect(rect);
stack.PushClipRRect(rrect);
MutatorsStack copy = MutatorsStack(stack);
@ -46,7 +46,7 @@ TEST(MutatorsStack, CopyAndUpdateTheCopy) {
TEST(MutatorsStack, PushClipRect) {
MutatorsStack stack;
auto rect = SkRect::MakeEmpty();
auto rect = DlRect();
stack.PushClipRect(rect);
auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kClipRect);
@ -55,16 +55,25 @@ TEST(MutatorsStack, PushClipRect) {
TEST(MutatorsStack, PushClipRRect) {
MutatorsStack stack;
auto rrect = SkRRect::MakeEmpty();
auto rrect = DlRoundRect();
stack.PushClipRRect(rrect);
auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kClipRRect);
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) {
MutatorsStack stack;
SkPath path;
DlPath path;
stack.PushClipPath(path);
auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == flutter::MutatorType::kClipPath);
@ -73,8 +82,7 @@ TEST(MutatorsStack, PushClipPath) {
TEST(MutatorsStack, PushTransform) {
MutatorsStack stack;
SkMatrix matrix;
matrix.setIdentity();
DlMatrix matrix;
stack.PushTransform(matrix);
auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kTransform);
@ -83,7 +91,7 @@ TEST(MutatorsStack, PushTransform) {
TEST(MutatorsStack, PushOpacity) {
MutatorsStack stack;
int alpha = 240;
uint8_t alpha = 240;
stack.PushOpacity(alpha);
auto iter = stack.Bottom();
ASSERT_TRUE(iter->get()->GetType() == MutatorType::kOpacity);
@ -95,7 +103,7 @@ TEST(MutatorsStack, PushBackdropFilter) {
const int num_of_mutators = 10;
for (int i = 0; i < num_of_mutators; i++) {
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();
@ -104,10 +112,10 @@ TEST(MutatorsStack, PushBackdropFilter) {
ASSERT_EQ(iter->get()->GetType(), MutatorType::kBackdropFilter);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilter().asBlur()->sigma_x(),
i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().x(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().x(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().width(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().height(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetX(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetY(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetWidth(), i);
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().GetHeight(), i);
++iter;
++i;
}
@ -116,8 +124,7 @@ TEST(MutatorsStack, PushBackdropFilter) {
TEST(MutatorsStack, Pop) {
MutatorsStack stack;
SkMatrix matrix;
matrix.setIdentity();
DlMatrix matrix;
stack.PushTransform(matrix);
stack.Pop();
auto iter = stack.Bottom();
@ -126,12 +133,11 @@ TEST(MutatorsStack, Pop) {
TEST(MutatorsStack, Traversal) {
MutatorsStack stack;
SkMatrix matrix;
matrix.setIdentity();
DlMatrix matrix;
stack.PushTransform(matrix);
auto rect = SkRect::MakeEmpty();
auto rect = DlRect();
stack.PushClipRect(rect);
auto rrect = SkRRect::MakeEmpty();
auto rrect = DlRoundRect();
stack.PushClipRRect(rrect);
auto iter = stack.Bottom();
int index = 0;
@ -159,153 +165,165 @@ TEST(MutatorsStack, Traversal) {
TEST(MutatorsStack, Equality) {
MutatorsStack stack;
SkMatrix matrix = SkMatrix::Scale(1, 1);
DlMatrix matrix = DlMatrix::MakeScale({1, 1, 1});
stack.PushTransform(matrix);
SkRect rect = SkRect::MakeEmpty();
DlRect rect = DlRect();
stack.PushClipRect(rect);
SkRRect rrect = SkRRect::MakeEmpty();
DlRoundRect rrect = DlRoundRect();
stack.PushClipRRect(rrect);
SkPath path;
DlPath path;
stack.PushClipPath(path);
int alpha = 240;
uint8_t alpha = 240;
stack.PushOpacity(alpha);
auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
stack.PushBackdropFilter(filter, SkRect::MakeEmpty());
stack.PushBackdropFilter(filter, DlRect());
MutatorsStack stack_other;
SkMatrix matrix_other = SkMatrix::Scale(1, 1);
DlMatrix matrix_other = DlMatrix::MakeScale({1, 1, 1});
stack_other.PushTransform(matrix_other);
SkRect rect_other = SkRect::MakeEmpty();
DlRect rect_other = DlRect();
stack_other.PushClipRect(rect_other);
SkRRect rrect_other = SkRRect::MakeEmpty();
DlRoundRect rrect_other = DlRoundRect();
stack_other.PushClipRRect(rrect_other);
SkPath other_path;
DlPath other_path;
stack_other.PushClipPath(other_path);
int other_alpha = 240;
uint8_t other_alpha = 240;
stack_other.PushOpacity(other_alpha);
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);
}
TEST(Mutator, Initialization) {
SkRect rect = SkRect::MakeEmpty();
DlRect rect = DlRect();
Mutator mutator = Mutator(rect);
ASSERT_TRUE(mutator.GetType() == MutatorType::kClipRect);
ASSERT_TRUE(mutator.GetRect() == rect);
SkRRect rrect = SkRRect::MakeEmpty();
DlRoundRect rrect = DlRoundRect();
Mutator mutator2 = Mutator(rrect);
ASSERT_TRUE(mutator2.GetType() == MutatorType::kClipRRect);
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);
ASSERT_TRUE(mutator3.GetType() == MutatorType::kClipPath);
ASSERT_TRUE(mutator3.GetPath() == path);
SkMatrix matrix;
matrix.setIdentity();
DlMatrix matrix;
Mutator mutator4 = Mutator(matrix);
ASSERT_TRUE(mutator4.GetType() == MutatorType::kTransform);
ASSERT_TRUE(mutator4.GetMatrix() == matrix);
int alpha = 240;
uint8_t alpha = 240;
Mutator mutator5 = Mutator(alpha);
ASSERT_TRUE(mutator5.GetType() == MutatorType::kOpacity);
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.GetFilterMutation().GetFilter() == *filter);
}
TEST(Mutator, CopyConstructor) {
SkRect rect = SkRect::MakeEmpty();
DlRect rect = DlRect();
Mutator mutator = Mutator(rect);
Mutator copy = Mutator(mutator);
ASSERT_TRUE(mutator == copy);
SkRRect rrect = SkRRect::MakeEmpty();
DlRoundRect rrect = DlRoundRect();
Mutator mutator2 = Mutator(rrect);
Mutator copy2 = Mutator(mutator2);
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 copy3 = Mutator(mutator3);
ASSERT_TRUE(mutator3 == copy3);
SkMatrix matrix;
matrix.setIdentity();
DlMatrix matrix;
Mutator mutator4 = Mutator(matrix);
Mutator copy4 = Mutator(mutator4);
ASSERT_TRUE(mutator4 == copy4);
int alpha = 240;
uint8_t alpha = 240;
Mutator mutator5 = Mutator(alpha);
Mutator copy5 = Mutator(mutator5);
ASSERT_TRUE(mutator5 == copy5);
auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter, SkRect::MakeEmpty());
Mutator mutator6 = Mutator(filter, DlRect());
Mutator copy6 = Mutator(mutator6);
ASSERT_TRUE(mutator6 == copy6);
}
TEST(Mutator, Equality) {
SkMatrix matrix;
matrix.setIdentity();
DlMatrix matrix;
Mutator mutator = Mutator(matrix);
Mutator other_mutator = Mutator(matrix);
ASSERT_TRUE(mutator == other_mutator);
SkRect rect = SkRect::MakeEmpty();
DlRect rect = DlRect();
Mutator mutator2 = Mutator(rect);
Mutator other_mutator2 = Mutator(rect);
ASSERT_TRUE(mutator2 == other_mutator2);
SkRRect rrect = SkRRect::MakeEmpty();
DlRoundRect rrect = DlRoundRect();
Mutator mutator3 = Mutator(rrect);
Mutator other_mutator3 = Mutator(rrect);
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 other_mutator4 = flutter::Mutator(path);
ASSERT_TRUE(mutator4 == other_mutator4);
ASSERT_FALSE(mutator2 == mutator);
int alpha = 240;
uint8_t alpha = 240;
Mutator mutator5 = Mutator(alpha);
Mutator other_mutator5 = Mutator(alpha);
ASSERT_TRUE(mutator5 == other_mutator5);
auto filter1 = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
auto filter2 = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
Mutator mutator6 = Mutator(filter1, SkRect::MakeEmpty());
Mutator other_mutator6 = Mutator(filter2, SkRect::MakeEmpty());
Mutator mutator6 = Mutator(filter1, DlRect());
Mutator other_mutator6 = Mutator(filter2, DlRect());
ASSERT_TRUE(mutator6 == other_mutator6);
}
TEST(Mutator, UnEquality) {
SkRect rect = SkRect::MakeEmpty();
DlRect rect = DlRect();
Mutator mutator = Mutator(rect);
SkMatrix matrix;
matrix.setIdentity();
DlMatrix matrix;
Mutator not_equal_mutator = Mutator(matrix);
ASSERT_TRUE(not_equal_mutator != mutator);
int alpha = 240;
int alpha2 = 241;
uint8_t alpha = 240;
uint8_t alpha2 = 241;
Mutator mutator2 = Mutator(alpha);
Mutator other_mutator2 = Mutator(alpha2);
ASSERT_TRUE(mutator2 != other_mutator2);
auto filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kClamp);
auto filter2 = DlImageFilter::MakeBlur(10, 10, DlTileMode::kClamp);
Mutator mutator3 = Mutator(filter, SkRect::MakeEmpty());
Mutator other_mutator3 = Mutator(filter2, SkRect::MakeEmpty());
Mutator mutator3 = Mutator(filter, DlRect());
Mutator other_mutator3 = Mutator(filter2, DlRect());
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(layer->paint_bounds(), path.GetBounds());
EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(layer->parent_mutators(),
std::vector{Mutator(ToSkMatrix(scale_matrix))});
EXPECT_EQ(layer->parent_mutators(), std::vector{Mutator(scale_matrix)});
EXPECT_EQ(layer->parent_matrix(), combined_matrix);
EXPECT_EQ(layer->parent_cull_rect(), local_cull_rect);
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)
// translation).
ASSERT_EQ(mutator->GetFilterMutation().GetFilterRect(),
SkRect::MakeLTRB(1, 1, 31, 31));
DlRect::MakeLTRB(1, 1, 31, 31));
DestroyShell(std::move(shell));
#endif // OS_FUCHSIA

View File

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

View File

@ -1637,10 +1637,13 @@ void PlatformViewAndroidJNIImpl::FlutterViewOnDisplayPlatformView(
mutators_stack.Begin();
while (iter != mutators_stack.End()) {
switch ((*iter)->GetType()) {
case kTransform: {
const SkMatrix& matrix = (*iter)->GetMatrix();
SkScalar matrix_array[9];
matrix.get9(matrix_array);
case MutatorType::kTransform: {
const DlMatrix& matrix = (*iter)->GetMatrix();
DlScalar matrix_array[9]{
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(
env, env->NewFloatArray(9));
@ -1650,40 +1653,65 @@ void PlatformViewAndroidJNIImpl::FlutterViewOnDisplayPlatformView(
transformMatrix.obj());
break;
}
case kClipRect: {
const SkRect& rect = (*iter)->GetRect();
env->CallVoidMethod(
mutatorsStack, g_mutators_stack_push_cliprect_method,
static_cast<int>(rect.left()), static_cast<int>(rect.top()),
static_cast<int>(rect.right()), static_cast<int>(rect.bottom()));
case MutatorType::kClipRect: {
const DlRect& rect = (*iter)->GetRect();
env->CallVoidMethod(mutatorsStack,
g_mutators_stack_push_cliprect_method,
static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.GetTop()), //
static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()));
break;
}
case kClipRRect: {
const SkRRect& rrect = (*iter)->GetRRect();
const SkRect& rect = rrect.rect();
const SkVector& upper_left = rrect.radii(SkRRect::kUpperLeft_Corner);
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);
case MutatorType::kClipRRect: {
const DlRoundRect& rrect = (*iter)->GetRRect();
const DlRect& rect = rrect.GetBounds();
const DlRoundingRadii radii = rrect.GetRadii();
SkScalar radiis[8] = {
upper_left.x(), upper_left.y(), upper_right.x(), upper_right.y(),
lower_right.x(), lower_right.y(), lower_left.x(), lower_left.y(),
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.left()), static_cast<int>(rect.top()),
static_cast<int>(rect.right()), static_cast<int>(rect.bottom()),
radiisArray.obj());
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::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;
}
// TODO(cyanglaz): Implement other mutators.
// https://github.com/flutter/flutter/issues/58426
case kClipPath:
case kOpacity:
case kBackdropFilter:
case MutatorType::kClipPath:
case MutatorType::kOpacity:
case MutatorType::kBackdropFilter:
break;
}
++iter;
@ -2017,10 +2045,13 @@ void PlatformViewAndroidJNIImpl::onDisplayPlatformView2(
mutators_stack.Begin();
while (iter != mutators_stack.End()) {
switch ((*iter)->GetType()) {
case kTransform: {
const SkMatrix& matrix = (*iter)->GetMatrix();
SkScalar matrix_array[9];
matrix.get9(matrix_array);
case MutatorType::kTransform: {
const DlMatrix& matrix = (*iter)->GetMatrix();
DlScalar matrix_array[9]{
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(
env, env->NewFloatArray(9));
@ -2030,98 +2061,192 @@ void PlatformViewAndroidJNIImpl::onDisplayPlatformView2(
transformMatrix.obj());
break;
}
case kClipRect: {
const SkRect& rect = (*iter)->GetRect();
env->CallVoidMethod(
mutatorsStack, g_mutators_stack_push_cliprect_method,
static_cast<int>(rect.left()), static_cast<int>(rect.top()),
static_cast<int>(rect.right()), static_cast<int>(rect.bottom()));
case MutatorType::kClipRect: {
const DlRect& rect = (*iter)->GetRect();
env->CallVoidMethod(mutatorsStack,
g_mutators_stack_push_cliprect_method,
static_cast<int>(rect.GetLeft()), //
static_cast<int>(rect.GetTop()), //
static_cast<int>(rect.GetRight()), //
static_cast<int>(rect.GetBottom()));
break;
}
case kClipRRect: {
const SkRRect& rrect = (*iter)->GetRRect();
const SkRect& rect = rrect.rect();
const SkVector& upper_left = rrect.radii(SkRRect::kUpperLeft_Corner);
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);
case MutatorType::kClipRRect: {
const DlRoundRect& rrect = (*iter)->GetRRect();
const DlRect& rect = rrect.GetBounds();
const DlRoundingRadii& radii = rrect.GetRadii();
SkScalar radiis[8] = {
upper_left.x(), upper_left.y(), upper_right.x(), upper_right.y(),
lower_right.x(), lower_right.y(), lower_left.x(), lower_left.y(),
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.left()), static_cast<int>(rect.top()),
static_cast<int>(rect.right()), static_cast<int>(rect.bottom()),
radiisArray.obj());
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 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();
env->CallVoidMethod(mutatorsStack, g_mutators_stack_push_opacity_method,
opacity);
break;
}
// TODO(cyanglaz): Implement other mutators.
// https://github.com/flutter/flutter/issues/58426
case kClipPath: {
const SkPath& path = (*iter)->GetPath();
case MutatorType::kClipPath: {
auto& dlPath = (*iter)->GetPath();
// Sometimes a kClipPath mutator is actually housing a simpler
// 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 =
env->NewObject(path_class->obj(), path_constructor);
SkPath::Iter pathIter(path, false);
SkPoint points[4];
SkPath::Verb verb;
bool subpath_needs_close = false;
std::optional<flutter::DlPoint> pending_moveto;
while ((verb = pathIter.next(points)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kMove_Verb: {
env->CallVoidMethod(androidPath, path_move_to_method,
points[0].fX, points[0].fY);
auto resolve_moveto = [&env, &pending_moveto, &androidPath]() {
if (pending_moveto.has_value()) {
env->CallVoidMethod(androidPath, path_move_to_method,
pending_moveto->x, pending_moveto->y);
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;
}
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,
points[1].fX, points[1].fY);
linear->p2.x, linear->p2.y);
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,
points[1].fX, points[1].fY, points[2].fX,
points[2].fY);
quadratic->cp.x, quadratic->cp.y,
quadratic->p2.x, quadratic->p2.y);
break;
}
case SkPath::kCubic_Verb: {
env->CallVoidMethod(androidPath, path_cubic_to_method,
points[1].fX, points[1].fY, points[2].fX,
points[2].fY, points[3].fX, points[3].fY);
break;
}
case SkPath::kConic_Verb: {
case impeller::Path::ComponentType::kConic: {
const impeller::ConicPathComponent* conic = it.conic();
FML_DCHECK(conic != nullptr);
resolve_moveto();
FML_DCHECK(path_conic_to_method != nullptr);
env->CallVoidMethod(androidPath, path_conic_to_method,
points[1].fX, points[1].fY, points[2].fX,
points[2].fY, pathIter.conicWeight());
conic->cp.x, conic->cp.y, //
conic->p2.x, conic->p2.y, conic->weight);
break;
}
case SkPath::kClose_Verb: {
env->CallVoidMethod(androidPath, path_close_method);
case impeller::Path::ComponentType::kCubic: {
const impeller::CubicPathComponent* cubic = it.cubic();
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;
}
default:
break;
}
}
if (subpath_needs_close) {
env->CallVoidMethod(androidPath, path_close_method);
}
env->CallVoidMethod(mutatorsStack,
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;
}
++iter;

View File

@ -12,26 +12,35 @@
FLUTTER_ASSERT_ARC
static constexpr int kMaxPointsInVerb = 4;
namespace {
CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) {
return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft,
clipSkRect.fBottom - clipSkRect.fTop);
static CGRect GetCGRectFromDlRect(const flutter::DlRect& clipDlRect) {
return CGRectMake(clipDlRect.GetX(), //
clipDlRect.GetY(), //
clipDlRect.GetWidth(), //
clipDlRect.GetHeight());
}
CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) {
// Skia only supports 2D transform so we don't map z.
CATransform3D GetCATransform3DFromDlMatrix(const flutter::DlMatrix& matrix) {
CATransform3D transform = CATransform3DIdentity;
transform.m11 = matrix.getScaleX();
transform.m21 = matrix.getSkewX();
transform.m41 = matrix.getTranslateX();
transform.m14 = matrix.getPerspX();
transform.m11 = matrix.m[0];
transform.m12 = matrix.m[1];
transform.m13 = matrix.m[2];
transform.m14 = matrix.m[3];
transform.m12 = matrix.getSkewY();
transform.m22 = matrix.getScaleY();
transform.m42 = matrix.getTranslateY();
transform.m24 = matrix.getPerspY();
transform.m21 = matrix.m[4];
transform.m22 = matrix.m[5];
transform.m23 = matrix.m[6];
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;
}
} // namespace
@ -278,12 +287,12 @@ static BOOL _preparedOnce = NO;
}
}
- (void)clipRect:(const SkRect&)clipSkRect matrix:(const SkMatrix&)matrix {
CGRect clipRect = GetCGRectFromSkRect(clipSkRect);
- (void)clipRect:(const flutter::DlRect&)clipDlRect matrix:(const flutter::DlMatrix&)matrix {
CGRect clipRect = GetCGRectFromDlRect(clipDlRect);
CGPathRef path = CGPathCreateWithRect(clipRect, nil);
// The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints =
CATransform3DConcat(GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
CATransform3DConcat(GetCATransform3DFromDlMatrix(matrix), _reverseScreenScale);
paths_.push_back([self getTransformedPath:path matrix:matrixInPoints]);
CGAffineTransform affine = [self affineWithMatrix:matrixInPoints];
// 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 {
containsNonRectPath_ = YES;
CGPathRef pathRef = nullptr;
switch (clipSkRRect.getType()) {
case SkRRect::kEmpty_Type: {
break;
}
case SkRRect::kRect_Type: {
[self clipRect:clipSkRRect.rect() matrix:matrix];
return;
}
case SkRRect::kOval_Type:
case SkRRect::kSimple_Type: {
CGRect clipRect = GetCGRectFromSkRect(clipSkRRect.rect());
pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(),
clipSkRRect.getSimpleRadii().y(), nil);
break;
}
case SkRRect::kNinePatch_Type:
case SkRRect::kComplex_Type: {
- (void)clipRRect:(const flutter::DlRoundRect&)clipDlRRect matrix:(const flutter::DlMatrix&)matrix {
if (clipDlRRect.IsEmpty()) {
return;
} else if (clipDlRRect.IsRect()) {
[self clipRect:clipDlRRect.GetBounds() matrix:matrix];
return;
} else {
CGPathRef pathRef = nullptr;
containsNonRectPath_ = YES;
if (clipDlRRect.GetRadii().AreAllCornersSame()) {
CGRect clipRect = GetCGRectFromDlRect(clipDlRRect.GetBounds());
auto radii = clipDlRRect.GetRadii();
pathRef =
CGPathCreateWithRoundedRect(clipRect, radii.top_left.width, radii.top_left.height, nil);
} else {
CGMutablePathRef mutablePathRef = CGPathCreateMutable();
// Complex types, we manually add each corner.
SkRect clipSkRect = clipSkRRect.rect();
SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner);
SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner);
SkVector bottomRightRadii = clipSkRRect.radii(SkRRect::kLowerRight_Corner);
SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner);
flutter::DlRect clipDlRect = clipDlRRect.GetBounds();
auto left = clipDlRect.GetLeft();
auto top = clipDlRect.GetTop();
auto right = clipDlRect.GetRight();
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
// 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.
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.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(),
clipSkRect.fTop);
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop,
clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(),
clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y());
CGPathAddLineToPoint(mutablePathRef, nil, //
right - top_right.width, top);
CGPathAddCurveToPoint(mutablePathRef, nil, //
right, top, //
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.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight,
clipSkRect.fBottom - bottomRightRadii.y());
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom,
clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom,
clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom);
CGPathAddLineToPoint(mutablePathRef, nil, //
right, bottom - bottom_right.height);
CGPathAddCurveToPoint(mutablePathRef, nil, //
right, bottom, //
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.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(),
clipSkRect.fBottom);
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom,
clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(),
clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y());
CGPathAddLineToPoint(mutablePathRef, nil, //
left + bottom_left.width, bottom);
CGPathAddCurveToPoint(mutablePathRef, nil, //
left, bottom, //
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.
CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft,
clipSkRect.fTop + topLeftRadii.y());
CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop,
clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop,
clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop);
CGPathAddLineToPoint(mutablePathRef, nil, //
left, top + top_left.height);
CGPathAddCurveToPoint(mutablePathRef, nil, //
left, top, //
left + top_left.width, top, //
left + top_left.width, top);
CGPathCloseSubpath(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 {
if (!path.isValid()) {
return;
}
if (path.isEmpty()) {
return;
}
- (void)clipPath:(const flutter::DlPath&)dlPath matrix:(const flutter::DlMatrix&)matrix {
containsNonRectPath_ = YES;
CGMutablePathRef pathRef = CGPathCreateMutable();
bool subpath_needs_close = false;
std::optional<flutter::DlPoint> pending_moveto;
// Loop through all verbs and translate them into CGPath
SkPath::Iter iter(path, true);
SkPoint pts[kMaxPointsInVerb];
SkPath::Verb verb = iter.next(pts);
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]);
auto resolve_moveto = [&pending_moveto, &pathRef]() {
if (pending_moveto.has_value()) {
CGPathMoveToPoint(pathRef, nil, pending_moveto->x, pending_moveto->y);
pending_moveto.reset();
}
switch (verb) {
case SkPath::kMove_Verb: {
CGPathMoveToPoint(pathRef, nil, pts[0].x(), pts[0].y());
last_pt_from_last_verb = pts[0];
};
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) {
CGPathCloseSubpath(pathRef);
}
pending_moveto = contour->destination;
subpath_needs_close = contour->IsClosed();
break;
}
case SkPath::kLine_Verb: {
CGPathAddLineToPoint(pathRef, nil, pts[1].x(), pts[1].y());
last_pt_from_last_verb = pts[1];
case impeller::Path::ComponentType::kLinear: {
const impeller::LinearPathComponent* linear = it.linear();
FML_DCHECK(linear != nullptr);
resolve_moveto();
CGPathAddLineToPoint(pathRef, nil, linear->p2.x, linear->p2.y);
break;
}
case SkPath::kQuad_Verb: {
CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
last_pt_from_last_verb = pts[2];
case impeller::Path::ComponentType::kQuadratic: {
const impeller::QuadraticPathComponent* quadratic = it.quadratic();
FML_DCHECK(quadratic != nullptr);
resolve_moveto();
CGPathAddQuadCurveToPoint(pathRef, nil, //
quadratic->cp.x, quadratic->cp.y, //
quadratic->p2.x, quadratic->p2.y);
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.
// TODO(cyanglaz): Better approximate the conic path.
// https://github.com/flutter/flutter/issues/35062
CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
last_pt_from_last_verb = pts[2];
CGPathAddQuadCurveToPoint(pathRef, nil, //
conic->cp.x, conic->cp.y, //
conic->p2.x, conic->p2.y);
break;
}
case SkPath::kCubic_Verb: {
CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(),
pts[3].x(), pts[3].y());
last_pt_from_last_verb = pts[3];
break;
}
case SkPath::kClose_Verb: {
CGPathCloseSubpath(pathRef);
break;
}
case SkPath::kDone_Verb: {
case impeller::Path::ComponentType::kCubic: {
const impeller::CubicPathComponent* cubic = it.cubic();
FML_DCHECK(cubic != nullptr);
resolve_moveto();
CGPathAddCurveToPoint(pathRef, nil, //
cubic->cp1.x, cubic->cp1.y, //
cubic->cp2.x, cubic->cp2.y, //
cubic->p2.x, cubic->p2.y);
break;
}
}
verb = iter.next(pts);
}
if (subpath_needs_close) {
CGPathCloseSubpath(pathRef);
}
// The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints =
CATransform3DConcat(GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
CATransform3DConcat(GetCATransform3DFromDlMatrix(matrix), _reverseScreenScale);
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
}

View File

@ -5,6 +5,7 @@
#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/utils/dl_matrix_clip_tracker.h"
#include "flutter/flow/surface_frame.h"
#include "flutter/flow/view_slicer.h"
#include "flutter/fml/make_copyable.h"
@ -15,6 +16,10 @@
#include "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
using flutter::DlMatrix;
using flutter::DlRect;
using flutter::DlRoundRect;
static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5;
struct LayerData {
@ -38,18 +43,27 @@ struct PlatformViewData {
// Converts a SkMatrix to CATransform3D.
//
// Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4.
static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) {
// Skia only supports 2D transform so we don't map z.
static CATransform3D GetCATransform3DFromDlMatrix(const DlMatrix& matrix) {
CATransform3D transform = CATransform3DIdentity;
transform.m11 = matrix.getScaleX();
transform.m21 = matrix.getSkewX();
transform.m41 = matrix.getTranslateX();
transform.m14 = matrix.getPerspX();
transform.m11 = matrix.m[0];
transform.m12 = matrix.m[1];
transform.m13 = matrix.m[2];
transform.m14 = matrix.m[3];
transform.m12 = matrix.getSkewY();
transform.m22 = matrix.getScaleY();
transform.m42 = matrix.getTranslateY();
transform.m24 = matrix.getPerspY();
transform.m21 = matrix.m[4];
transform.m22 = matrix.m[5];
transform.m23 = matrix.m[6];
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;
}
@ -62,57 +76,11 @@ static void ResetAnchor(CALayer* layer) {
layer.position = CGPointZero;
}
static CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) {
return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft,
clipSkRect.fBottom - clipSkRect.fTop);
}
// 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);
static CGRect GetCGRectFromDlRect(const DlRect& clipDlRect) {
return CGRectMake(clipDlRect.GetLeft(), //
clipDlRect.GetTop(), //
clipDlRect.GetWidth(), //
clipDlRect.GetHeight());
}
@interface FlutterPlatformViewsController ()
@ -531,7 +499,8 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
ResetAnchor(embeddedView.layer);
ChildClippingView* clipView = (ChildClippingView*)embeddedView.superview;
SkMatrix transformMatrix;
DlMatrix transformMatrix;
const DlRect& dlBoundingRect = flutter::ToDlRect(boundingRect);
NSMutableArray* blurFilters = [[NSMutableArray alloc] init];
FML_DCHECK(!clipView.maskView ||
[clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]);
@ -543,13 +512,13 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
auto iter = mutatorsStack.Begin();
while (iter != mutatorsStack.End()) {
switch ((*iter)->GetType()) {
case flutter::kTransform: {
transformMatrix.preConcat((*iter)->GetMatrix());
case flutter::MutatorType::kTransform: {
transformMatrix = transformMatrix * (*iter)->GetMatrix();
break;
}
case flutter::kClipRect: {
if (ClipRectContainsPlatformViewBoundingRect((*iter)->GetRect(), boundingRect,
transformMatrix)) {
case flutter::MutatorType::kClipRect: {
if (flutter::DisplayListMatrixClipState::TransformedRectCoversBounds(
(*iter)->GetRect(), transformMatrix, dlBoundingRect)) {
break;
}
[self clipViewSetMaskView:clipView];
@ -557,9 +526,9 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
matrix:transformMatrix];
break;
}
case flutter::kClipRRect: {
if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), boundingRect,
transformMatrix)) {
case flutter::MutatorType::kClipRRect: {
if (flutter::DisplayListMatrixClipState::TransformedRRectCoversBounds(
(*iter)->GetRRect(), transformMatrix, dlBoundingRect)) {
break;
}
[self clipViewSetMaskView:clipView];
@ -567,7 +536,17 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
matrix:transformMatrix];
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
// rect. See `ClipRRectContainsPlatformViewBoundingRect`.
// https://github.com/flutter/flutter/issues/118650
@ -576,15 +555,15 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
matrix:transformMatrix];
break;
}
case flutter::kOpacity:
case flutter::MutatorType::kOpacity:
embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha;
break;
case flutter::kBackdropFilter: {
case flutter::MutatorType::kBackdropFilter: {
// Only support DlBlurImageFilter for BackdropFilter.
if (!self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
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 = CGRectApplyAffineTransform(
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
// 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.
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.
// 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
// 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 {

View File

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

View File

@ -37,17 +37,17 @@
// Adds a clip rect operation 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.
//
// 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.
//
// 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

View File

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

View File

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

View File

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

View File

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