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 f12411811f..555c9ea276 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 @@ -207,6 +207,44 @@ TEST_P(AiksTest, CanRenderTextFrameWithFractionScaling) { 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 { + 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) { // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens. std::array phase_offsets = { diff --git a/engine/src/flutter/impeller/entity/contents/text_contents.cc b/engine/src/flutter/impeller/entity/contents/text_contents.cc index a76f87a55b..df38d351c5 100644 --- a/engine/src/flutter/impeller/entity/contents/text_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/text_contents.cc @@ -175,11 +175,12 @@ void TextContents::ComputeVertexData( Point uv_origin = (atlas_glyph_bounds.GetLeftTop()) / 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 = // This is for RTL text. - (basis_transform.m[0] < 0 ? Matrix::MakeScale({-1, 1, 1}) - : Matrix()) * - glyph_bounds.GetLeftTop() + + unscaled_basis * glyph_bounds.GetLeftTop() + (basis_transform * glyph_position.position); Point screen_glyph_position = @@ -189,9 +190,7 @@ void TextContents::ComputeVertexData( Point position; if (is_translation_scale) { position = (screen_glyph_position + - ((basis_transform.m[0] < 0 ? Matrix::MakeScale({-1, 1, 1}) - : Matrix()) * - point * glyph_bounds.GetSize())) + (unscaled_basis * point * glyph_bounds.GetSize())) .Round(); } else { position = entity_transform * diff --git a/engine/src/flutter/testing/impeller_golden_tests_output.txt b/engine/src/flutter/testing/impeller_golden_tests_output.txt index b10d44d8af..f3b05af8ed 100644 --- a/engine/src/flutter/testing/impeller_golden_tests_output.txt +++ b/engine/src/flutter/testing/impeller_golden_tests_output.txt @@ -919,6 +919,9 @@ impeller_Play_AiksTest_TextForegroundShaderWithTransform_Vulkan.png impeller_Play_AiksTest_TextFrameSubpixelAlignment_Metal.png impeller_Play_AiksTest_TextFrameSubpixelAlignment_OpenGLES.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_OpenGLES.png impeller_Play_AiksTest_ToImageFromImage_Vulkan.png