Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] Use glyph bounds to compute the max glyph size instead of font metrics #37998

Merged
merged 3 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,43 @@ TEST_P(AiksTest, CanRenderTextInSaveLayer) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, CanRenderTextOutsideBoundaries) {
Canvas canvas;
canvas.Translate({200, 150});

// Construct the text blob.
auto mapping = OpenFixtureAsSkData("wtf.otf");
ASSERT_NE(mapping, nullptr);

Scalar font_size = 80;
SkFont sk_font(SkTypeface::MakeFromData(mapping), font_size);

Paint text_paint;
text_paint.color = Color::White().WithAlpha(0.8);

struct {
Point position;
const char* text;
} text[] = {{Point(0, 0), "0F0F0F0"},
{Point(1, 2), "789"},
{Point(1, 3), "456"},
{Point(1, 4), "123"},
{Point(0, 6), "0F0F0F0"}};
for (auto& t : text) {
canvas.Save();
canvas.Translate(t.position * Point(font_size * 2, font_size * 1.1));
{
auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
ASSERT_NE(blob, nullptr);
auto frame = TextFrameFromTextBlob(blob);
canvas.DrawTextFrame(frame, Point(), text_paint);
}
canvas.Restore();
}

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, CanDrawPaint) {
Paint paint;
paint.color = Color::MediumTurquoise();
Expand Down
3 changes: 1 addition & 2 deletions impeller/entity/contents/text_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ static bool CommonRender(
auto glyph_size_ = font.GetMetrics().GetBoundingBox().size;
auto glyph_size = Point{static_cast<Scalar>(glyph_size_.width),
static_cast<Scalar>(glyph_size_.height)};
auto metrics_offset =
Point{font.GetMetrics().min_extent.x, font.GetMetrics().ascent};
auto metrics_offset = font.GetMetrics().min_extent;

for (const auto& glyph_position : run.GetGlyphPositions()) {
FontGlyphPair font_glyph_pair{font, glyph_position.glyph};
Expand Down
1 change: 1 addition & 0 deletions impeller/fixtures/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ test_fixtures("file_fixtures") {
"table_mountain_pz.png",
"test_texture.frag",
"types.h",
"wtf.otf",
]
if (host_os == "mac") {
fixtures += [ "/System/Library/Fonts/Apple Color Emoji.ttc" ]
Expand Down
Binary file added impeller/fixtures/wtf.otf
Binary file not shown.
25 changes: 21 additions & 4 deletions impeller/typographer/backends/skia/text_frame_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@

#include "impeller/typographer/backends/skia/text_frame_skia.h"

#include <vector>

#include "flutter/fml/logging.h"
#include "impeller/typographer/backends/skia/typeface_skia.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkRect.h"
#include "third_party/skia/include/core/SkFont.h"
#include "third_party/skia/include/core/SkFontMetrics.h"
#include "third_party/skia/src/core/SkStrikeSpec.h" // nogncheck
#include "third_party/skia/src/core/SkTextBlobPriv.h" // nogncheck

namespace impeller {

static Font ToFont(const SkFont& font, Scalar scale) {
static Font ToFont(const SkTextBlobRunIterator& run, Scalar scale) {
auto& font = run.font();
auto typeface = std::make_shared<TypefaceSkia>(font.refTypefaceOrDefault());

SkFontMetrics sk_metrics;
Expand All @@ -24,8 +29,20 @@ static Font ToFont(const SkFont& font, Scalar scale) {
metrics.point_size = font.getSize();
metrics.ascent = sk_metrics.fAscent;
metrics.descent = sk_metrics.fDescent;
metrics.min_extent = {sk_metrics.fXMin, sk_metrics.fAscent};
metrics.max_extent = {sk_metrics.fXMax, sk_metrics.fDescent};
metrics.min_extent = {sk_metrics.fXMin, sk_metrics.fTop};
metrics.max_extent = {sk_metrics.fXMax, sk_metrics.fBottom};

std::vector<SkRect> glyph_bounds;
SkPaint paint;

glyph_bounds.resize(run.glyphCount());
run.font().getBounds(run.glyphs(), run.glyphCount(), glyph_bounds.data(),
nullptr);
for (auto& bounds : glyph_bounds) {
metrics.min_extent = metrics.min_extent.Min({bounds.fLeft, bounds.fTop});
metrics.max_extent =
metrics.max_extent.Max({bounds.fRight, bounds.fBottom});
}

return Font{std::move(typeface), metrics};
}
Expand All @@ -38,7 +55,7 @@ TextFrame TextFrameFromTextBlob(const sk_sp<SkTextBlob>& blob, Scalar scale) {
TextFrame frame;

for (SkTextBlobRunIterator run(blob.get()); !run.done(); run.next()) {
TextRun text_run(ToFont(run.font(), scale));
TextRun text_run(ToFont(run, scale));

// TODO(jonahwilliams): ask Skia for a public API to look this up.
// https://github.com/flutter/flutter/issues/112005
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ static size_t PairsFitInAtlasOfSize(const FontGlyphPair::Vector& pairs,

for (size_t i = 0; i < pairs.size(); i++) {
const auto& pair = pairs[i];

const auto glyph_size =
ISize::Ceil(pair.font.GetMetrics().GetBoundingBox().size *
pair.font.GetMetrics().scale);
Expand Down Expand Up @@ -291,9 +292,9 @@ static std::shared_ptr<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
&glyph_id, // glyphs
&position, // positions
SkPoint::Make(-metrics.min_extent.x,
-metrics.ascent), // origin
sk_font, // font
glyph_paint // paint
-metrics.min_extent.y), // origin
sk_font, // font
glyph_paint // paint
);
return true;
});
Expand Down
4 changes: 2 additions & 2 deletions impeller/typographer/typographer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ TEST_P(TypographerTest, GlyphAtlasWithOddUniqueGlyphSize) {

// The 3 unique glyphs should not evenly fit into a square texture, so we
// should have a rectangular one.
ASSERT_EQ(atlas->GetTexture()->GetSize().width * 2,
ASSERT_EQ(atlas->GetTexture()->GetSize().width,
atlas->GetTexture()->GetSize().height);
}

Expand Down Expand Up @@ -166,7 +166,7 @@ TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
ASSERT_NE(atlas, nullptr);
ASSERT_NE(atlas->GetTexture(), nullptr);

ASSERT_EQ(atlas->GetTexture()->GetSize().width * 2,
ASSERT_EQ(atlas->GetTexture()->GetSize().width,
atlas->GetTexture()->GetSize().height);
}

Expand Down