Skip to content

Commit

Permalink
Render glyphs at the correct resolution with respect to the current t…
Browse files Browse the repository at this point in the history
…ransform (flutter#101)
  • Loading branch information
bdero authored and dnfield committed Apr 27, 2022
1 parent 39f4ebd commit 0aaa84e
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 24 deletions.
10 changes: 6 additions & 4 deletions impeller/display_list/display_list_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -609,9 +610,10 @@ void DisplayListDispatcher::drawDisplayList(
void DisplayListDispatcher::drawTextBlob(const sk_sp<SkTextBlob> 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_ //
);
}

Expand Down
3 changes: 3 additions & 0 deletions impeller/geometry/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
30 changes: 30 additions & 0 deletions impeller/geometry/geometry_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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) {
Expand Down
9 changes: 9 additions & 0 deletions impeller/geometry/matrix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions impeller/geometry/matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions impeller/geometry/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ struct TPoint {
return *this;
}

template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
inline TPoint operator*=(U scale) {
x *= static_cast<Type>(scale);
y *= static_cast<Type>(scale);
return *this;
}

template <class U>
inline TPoint operator/=(const TPoint<U>& p) {
x /= static_cast<Type>(p.x);
Expand All @@ -102,6 +109,13 @@ struct TPoint {
return *this;
}

template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
inline TPoint operator/=(U scale) {
x /= static_cast<Type>(scale);
y /= static_cast<Type>(scale);
return *this;
}

constexpr TPoint operator-() const { return {-x, -y}; }

constexpr TPoint operator+(const TPoint& p) const {
Expand Down
2 changes: 0 additions & 2 deletions impeller/geometry/scalar.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ namespace impeller {

using Scalar = float;

constexpr Scalar kEhCloseEnough = 1e-3f;

template <class T, class = std::enable_if_t<std::is_arithmetic_v<T>>>
constexpr T Absolute(const T& val) {
return val >= T{} ? val : -val;
Expand Down
8 changes: 5 additions & 3 deletions impeller/typographer/backends/skia/text_frame_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<TypefaceSkia>(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;
Expand All @@ -28,15 +29,16 @@ static Font ToFont(const SkFont& font) {
return Font{std::move(typeface), std::move(metrics)};
}

TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob) {
TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob,
Scalar scale) {
if (!blob) {
return {};
}

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()) {
Expand Down
2 changes: 1 addition & 1 deletion impeller/typographer/backends/skia/text_frame_skia.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@

namespace impeller {

TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob);
TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob, Scalar scale = 1.0f);

} // namespace impeller
21 changes: 12 additions & 9 deletions impeller/typographer/backends/skia/text_render_context_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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, //
Expand Down Expand Up @@ -125,21 +126,23 @@ static std::optional<SkBitmap> 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();

auto glyph_color = SK_ColorWHITE;

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;
});
Expand Down
14 changes: 10 additions & 4 deletions impeller/typographer/font.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ class Font : public Comparable<Font> {
/// 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.
///
Expand Down Expand Up @@ -69,9 +75,9 @@ class Font : public Comparable<Font> {
}

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;
}
};

Expand Down Expand Up @@ -107,6 +113,6 @@ class Font : public Comparable<Font> {
template <>
struct std::hash<impeller::Font::Metrics> {
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);
}
};
2 changes: 1 addition & 1 deletion impeller/typographer/glyph_atlas.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class GlyphAtlas {
const std::shared_ptr<Texture>& 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
Expand Down

0 comments on commit 0aaa84e

Please sign in to comment.