@@ -283,7 +283,8 @@ static bool BulkUpdateAtlasBitmap(const GlyphAtlas& atlas,
283
283
if (!data.has_value ()) {
284
284
continue ;
285
285
}
286
- auto [pos, bounds] = data.value ();
286
+ auto [pos, bounds, placeholder] = data.value ();
287
+ FML_DCHECK (!placeholder);
287
288
Size size = pos.GetSize ();
288
289
if (size.IsEmpty ()) {
289
290
continue ;
@@ -326,7 +327,9 @@ static bool UpdateAtlasBitmap(const GlyphAtlas& atlas,
326
327
if (!data.has_value ()) {
327
328
continue ;
328
329
}
329
- auto [pos, bounds] = data.value ();
330
+ auto [pos, bounds, placeholder] = data.value ();
331
+ FML_DCHECK (!placeholder);
332
+
330
333
Size size = pos.GetSize ();
331
334
if (size.IsEmpty ()) {
332
335
continue ;
@@ -404,61 +407,88 @@ static Rect ComputeGlyphSize(const SkFont& font,
404
407
scaled_bounds.fBottom );
405
408
};
406
409
407
- static void CollectNewGlyphs (const std::shared_ptr<GlyphAtlas>& atlas,
408
- const FontGlyphMap& font_glyph_map,
409
- std::vector<FontGlyphPair>& new_glyphs,
410
- std::vector<Rect>& glyph_sizes) {
411
- for (const auto & font_value : font_glyph_map) {
412
- const ScaledFont& scaled_font = font_value.first ;
413
- const FontGlyphAtlas* font_glyph_atlas =
414
- atlas->GetFontGlyphAtlas (scaled_font.font , scaled_font.scale );
415
-
416
- auto metrics = scaled_font.font .GetMetrics ();
417
-
418
- SkFont sk_font (
419
- TypefaceSkia::Cast (*scaled_font.font .GetTypeface ()).GetSkiaTypeface (),
420
- metrics.point_size , metrics.scaleX , metrics.skewX );
421
- sk_font.setEdging (SkFont::Edging::kAntiAlias );
422
- sk_font.setHinting (SkFontHinting::kSlight );
423
- sk_font.setEmbolden (metrics.embolden );
424
- // Rather than computing the bounds at the requested point size and scaling
425
- // up the bounds, we scale up the font size and request the bounds. This
426
- // seems to give more accurate bounds information.
427
- sk_font.setSize (sk_font.getSize () * scaled_font.scale );
428
- sk_font.setSubpixel (true );
429
-
430
- if (font_glyph_atlas) {
431
- for (const SubpixelGlyph& glyph : font_value.second ) {
432
- if (!font_glyph_atlas->FindGlyphBounds (glyph)) {
433
- new_glyphs.emplace_back (scaled_font, glyph);
434
- glyph_sizes.push_back (
435
- ComputeGlyphSize (sk_font, glyph, scaled_font.scale ));
410
+ std::pair<std::vector<FontGlyphPair>, std::vector<Rect>>
411
+ TypographerContextSkia::CollectNewGlyphs (
412
+ const std::shared_ptr<GlyphAtlas>& atlas,
413
+ const std::vector<std::shared_ptr<TextFrame>>& text_frames) {
414
+ std::vector<FontGlyphPair> new_glyphs;
415
+ std::vector<Rect> glyph_sizes;
416
+ for (const auto & frame : text_frames) {
417
+ // TODO(jonahwilliams): unless we destroy the atlas (which we know about),
418
+ // we could probably guarantee that a text frame that is complete does not
419
+ // need to be processed unless the scale or properties changed. I'm leaving
420
+ // this as a future optimization.
421
+ frame->ClearFrameBounds ();
422
+
423
+ for (const auto & run : frame->GetRuns ()) {
424
+ auto metrics = run.GetFont ().GetMetrics ();
425
+
426
+ auto rounded_scale =
427
+ TextFrame::RoundScaledFontSize (frame->GetScale (), metrics.point_size );
428
+ ScaledFont scaled_font{.font = run.GetFont (), .scale = rounded_scale};
429
+
430
+ FontGlyphAtlas* font_glyph_atlas =
431
+ atlas->GetOrCreateFontGlyphAtlas (scaled_font);
432
+ FML_DCHECK (!!font_glyph_atlas);
433
+
434
+ SkFont sk_font (
435
+ TypefaceSkia::Cast (*scaled_font.font .GetTypeface ()).GetSkiaTypeface (),
436
+ metrics.point_size , metrics.scaleX , metrics.skewX );
437
+ sk_font.setEdging (SkFont::Edging::kAntiAlias );
438
+ sk_font.setHinting (SkFontHinting::kSlight );
439
+ sk_font.setEmbolden (metrics.embolden );
440
+ // Rather than computing the bounds at the requested point size and
441
+ // scaling up the bounds, we scale up the font size and request the
442
+ // bounds. This seems to give more accurate bounds information.
443
+ sk_font.setSize (sk_font.getSize () * scaled_font.scale );
444
+ sk_font.setSubpixel (true );
445
+
446
+ for (const auto & glyph_position : run.GetGlyphPositions ()) {
447
+ Point subpixel = TextFrame::ComputeSubpixelPosition (
448
+ glyph_position, scaled_font.font .GetAxisAlignment (),
449
+ frame->GetOffset (), frame->GetScale ());
450
+ SubpixelGlyph subpixel_glyph (glyph_position.glyph , subpixel,
451
+ frame->GetProperties ());
452
+ const auto & font_glyph_bounds =
453
+ font_glyph_atlas->FindGlyphBounds (subpixel_glyph);
454
+
455
+ if (!font_glyph_bounds.has_value ()) {
456
+ new_glyphs.push_back (FontGlyphPair{scaled_font, subpixel_glyph});
457
+ auto glyph_bounds =
458
+ ComputeGlyphSize (sk_font, subpixel_glyph, scaled_font.scale );
459
+ glyph_sizes.push_back (glyph_bounds);
460
+
461
+ auto frame_bounds = FrameBounds{
462
+ Rect::MakeLTRB (0 , 0 , 0 , 0 ), //
463
+ glyph_bounds, //
464
+ /* placeholder=*/ true //
465
+ };
466
+
467
+ frame->AppendFrameBounds (frame_bounds);
468
+ font_glyph_atlas->AppendGlyph (subpixel_glyph, frame_bounds);
469
+ } else {
470
+ frame->AppendFrameBounds (font_glyph_bounds.value ());
436
471
}
437
472
}
438
- } else {
439
- for (const SubpixelGlyph& glyph : font_value.second ) {
440
- new_glyphs.emplace_back (scaled_font, glyph);
441
- glyph_sizes.push_back (
442
- ComputeGlyphSize (sk_font, glyph, scaled_font.scale ));
443
- }
444
473
}
445
474
}
475
+ return {std::move (new_glyphs), std::move (glyph_sizes)};
446
476
}
447
477
448
478
std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas (
449
479
Context& context,
450
480
GlyphAtlas::Type type,
451
481
HostBuffer& host_buffer,
452
482
const std::shared_ptr<GlyphAtlasContext>& atlas_context,
453
- const FontGlyphMap& font_glyph_map ) const {
483
+ const std::vector<std::shared_ptr<TextFrame>>& text_frames ) const {
454
484
TRACE_EVENT0 (" impeller" , __FUNCTION__);
455
485
if (!IsValid ()) {
456
486
return nullptr ;
457
487
}
458
488
std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas ();
459
489
FML_DCHECK (last_atlas->GetType () == type);
460
490
461
- if (font_glyph_map .empty ()) {
491
+ if (text_frames .empty ()) {
462
492
return last_atlas;
463
493
}
464
494
@@ -467,9 +497,7 @@ std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
467
497
// with the current atlas and reuse if possible. For each new font and
468
498
// glyph pair, compute the glyph size at scale.
469
499
// ---------------------------------------------------------------------------
470
- std::vector<FontGlyphPair> new_glyphs;
471
- std::vector<Rect> glyph_sizes;
472
- CollectNewGlyphs (last_atlas, font_glyph_map, new_glyphs, glyph_sizes);
500
+ auto [new_glyphs, glyph_sizes] = CollectNewGlyphs (last_atlas, text_frames);
473
501
if (new_glyphs.size () == 0 ) {
474
502
return last_atlas;
475
503
}
@@ -540,9 +568,11 @@ std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
540
568
blit_old_atlas = false ;
541
569
new_atlas = std::make_shared<GlyphAtlas>(type);
542
570
543
- new_glyphs.clear ();
544
- glyph_sizes.clear ();
545
- CollectNewGlyphs (new_atlas, font_glyph_map, new_glyphs, glyph_sizes);
571
+ auto [update_glyphs, update_sizes] =
572
+ CollectNewGlyphs (new_atlas, text_frames);
573
+ new_glyphs = std::move (update_glyphs);
574
+ glyph_sizes = std::move (update_sizes);
575
+
546
576
glyph_positions.clear ();
547
577
glyph_positions.reserve (new_glyphs.size ());
548
578
first_missing_index = 0 ;
0 commit comments