From 0aaa84e5c9856c2c08e0cf370b36f4fd8ae38048 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 24 Mar 2022 23:13:24 -0700 Subject: [PATCH] Render glyphs at the correct resolution with respect to the current transform (#101) --- .../display_list/display_list_dispatcher.cc | 10 ++++--- impeller/geometry/constants.h | 3 ++ impeller/geometry/geometry_unittests.cc | 30 +++++++++++++++++++ impeller/geometry/matrix.cc | 9 ++++++ impeller/geometry/matrix.h | 2 ++ impeller/geometry/point.h | 14 +++++++++ impeller/geometry/scalar.h | 2 -- .../backends/skia/text_frame_skia.cc | 8 +++-- .../backends/skia/text_frame_skia.h | 2 +- .../backends/skia/text_render_context_skia.cc | 21 +++++++------ impeller/typographer/font.h | 14 ++++++--- impeller/typographer/glyph_atlas.h | 2 +- 12 files changed, 93 insertions(+), 24 deletions(-) diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index b1e23010cda72..52950a8de4e8b 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -247,7 +247,8 @@ void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) { } // |flutter::Dispatcher| -void DisplayListDispatcher::setImageFilter(const flutter::DlImageFilter* filter) { +void DisplayListDispatcher::setImageFilter( + const flutter::DlImageFilter* filter) { UNIMPLEMENTED; } @@ -609,9 +610,10 @@ void DisplayListDispatcher::drawDisplayList( void DisplayListDispatcher::drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) { - canvas_.DrawTextFrame(TextFrameFromTextBlob(blob), // - impeller::Point{x, y}, // - paint_ // + Scalar scale = canvas_.GetCurrentTransformation().GetMaxBasisLength(); + canvas_.DrawTextFrame(TextFrameFromTextBlob(blob, scale), // + impeller::Point{x, y}, // + paint_ // ); } diff --git a/impeller/geometry/constants.h b/impeller/geometry/constants.h index 8385b7eccb06e..a0cadfffcc483 100644 --- a/impeller/geometry/constants.h +++ b/impeller/geometry/constants.h @@ -43,4 +43,7 @@ constexpr float kSqrt2 = 1.41421356237309504880; // 1/sqrt(2) constexpr float k1OverSqrt2 = 0.70710678118654752440; +// 0.001 +constexpr float kEhCloseEnough = 1e-3; + } // namespace impeller diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 35b6641b574fb..fbdd2c9c7d6b1 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -212,6 +212,21 @@ TEST(GeometryTest, MatrixTransformDirection) { } } +TEST(GeometryTest, MatrixGetMaxBasisLength) { + { + auto m = Matrix::MakeScale({3, 1, 1}); + ASSERT_EQ(m.GetMaxBasisLength(), 3); + + m = m * Matrix::MakeSkew(0, 4); + ASSERT_EQ(m.GetMaxBasisLength(), 5); + } + + { + auto m = Matrix::MakeScale({-3, 4, 2}); + ASSERT_EQ(m.GetMaxBasisLength(), 4); + } +} + TEST(GeometryTest, QuaternionLerp) { auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0}; auto q2 = Quaternion{{0.0, 0.0, 1.0}, M_PI_4}; @@ -570,6 +585,21 @@ TEST(GeometryTest, CanUsePointAssignmentOperators) { ASSERT_EQ(p.x, 1u); ASSERT_EQ(p.y, 2u); } + + // Arithmetic type on RHS + { + IPoint p(1, 2); + p *= 3; + ASSERT_EQ(p.x, 3u); + ASSERT_EQ(p.y, 6u); + } + + { + IPoint p(3, 6); + p /= 3; + ASSERT_EQ(p.x, 1u); + ASSERT_EQ(p.y, 2u); + } } TEST(GeometryTest, PointDotProduct) { diff --git a/impeller/geometry/matrix.cc b/impeller/geometry/matrix.cc index f5aaa3458b500..70ede5866aee8 100644 --- a/impeller/geometry/matrix.cc +++ b/impeller/geometry/matrix.cc @@ -193,6 +193,15 @@ Scalar Matrix::GetDeterminant() const { return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; } +Scalar Matrix::GetMaxBasisLength() const { + Scalar max = 0; + for (int i = 0; i < 3; i++) { + max = std::max(max, + e[i][0] * e[i][0] + e[i][1] * e[i][1] + e[i][2] * e[i][2]); + } + return std::sqrt(max); +} + /* * Adapted for Impeller from Graphics Gems: * http://www.realtimerendering.com/resources/GraphicsGems/gemsii/unmatrix.c diff --git a/impeller/geometry/matrix.h b/impeller/geometry/matrix.h index c3178d71953e1..539ae84ae37bd 100644 --- a/impeller/geometry/matrix.h +++ b/impeller/geometry/matrix.h @@ -219,6 +219,8 @@ struct Matrix { Scalar GetDeterminant() const; + Scalar GetMaxBasisLength() const; + constexpr bool IsAffine() const { return (m[2] == 0 && m[3] == 0 && m[6] == 0 && m[7] == 0 && m[8] == 0 && m[9] == 0 && m[10] == 1 && m[11] == 0 && m[14] == 0 && m[15] == 1); diff --git a/impeller/geometry/point.h b/impeller/geometry/point.h index 957ab2ad32d26..7b511ed9d64a6 100644 --- a/impeller/geometry/point.h +++ b/impeller/geometry/point.h @@ -88,6 +88,13 @@ struct TPoint { return *this; } + template >> + inline TPoint operator*=(U scale) { + x *= static_cast(scale); + y *= static_cast(scale); + return *this; + } + template inline TPoint operator/=(const TPoint& p) { x /= static_cast(p.x); @@ -102,6 +109,13 @@ struct TPoint { return *this; } + template >> + inline TPoint operator/=(U scale) { + x /= static_cast(scale); + y /= static_cast(scale); + return *this; + } + constexpr TPoint operator-() const { return {-x, -y}; } constexpr TPoint operator+(const TPoint& p) const { diff --git a/impeller/geometry/scalar.h b/impeller/geometry/scalar.h index 1a27bb3aa5e49..3ca2f1dab6638 100644 --- a/impeller/geometry/scalar.h +++ b/impeller/geometry/scalar.h @@ -14,8 +14,6 @@ namespace impeller { using Scalar = float; -constexpr Scalar kEhCloseEnough = 1e-3f; - template >> constexpr T Absolute(const T& val) { return val >= T{} ? val : -val; diff --git a/impeller/typographer/backends/skia/text_frame_skia.cc b/impeller/typographer/backends/skia/text_frame_skia.cc index d9db8e36f4757..4f92b300fb309 100644 --- a/impeller/typographer/backends/skia/text_frame_skia.cc +++ b/impeller/typographer/backends/skia/text_frame_skia.cc @@ -12,13 +12,14 @@ namespace impeller { -static Font ToFont(const SkFont& font) { +static Font ToFont(const SkFont& font, Scalar scale) { auto typeface = std::make_shared(font.refTypefaceOrDefault()); SkFontMetrics sk_metrics; font.getMetrics(&sk_metrics); Font::Metrics metrics; + metrics.scale = scale; metrics.point_size = font.getSize(); metrics.ascent = sk_metrics.fAscent; metrics.descent = sk_metrics.fDescent; @@ -28,7 +29,8 @@ static Font ToFont(const SkFont& font) { return Font{std::move(typeface), std::move(metrics)}; } -TextFrame TextFrameFromTextBlob(sk_sp blob) { +TextFrame TextFrameFromTextBlob(sk_sp blob, + Scalar scale) { if (!blob) { return {}; } @@ -36,7 +38,7 @@ TextFrame TextFrameFromTextBlob(sk_sp blob) { TextFrame frame; for (SkTextBlobRunIterator run(blob.get()); !run.done(); run.next()) { - TextRun text_run(ToFont(run.font())); + TextRun text_run(ToFont(run.font(), scale)); const auto glyph_count = run.glyphCount(); const auto* glyphs = run.glyphs(); switch (run.positioning()) { diff --git a/impeller/typographer/backends/skia/text_frame_skia.h b/impeller/typographer/backends/skia/text_frame_skia.h index ca15f01881712..a7b8074135c3f 100644 --- a/impeller/typographer/backends/skia/text_frame_skia.h +++ b/impeller/typographer/backends/skia/text_frame_skia.h @@ -10,6 +10,6 @@ namespace impeller { -TextFrame TextFrameFromTextBlob(sk_sp blob); +TextFrame TextFrameFromTextBlob(sk_sp blob, Scalar scale = 1.0f); } // namespace impeller diff --git a/impeller/typographer/backends/skia/text_render_context_skia.cc b/impeller/typographer/backends/skia/text_render_context_skia.cc index 94d686e0bdb80..c93906d501ba7 100644 --- a/impeller/typographer/backends/skia/text_render_context_skia.cc +++ b/impeller/typographer/backends/skia/text_render_context_skia.cc @@ -65,7 +65,8 @@ static bool PairsFitInAtlasOfSize(const FontGlyphPair::Vector& pairs, for (const auto& pair : pairs) { const auto glyph_size = - ISize::Ceil(pair.font.GetMetrics().GetBoundingBox().size); + ISize::Ceil(pair.font.GetMetrics().GetBoundingBox().size * + pair.font.GetMetrics().scale); SkIPoint16 location_in_atlas; if (!rect_packer->addRect(glyph_size.width, // glyph_size.height, // @@ -125,7 +126,8 @@ static std::optional CreateAtlasBitmap(const GlyphAtlas& atlas, SkFont sk_font( TypefaceSkia::Cast(*font_glyph.font.GetTypeface()).GetSkiaTypeface(), - font_glyph.font.GetMetrics().point_size); + font_glyph.font.GetMetrics().point_size * + font_glyph.font.GetMetrics().scale); const auto& metrics = font_glyph.font.GetMetrics(); @@ -133,13 +135,14 @@ static std::optional CreateAtlasBitmap(const GlyphAtlas& atlas, SkPaint glyph_paint; glyph_paint.setColor(glyph_color); - canvas->drawGlyphs(1u, // count - &glyph_id, // glyphs - &position, // positions - SkPoint::Make(-metrics.min_extent.x, - -metrics.ascent), // origin - sk_font, // font - glyph_paint // paint + canvas->drawGlyphs( + 1u, // count + &glyph_id, // glyphs + &position, // positions + SkPoint::Make(-metrics.min_extent.x * metrics.scale, + -metrics.ascent * metrics.scale), // origin + sk_font, // font + glyph_paint // paint ); return true; }); diff --git a/impeller/typographer/font.h b/impeller/typographer/font.h index e23d8908fa444..2830900b7de9f 100644 --- a/impeller/typographer/font.h +++ b/impeller/typographer/font.h @@ -28,6 +28,12 @@ class Font : public Comparable { /// the baseline with an upper-left-origin coordinate system. /// struct Metrics { + //-------------------------------------------------------------------------- + /// The scaling factor that should be used when rendering this font to an + /// atlas. This should normally be set in accordance with the transformation + /// matrix that will be used to position glyph geometry. + /// + Scalar scale = 1.0f; //-------------------------------------------------------------------------- /// The point size of the font. /// @@ -69,9 +75,9 @@ class Font : public Comparable { } constexpr bool operator==(const Metrics& o) const { - return point_size == o.point_size && ascent == o.ascent && - descent == o.descent && min_extent == o.min_extent && - max_extent == o.max_extent; + return scale == o.scale && point_size == o.point_size && + ascent == o.ascent && descent == o.descent && + min_extent == o.min_extent && max_extent == o.max_extent; } }; @@ -107,6 +113,6 @@ class Font : public Comparable { template <> struct std::hash { constexpr std::size_t operator()(const impeller::Font::Metrics& m) const { - return fml::HashCombine(m.point_size, m.ascent, m.descent); + return fml::HashCombine(m.scale, m.point_size, m.ascent, m.descent); } }; diff --git a/impeller/typographer/glyph_atlas.h b/impeller/typographer/glyph_atlas.h index e72c3b83e1553..896ca7c8f2d6e 100644 --- a/impeller/typographer/glyph_atlas.h +++ b/impeller/typographer/glyph_atlas.h @@ -47,7 +47,7 @@ class GlyphAtlas { const std::shared_ptr& GetTexture() const; //---------------------------------------------------------------------------- - /// @brief Record there location of a specific font-glyph pair within the + /// @brief Record the location of a specific font-glyph pair within the /// atlas. /// /// @param[in] pair The font-glyph pair