Fixes rendering text rotated 180 degrees (#165008)

fixes https://github.com/flutter/flutter/issues/164958

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
gaaclarke 2025-03-12 11:14:16 -07:00 committed by GitHub
parent 6316b48bca
commit f0992e0965
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 6 deletions

View File

@ -207,6 +207,44 @@ TEST_P(AiksTest, CanRenderTextFrameWithFractionScaling) {
ASSERT_TRUE(OpenPlaygroundHere(callback)); ASSERT_TRUE(OpenPlaygroundHere(callback));
} }
// https://github.com/flutter/flutter/issues/164958
TEST_P(AiksTest, TextRotated180Degrees) {
float fpivot[2] = {200 + 30, 200 - 20};
float rotation = 180;
float foffset[2] = {200, 200};
auto callback = [&]() -> sk_sp<DisplayList> {
if (AiksTest::ImGuiBegin("Controls", nullptr,
ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::SliderFloat("pivotx", &fpivot[0], 0, 300);
ImGui::SliderFloat("pivoty", &fpivot[1], 0, 300);
ImGui::SliderFloat("rotation", &rotation, 0, 360);
ImGui::SliderFloat("foffsetx", &foffset[0], 0, 300);
ImGui::SliderFloat("foffsety", &foffset[1], 0, 300);
ImGui::End();
}
DisplayListBuilder builder;
builder.Scale(GetContentScale().x, GetContentScale().y);
builder.DrawPaint(DlPaint().setColor(DlColor(0xffffeeff)));
builder.Save();
DlPoint pivot = Point(fpivot[0], fpivot[1]);
builder.Translate(pivot.x, pivot.y);
builder.Rotate(rotation);
builder.Translate(-pivot.x, -pivot.y);
RenderTextInCanvasSkia(GetContext(), builder, "test", "Roboto-Regular.ttf",
TextRenderOptions{
.color = DlColor::kBlack(),
.position = DlPoint(foffset[0], foffset[1]),
});
builder.Restore();
return builder.Build();
};
ASSERT_TRUE(OpenPlaygroundHere(callback));
}
TEST_P(AiksTest, TextFrameSubpixelAlignment) { TEST_P(AiksTest, TextFrameSubpixelAlignment) {
// "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens. // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
std::array<Scalar, 20> phase_offsets = { std::array<Scalar, 20> phase_offsets = {

View File

@ -175,11 +175,12 @@ void TextContents::ComputeVertexData(
Point uv_origin = (atlas_glyph_bounds.GetLeftTop()) / atlas_size; Point uv_origin = (atlas_glyph_bounds.GetLeftTop()) / atlas_size;
Point uv_size = SizeToPoint(atlas_glyph_bounds.GetSize()) / atlas_size; Point uv_size = SizeToPoint(atlas_glyph_bounds.GetSize()) / atlas_size;
Matrix unscaled_basis =
Matrix::MakeScale({basis_transform.m[0] > 0 ? 1.f : -1.f,
basis_transform.m[5] > 0 ? 1.f : -1.f, 1.f});
Point unrounded_glyph_position = Point unrounded_glyph_position =
// This is for RTL text. // This is for RTL text.
(basis_transform.m[0] < 0 ? Matrix::MakeScale({-1, 1, 1}) unscaled_basis * glyph_bounds.GetLeftTop() +
: Matrix()) *
glyph_bounds.GetLeftTop() +
(basis_transform * glyph_position.position); (basis_transform * glyph_position.position);
Point screen_glyph_position = Point screen_glyph_position =
@ -189,9 +190,7 @@ void TextContents::ComputeVertexData(
Point position; Point position;
if (is_translation_scale) { if (is_translation_scale) {
position = (screen_glyph_position + position = (screen_glyph_position +
((basis_transform.m[0] < 0 ? Matrix::MakeScale({-1, 1, 1}) (unscaled_basis * point * glyph_bounds.GetSize()))
: Matrix()) *
point * glyph_bounds.GetSize()))
.Round(); .Round();
} else { } else {
position = entity_transform * position = entity_transform *

View File

@ -919,6 +919,9 @@ impeller_Play_AiksTest_TextForegroundShaderWithTransform_Vulkan.png
impeller_Play_AiksTest_TextFrameSubpixelAlignment_Metal.png impeller_Play_AiksTest_TextFrameSubpixelAlignment_Metal.png
impeller_Play_AiksTest_TextFrameSubpixelAlignment_OpenGLES.png impeller_Play_AiksTest_TextFrameSubpixelAlignment_OpenGLES.png
impeller_Play_AiksTest_TextFrameSubpixelAlignment_Vulkan.png impeller_Play_AiksTest_TextFrameSubpixelAlignment_Vulkan.png
impeller_Play_AiksTest_TextRotated180Degrees_Metal.png
impeller_Play_AiksTest_TextRotated180Degrees_OpenGLES.png
impeller_Play_AiksTest_TextRotated180Degrees_Vulkan.png
impeller_Play_AiksTest_ToImageFromImage_Metal.png impeller_Play_AiksTest_ToImageFromImage_Metal.png
impeller_Play_AiksTest_ToImageFromImage_OpenGLES.png impeller_Play_AiksTest_ToImageFromImage_OpenGLES.png
impeller_Play_AiksTest_ToImageFromImage_Vulkan.png impeller_Play_AiksTest_ToImageFromImage_Vulkan.png