44
55#include " impeller/typographer/backends/skia/typographer_context_skia.h"
66
7+ #include < numeric>
78#include < utility>
89
910#include " flutter/fml/logging.h"
2122
2223namespace impeller {
2324
24- using FontGlyphPairRefVector =
25- std::vector<std::reference_wrapper<const FontGlyphPair>>;
26-
2725// TODO(bdero): We might be able to remove this per-glyph padding if we fix
2826// the underlying causes of the overlap.
2927// https://github.com/flutter/flutter/issues/114563
@@ -43,7 +41,7 @@ TypographerContextSkia::CreateGlyphAtlasContext() const {
4341}
4442
4543static size_t PairsFitInAtlasOfSize (
46- const FontGlyphPair::Set & pairs,
44+ const std::vector<FontGlyphPair> & pairs,
4745 const ISize& atlas_size,
4846 std::vector<Rect>& glyph_positions,
4947 const std::shared_ptr<RectanglePacker>& rect_packer) {
@@ -58,7 +56,8 @@ static size_t PairsFitInAtlasOfSize(
5856 for (auto it = pairs.begin (); it != pairs.end (); ++i, ++it) {
5957 const auto & pair = *it;
6058
61- const auto glyph_size = ISize::Ceil (pair.glyph .bounds .size * pair.scale );
59+ const auto glyph_size =
60+ ISize::Ceil (pair.glyph .bounds .size * pair.scaled_font .scale );
6261 IPoint16 location_in_atlas;
6362 if (!rect_packer->addRect (glyph_size.width + kPadding , //
6463 glyph_size.height + kPadding , //
@@ -78,7 +77,7 @@ static size_t PairsFitInAtlasOfSize(
7877
7978static bool CanAppendToExistingAtlas (
8079 const std::shared_ptr<GlyphAtlas>& atlas,
81- const FontGlyphPairRefVector & extra_pairs,
80+ const std::vector<FontGlyphPair> & extra_pairs,
8281 std::vector<Rect>& glyph_positions,
8382 ISize atlas_size,
8483 const std::shared_ptr<RectanglePacker>& rect_packer) {
@@ -95,7 +94,8 @@ static bool CanAppendToExistingAtlas(
9594 for (size_t i = 0 ; i < extra_pairs.size (); i++) {
9695 const FontGlyphPair& pair = extra_pairs[i];
9796
98- const auto glyph_size = ISize::Ceil (pair.glyph .bounds .size * pair.scale );
97+ const auto glyph_size =
98+ ISize::Ceil (pair.glyph .bounds .size * pair.scaled_font .scale );
9999 IPoint16 location_in_atlas;
100100 if (!rect_packer->addRect (glyph_size.width + kPadding , //
101101 glyph_size.height + kPadding , //
@@ -114,7 +114,7 @@ static bool CanAppendToExistingAtlas(
114114}
115115
116116static ISize OptimumAtlasSizeForFontGlyphPairs (
117- const FontGlyphPair::Set & pairs,
117+ const std::vector<FontGlyphPair> & pairs,
118118 std::vector<Rect>& glyph_positions,
119119 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
120120 GlyphAtlas::Type type) {
@@ -153,16 +153,17 @@ static ISize OptimumAtlasSizeForFontGlyphPairs(
153153}
154154
155155static void DrawGlyph (SkCanvas* canvas,
156- const FontGlyphPair& font_glyph,
156+ const ScaledFont& scaled_font,
157+ const Glyph& glyph,
157158 const Rect& location,
158159 bool has_color) {
159- const auto & metrics = font_glyph .font .GetMetrics ();
160- const auto position = SkPoint::Make (location.origin .x / font_glyph .scale ,
161- location.origin .y / font_glyph .scale );
162- SkGlyphID glyph_id = font_glyph. glyph .index ;
160+ const auto & metrics = scaled_font .font .GetMetrics ();
161+ const auto position = SkPoint::Make (location.origin .x / scaled_font .scale ,
162+ location.origin .y / scaled_font .scale );
163+ SkGlyphID glyph_id = glyph.index ;
163164
164165 SkFont sk_font (
165- TypefaceSkia::Cast (*font_glyph .font .GetTypeface ()).GetSkiaTypeface (),
166+ TypefaceSkia::Cast (*scaled_font .font .GetTypeface ()).GetSkiaTypeface (),
166167 metrics.point_size , metrics.scaleX , metrics.skewX );
167168 sk_font.setEdging (SkFont::Edging::kAntiAlias );
168169 sk_font.setHinting (SkFontHinting::kSlight );
@@ -173,21 +174,20 @@ static void DrawGlyph(SkCanvas* canvas,
173174 SkPaint glyph_paint;
174175 glyph_paint.setColor (glyph_color);
175176 canvas->resetMatrix ();
176- canvas->scale (font_glyph.scale , font_glyph.scale );
177- canvas->drawGlyphs (
178- 1u , // count
179- &glyph_id, // glyphs
180- &position, // positions
181- SkPoint::Make (-font_glyph.glyph .bounds .GetLeft (),
182- -font_glyph.glyph .bounds .GetTop ()), // origin
183- sk_font, // font
184- glyph_paint // paint
177+ canvas->scale (scaled_font.scale , scaled_font.scale );
178+ canvas->drawGlyphs (1u , // count
179+ &glyph_id, // glyphs
180+ &position, // positions
181+ SkPoint::Make (-glyph.bounds .GetLeft (),
182+ -glyph.bounds .GetTop ()), // origin
183+ sk_font, // font
184+ glyph_paint // paint
185185 );
186186}
187187
188188static bool UpdateAtlasBitmap (const GlyphAtlas& atlas,
189189 const std::shared_ptr<SkBitmap>& bitmap,
190- const FontGlyphPairRefVector & new_pairs) {
190+ const std::vector<FontGlyphPair> & new_pairs) {
191191 TRACE_EVENT0 (" impeller" , __FUNCTION__);
192192 FML_DCHECK (bitmap != nullptr );
193193
@@ -207,7 +207,7 @@ static bool UpdateAtlasBitmap(const GlyphAtlas& atlas,
207207 if (!pos.has_value ()) {
208208 continue ;
209209 }
210- DrawGlyph (canvas, pair, pos.value (), has_color);
210+ DrawGlyph (canvas, pair. scaled_font , pair. glyph , pos.value (), has_color);
211211 }
212212 return true ;
213213}
@@ -243,9 +243,10 @@ static std::shared_ptr<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
243243
244244 bool has_color = atlas.GetType () == GlyphAtlas::Type::kColorBitmap ;
245245
246- atlas.IterateGlyphs ([canvas, has_color](const FontGlyphPair& font_glyph,
246+ atlas.IterateGlyphs ([canvas, has_color](const ScaledFont& scaled_font,
247+ const Glyph& glyph,
247248 const Rect& location) -> bool {
248- DrawGlyph (canvas, font_glyph , location, has_color);
249+ DrawGlyph (canvas, scaled_font, glyph , location, has_color);
249250 return true ;
250251 });
251252
@@ -313,26 +314,37 @@ std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
313314 Context& context,
314315 GlyphAtlas::Type type,
315316 std::shared_ptr<GlyphAtlasContext> atlas_context,
316- const FontGlyphPair::Set& font_glyph_pairs ) const {
317+ const FontGlyphMap& font_glyph_map ) const {
317318 TRACE_EVENT0 (" impeller" , __FUNCTION__);
318319 if (!IsValid ()) {
319320 return nullptr ;
320321 }
321322 auto & atlas_context_skia = GlyphAtlasContextSkia::Cast (*atlas_context);
322323 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas ();
323324
324- if (font_glyph_pairs .empty ()) {
325+ if (font_glyph_map .empty ()) {
325326 return last_atlas;
326327 }
327328
328329 // ---------------------------------------------------------------------------
329330 // Step 1: Determine if the atlas type and font glyph pairs are compatible
330331 // with the current atlas and reuse if possible.
331332 // ---------------------------------------------------------------------------
332- FontGlyphPairRefVector new_glyphs;
333- for (const FontGlyphPair& pair : font_glyph_pairs) {
334- if (!last_atlas->FindFontGlyphBounds (pair).has_value ()) {
335- new_glyphs.push_back (pair);
333+ std::vector<FontGlyphPair> new_glyphs;
334+ for (const auto & font_value : font_glyph_map) {
335+ const ScaledFont& scaled_font = font_value.first ;
336+ const FontGlyphAtlas* font_glyph_atlas =
337+ last_atlas->GetFontGlyphAtlas (scaled_font.font , scaled_font.scale );
338+ if (font_glyph_atlas) {
339+ for (const Glyph& glyph : font_value.second ) {
340+ if (!font_glyph_atlas->FindGlyphBounds (glyph)) {
341+ new_glyphs.emplace_back (scaled_font, glyph);
342+ }
343+ }
344+ } else {
345+ for (const Glyph& glyph : font_value.second ) {
346+ new_glyphs.emplace_back (scaled_font, glyph);
347+ }
336348 }
337349 }
338350 if (last_atlas->GetType () == type && new_glyphs.size () == 0 ) {
@@ -381,6 +393,16 @@ std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
381393 // ---------------------------------------------------------------------------
382394 // Step 3b: Get the optimum size of the texture atlas.
383395 // ---------------------------------------------------------------------------
396+ std::vector<FontGlyphPair> font_glyph_pairs;
397+ font_glyph_pairs.reserve (std::accumulate (
398+ font_glyph_map.begin (), font_glyph_map.end (), 0 ,
399+ [](const int a, const auto & b) { return a + b.second .size (); }));
400+ for (const auto & font_value : font_glyph_map) {
401+ const ScaledFont& scaled_font = font_value.first ;
402+ for (const Glyph& glyph : font_value.second ) {
403+ font_glyph_pairs.push_back ({scaled_font, glyph});
404+ }
405+ }
384406 auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
385407 auto atlas_size = OptimumAtlasSizeForFontGlyphPairs (
386408 font_glyph_pairs, glyph_positions, atlas_context, type);
0 commit comments