[CP-stable] [Impeller] Fix positioning of text shadow masks (#188766)
This pull request is created manually per (https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request)
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.
### Issue Link:
What is the link to the issue this cherry-pick is addressing?
https://github.com/flutter/flutter/issues/188035
### Impact Description:
Apps that use shadows on Text will have those shadows separate from the text and appear at the coordinate origin of the nearest widget that wraps things with some kind of SaveLayer or engine layer.
### Changelog Description:
Explain this cherry pick:
* Ensures that shadows track the position of text even when enclosed in a SaveLayer
* Prior to this fix, those shadows would appear at the origin of such a SaveLayer - typically the upper or lower corner of one of the parent widgets.
* This would happen on all platforms.
[flutter/188035] When rendering text with shadows, the shadows would appear elsewhere on the screen, separate from the text
### Workaround:
No known workarounds exist.
### Risk:
What is the risk level of this cherry-pick?
### Test Coverage:
Are you confident that your fix is well-tested by automated tests?
### Validation Steps:
The golden images created by this PR will verify the code is correct if the shadows on the text appear directly underneath each rendered string.
diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_text_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_text_unittests.cc
index 30b884e..f1e96d9 100644
--- a/engine/src/flutter/impeller/display_list/aiks_dl_text_unittests.cc
+++ b/engine/src/flutter/impeller/display_list/aiks_dl_text_unittests.cc
@@ -1055,5 +1055,31 @@
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
+TEST_P(AiksTest, TextWithShadowAndPosition) {
+ DisplayListBuilder builder;
+ builder.Scale(GetContentScale().x, GetContentScale().y);
+ builder.Clear(DlColor::kWhite());
+
+ auto frame = MakeDefaultTextFrame("Hello", 25.0f);
+ auto text = DlTextImpeller::Make(frame);
+ DlPaint paint = DlPaint().setColor(DlColor::kMagenta());
+ DlPaint shadow_paint_ctm = DlPaint().setMaskFilter(
+ DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5.0f, true));
+ DlPaint shadow_paint_no_ctm = DlPaint().setMaskFilter(
+ DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5.0f, false));
+
+ builder.Translate(100, 100);
+ builder.Scale(4, 4);
+ for (int x = 10; x <= 100; x += 30) {
+ builder.DrawText(text, x, 20, shadow_paint_ctm);
+ builder.DrawText(text, x, 20, paint);
+
+ builder.DrawText(text, x, 50, shadow_paint_no_ctm);
+ builder.DrawText(text, x, 50, paint);
+ }
+
+ ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
+}
+
} // namespace testing
} // namespace impeller
diff --git a/engine/src/flutter/impeller/display_list/canvas.cc b/engine/src/flutter/impeller/display_list/canvas.cc
index 6cff7f5..1b67031 100644
--- a/engine/src/flutter/impeller/display_list/canvas.cc
+++ b/engine/src/flutter/impeller/display_list/canvas.cc
@@ -1947,7 +1947,7 @@
? std::optional(paint.stroke)
: std::nullopt);
- entity.SetTransform(GetCurrentTransform());
+ entity.SetTransform(GetCurrentTransform().Translate(position));
if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
paint)) {
diff --git a/engine/src/flutter/impeller/entity/contents/text_contents.cc b/engine/src/flutter/impeller/entity/contents/text_contents.cc
index 2f4c696..d02d115 100644
--- a/engine/src/flutter/impeller/entity/contents/text_contents.cc
+++ b/engine/src/flutter/impeller/entity/contents/text_contents.cc
@@ -58,9 +58,7 @@
}
std::optional<Rect> TextContents::GetCoverage(const Entity& entity) const {
- const Matrix entity_offset_transform =
- entity.GetTransform() * Matrix::MakeTranslation(position_);
- return frame_->GetBounds().TransformBounds(entity_offset_transform);
+ return frame_->GetBounds().TransformBounds(entity.GetTransform());
}
void TextContents::SetTextProperties(
@@ -92,7 +90,7 @@
void TextContents::ComputeVertexData(
VS::PerVertexData* vtx_contents,
- const Matrix& entity_transform,
+ const Matrix& entity_offset_transform,
const std::shared_ptr<TextFrame>& frame,
Point position,
const Matrix& screen_transform,
@@ -108,9 +106,6 @@
constexpr std::array<Point, 4> unit_points = {Point{0, 0}, Point{1, 0},
Point{0, 1}, Point{1, 1}};
- Matrix entity_offset_transform =
- entity_transform * Matrix::MakeTranslation(position);
-
ISize atlas_size = atlas->GetTexture()->GetSize();
bool is_translation_scale = entity_offset_transform.IsTranslationScaleOnly();
Matrix basis_transform = entity_offset_transform.Basis();