diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 96bd9eccd63c8..5bf6cb10c0db9 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -3192,6 +3192,24 @@ TEST_P(AiksTest, StrokedPathWithMoveToThenCloseDrawnCorrectly) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, CanRenderTextWithLargePerspectiveTransform) { + // Verifies that text scales are clamped to work around + // https://github.com/flutter/flutter/issues/136112 . + + Canvas canvas; + Paint save_paint; + canvas.SaveLayer(save_paint); + canvas.Transform(Matrix(2000, 0, 0, 0, // + 0, 2000, 0, 0, // + 0, 0, -1, 9000, // + 0, 0, -1, 7000 // + )); + + ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world", + "Roboto-Regular.ttf")); + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + } // namespace testing } // namespace impeller diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index 0282807fccfbb..14b7e2d493948 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -2566,6 +2566,7 @@ TEST_P(EntityTest, TextContentsCeilsGlyphScaleToDecimal) { ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f, 12), 0.53f); ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f, 12), 2.1f); ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f); + ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f, 12), 48.0f); } TEST_P(EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass) { diff --git a/impeller/typographer/text_frame.cc b/impeller/typographer/text_frame.cc index 5e38b68a76729..75955bf30bf45 100644 --- a/impeller/typographer/text_frame.cc +++ b/impeller/typographer/text_frame.cc @@ -64,7 +64,12 @@ bool TextFrame::MaybeHasOverlapping() const { // static Scalar TextFrame::RoundScaledFontSize(Scalar scale, Scalar point_size) { - return std::round(scale * 100) / 100; + // An arbitrarily chosen maximum text scale to ensure that regardless of the + // CTM, a glyph will fit in the atlas. If we clamp significantly, this may + // reduce fidelity but is preferable to the alternative of failing to render. + constexpr Scalar kMaximumTextScale = 48; + Scalar result = std::round(scale * 100) / 100; + return std::clamp(result, 0.0f, kMaximumTextScale); } void TextFrame::CollectUniqueFontGlyphPairs(FontGlyphMap& glyph_map, diff --git a/testing/impeller_golden_tests_output.txt b/testing/impeller_golden_tests_output.txt index 17055406dccd4..c79b5c696fd24 100644 --- a/testing/impeller_golden_tests_output.txt +++ b/testing/impeller_golden_tests_output.txt @@ -451,6 +451,9 @@ impeller_Play_AiksTest_CanRenderTextInSaveLayer_Vulkan.png impeller_Play_AiksTest_CanRenderTextOutsideBoundaries_Metal.png impeller_Play_AiksTest_CanRenderTextOutsideBoundaries_OpenGLES.png impeller_Play_AiksTest_CanRenderTextOutsideBoundaries_Vulkan.png +impeller_Play_AiksTest_CanRenderTextWithLargePerspectiveTransform_Metal.png +impeller_Play_AiksTest_CanRenderTextWithLargePerspectiveTransform_OpenGLES.png +impeller_Play_AiksTest_CanRenderTextWithLargePerspectiveTransform_Vulkan.png impeller_Play_AiksTest_CanRenderThickCurvedStrokes_Metal.png impeller_Play_AiksTest_CanRenderThickCurvedStrokes_OpenGLES.png impeller_Play_AiksTest_CanRenderThickCurvedStrokes_Vulkan.png