Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b5242cc

Browse files
authored
[Impeller] Pack πŸ‘ the πŸ‘ atlas πŸ‘ (#38024)
1 parent 87e7411 commit b5242cc

File tree

7 files changed

+42
-82
lines changed

7 files changed

+42
-82
lines changed

β€Žimpeller/entity/contents/text_contents.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,6 @@ static bool CommonRender(
128128

129129
for (const auto& run : frame.GetRuns()) {
130130
auto font = run.GetFont();
131-
auto glyph_size_ = font.GetMetrics().GetBoundingBox().size;
132-
auto glyph_size = Point{static_cast<Scalar>(glyph_size_.width),
133-
static_cast<Scalar>(glyph_size_.height)};
134-
auto metrics_offset = font.GetMetrics().min_extent;
135131

136132
for (const auto& glyph_position : run.GetGlyphPositions()) {
137133
FontGlyphPair font_glyph_pair{font, glyph_position.glyph};
@@ -144,13 +140,14 @@ static bool CommonRender(
144140
auto atlas_position = atlas_glyph_pos->origin;
145141
auto atlas_glyph_size =
146142
Point{atlas_glyph_pos->size.width, atlas_glyph_pos->size.height};
147-
auto offset_glyph_position = glyph_position.position + metrics_offset;
143+
auto offset_glyph_position =
144+
glyph_position.position + glyph_position.glyph.bounds.origin;
148145

149146
for (const auto& point : unit_points) {
150147
typename VS::PerVertexData vtx;
151148
vtx.unit_position = point;
152149
vtx.destination_position = offset_glyph_position + Point(0.5, 0.5);
153-
vtx.destination_size = glyph_size - Point(1.0, 1.0);
150+
vtx.destination_size = Point(glyph_position.glyph.bounds.size);
154151
vtx.source_position = atlas_position + Point(0.5, 0.5);
155152
vtx.source_glyph_size = atlas_glyph_size - Point(1.0, 1.0);
156153
if constexpr (std::is_same_v<TPipeline, GlyphAtlasPipeline>) {

β€Žimpeller/typographer/backends/skia/text_frame_skia.cc

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,14 @@ static Font ToFont(const SkTextBlobRunIterator& run, Scalar scale) {
2727
Font::Metrics metrics;
2828
metrics.scale = scale;
2929
metrics.point_size = font.getSize();
30-
metrics.ascent = sk_metrics.fAscent;
31-
metrics.descent = sk_metrics.fDescent;
32-
metrics.min_extent = {sk_metrics.fXMin, sk_metrics.fTop};
33-
metrics.max_extent = {sk_metrics.fXMax, sk_metrics.fBottom};
34-
35-
std::vector<SkRect> glyph_bounds;
36-
SkPaint paint;
37-
38-
glyph_bounds.resize(run.glyphCount());
39-
run.font().getBounds(run.glyphs(), run.glyphCount(), glyph_bounds.data(),
40-
nullptr);
41-
for (auto& bounds : glyph_bounds) {
42-
metrics.min_extent = metrics.min_extent.Min({bounds.fLeft, bounds.fTop});
43-
metrics.max_extent =
44-
metrics.max_extent.Max({bounds.fRight, bounds.fBottom});
45-
}
4630

4731
return Font{std::move(typeface), metrics};
4832
}
4933

34+
static Rect ToRect(const SkRect& rect) {
35+
return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
36+
}
37+
5038
TextFrame TextFrameFromTextBlob(const sk_sp<SkTextBlob>& blob, Scalar scale) {
5139
if (!blob) {
5240
return {};
@@ -71,7 +59,11 @@ TextFrame TextFrameFromTextBlob(const sk_sp<SkTextBlob>& blob, Scalar scale) {
7159
case SkTextBlobRunIterator::kHorizontal_Positioning:
7260
FML_DLOG(ERROR) << "Unimplemented.";
7361
break;
74-
case SkTextBlobRunIterator::kFull_Positioning:
62+
case SkTextBlobRunIterator::kFull_Positioning: {
63+
std::vector<SkRect> glyph_bounds;
64+
glyph_bounds.resize(glyph_count);
65+
run.font().getBounds(glyphs, glyph_count, glyph_bounds.data(), nullptr);
66+
7567
for (auto i = 0u; i < glyph_count; i++) {
7668
// kFull_Positioning has two scalars per glyph.
7769
const SkPoint* glyph_points = run.points();
@@ -80,10 +72,11 @@ TextFrame TextFrameFromTextBlob(const sk_sp<SkTextBlob>& blob, Scalar scale) {
8072
? Glyph::Type::kBitmap
8173
: Glyph::Type::kPath;
8274

83-
text_run.AddGlyph(Glyph{glyphs[i], type},
75+
text_run.AddGlyph(Glyph{glyphs[i], type, ToRect(glyph_bounds[i])},
8476
Point{point->x(), point->y()});
8577
}
8678
break;
79+
}
8780
case SkTextBlobRunIterator::kRSXform_Positioning:
8881
FML_DLOG(ERROR) << "Unimplemented.";
8982
break;

β€Žimpeller/typographer/backends/skia/text_render_context_skia.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,16 @@ static size_t PairsFitInAtlasOfSize(const FontGlyphPair::Vector& pairs,
7171
glyph_positions.clear();
7272
glyph_positions.reserve(pairs.size());
7373

74-
// TODO(114563): We might be able to remove this per-glyph padding if we fix
75-
// the underlying causes of the overlap.
74+
// TODO(bdero): We might be able to remove this per-glyph padding if we fix
75+
// the underlying causes of the overlap.
76+
// https://github.com/flutter/flutter/issues/114563
7677
constexpr auto padding = 2;
7778

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

8182
const auto glyph_size =
82-
ISize::Ceil(pair.font.GetMetrics().GetBoundingBox().size *
83-
pair.font.GetMetrics().scale);
83+
ISize::Ceil((pair.glyph.bounds * pair.font.GetMetrics().scale).size);
8484
SkIPoint16 location_in_atlas;
8585
if (!rect_packer->addRect(glyph_size.width + padding, //
8686
glyph_size.height + padding, //
@@ -288,13 +288,14 @@ static std::shared_ptr<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
288288
glyph_paint.setColor(glyph_color);
289289
canvas->resetMatrix();
290290
canvas->scale(metrics.scale, metrics.scale);
291-
canvas->drawGlyphs(1u, // count
292-
&glyph_id, // glyphs
293-
&position, // positions
294-
SkPoint::Make(-metrics.min_extent.x,
295-
-metrics.min_extent.y), // origin
296-
sk_font, // font
297-
glyph_paint // paint
291+
canvas->drawGlyphs(
292+
1u, // count
293+
&glyph_id, // glyphs
294+
&position, // positions
295+
SkPoint::Make(-font_glyph.glyph.bounds.GetLeft(),
296+
-font_glyph.glyph.bounds.GetTop()), // origin
297+
sk_font, // font
298+
glyph_paint // paint
298299
);
299300
return true;
300301
});

β€Žimpeller/typographer/font.h

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -38,46 +38,9 @@ class Font : public Comparable<Font> {
3838
/// The point size of the font.
3939
///
4040
Scalar point_size = 12.0f;
41-
//--------------------------------------------------------------------------
42-
/// The font ascent relative to the baseline. This is usually negative as
43-
/// moving upwards (ascending) in an upper-left-origin coordinate system
44-
/// yields smaller numbers.
45-
///
46-
Scalar ascent = 0.0f;
47-
//--------------------------------------------------------------------------
48-
/// The font descent relative to the baseline. This is usually positive as
49-
/// moving downwards (descending) in an upper-left-origin coordinate system
50-
/// yields larger numbers.
51-
///
52-
Scalar descent = 0.0f;
53-
//--------------------------------------------------------------------------
54-
/// The minimum glyph extents relative to the origin. Typically negative in
55-
/// an upper-left-origin coordinate system.
56-
///
57-
Point min_extent;
58-
//--------------------------------------------------------------------------
59-
/// The maximum glyph extents relative to the origin. Typically positive in
60-
/// an upper-left-origin coordinate system.
61-
///
62-
Point max_extent;
63-
64-
//--------------------------------------------------------------------------
65-
/// @brief The union of the bounding boxes of all the glyphs.
66-
///
67-
/// @return The bounding box.
68-
///
69-
constexpr Rect GetBoundingBox() const {
70-
return Rect::MakeLTRB(min_extent.x, //
71-
min_extent.y, //
72-
max_extent.x, //
73-
max_extent.y //
74-
);
75-
}
7641

7742
constexpr bool operator==(const Metrics& o) const {
78-
return scale == o.scale && point_size == o.point_size &&
79-
ascent == o.ascent && descent == o.descent &&
80-
min_extent == o.min_extent && max_extent == o.max_extent;
43+
return scale == o.scale && point_size == o.point_size;
8144
}
8245
};
8346

@@ -113,6 +76,6 @@ class Font : public Comparable<Font> {
11376
template <>
11477
struct std::hash<impeller::Font::Metrics> {
11578
constexpr std::size_t operator()(const impeller::Font::Metrics& m) const {
116-
return fml::HashCombine(m.scale, m.point_size, m.ascent, m.descent);
79+
return fml::HashCombine(m.scale, m.point_size);
11780
}
11881
};

β€Žimpeller/typographer/glyph.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <functional>
99

1010
#include "flutter/fml/macros.h"
11+
#include "impeller/geometry/rect.h"
1112

1213
namespace impeller {
1314

@@ -23,11 +24,18 @@ struct Glyph {
2324
uint16_t index = 0;
2425

2526
//------------------------------------------------------------------------------
26-
/// @brief Whether the glyph is a path or a bitmap.
27+
/// @brief Whether the glyph is a path or a bitmap.
2728
///
2829
Type type = Type::kPath;
2930

30-
Glyph(uint16_t p_index, Type p_type) : index(p_index), type(p_type) {}
31+
//------------------------------------------------------------------------------
32+
/// @brief Visibility coverage of the glyph in text run space (relative to
33+
/// the baseline, no scaling applied).
34+
///
35+
Rect bounds;
36+
37+
Glyph(uint16_t p_index, Type p_type, Rect p_bounds)
38+
: index(p_index), type(p_type), bounds(p_bounds) {}
3139
};
3240

3341
} // namespace impeller

β€Žimpeller/typographer/text_frame.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ std::optional<Rect> TextFrame::GetBounds() const {
1414
std::optional<Rect> result;
1515

1616
for (const auto& run : runs_) {
17-
const auto glyph_bounds = run.GetFont().GetMetrics().GetBoundingBox();
1817
for (const auto& glyph_position : run.GetGlyphPositions()) {
19-
Rect glyph_rect = Rect(glyph_position.position + glyph_bounds.origin,
20-
glyph_bounds.size);
18+
Rect glyph_rect =
19+
Rect(glyph_position.position + glyph_position.glyph.bounds.origin,
20+
glyph_position.glyph.bounds.size);
2121
result = result.has_value() ? result->Union(glyph_rect) : glyph_rect;
2222
}
2323
}

β€Žimpeller/typographer/typographer_unittests.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ TEST_P(TypographerTest, GlyphAtlasWithOddUniqueGlyphSize) {
108108
ASSERT_NE(atlas, nullptr);
109109
ASSERT_NE(atlas->GetTexture(), nullptr);
110110

111-
// The 3 unique glyphs should not evenly fit into a square texture, so we
112-
// should have a rectangular one.
113111
ASSERT_EQ(atlas->GetTexture()->GetSize().width,
114112
atlas->GetTexture()->GetSize().height);
115113
}
@@ -166,7 +164,7 @@ TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
166164
ASSERT_NE(atlas, nullptr);
167165
ASSERT_NE(atlas->GetTexture(), nullptr);
168166

169-
ASSERT_EQ(atlas->GetTexture()->GetSize().width,
167+
ASSERT_EQ(atlas->GetTexture()->GetSize().width * 2,
170168
atlas->GetTexture()->GetSize().height);
171169
}
172170

0 commit comments

Comments
Β (0)