351 {
354 return nullptr;
355 }
356 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
358
359 if (font_glyph_map.empty()) {
360 return last_atlas;
361 }
362
363
364
365
366
367
368 std::vector<Rect> glyph_sizes;
369 std::vector<FontGlyphPair> new_glyphs;
370 for (const auto& font_value : font_glyph_map) {
371 const ScaledFont& scaled_font = font_value.first;
372 const FontGlyphAtlas* font_glyph_atlas =
373 last_atlas->GetFontGlyphAtlas(scaled_font.font, scaled_font.scale);
374
375 auto metrics = scaled_font.font.GetMetrics();
376
379 metrics.point_size, metrics.scaleX, metrics.skewX);
382 sk_font.setEmbolden(metrics.embolden);
383
384
385
386 sk_font.setSize(sk_font.getSize() * scaled_font.scale);
387 sk_font.setSubpixel(true);
388
389 if (font_glyph_atlas) {
390 for (const SubpixelGlyph& glyph : font_value.second) {
391 if (!font_glyph_atlas->FindGlyphBounds(glyph)) {
392 new_glyphs.emplace_back(scaled_font, glyph);
393 glyph_sizes.push_back(
395 }
396 }
397 } else {
398 for (const SubpixelGlyph& glyph : font_value.second) {
399 new_glyphs.emplace_back(scaled_font, glyph);
400 glyph_sizes.push_back(
402 }
403 }
404 }
405 if (new_glyphs.size() == 0) {
406 return last_atlas;
407 }
408
409
410
411
412
413 std::vector<Rect> glyph_positions;
414 glyph_positions.reserve(new_glyphs.size());
415 size_t first_missing_index = 0;
416
417 if (last_atlas->GetTexture()) {
418
420 last_atlas, new_glyphs, glyph_positions, glyph_sizes,
421 atlas_context->GetAtlasSize(), atlas_context->GetHeightAdjustment(),
422 atlas_context->GetRectPacker());
423
424
425
426
427
428 for (
size_t i = 0;
i < first_missing_index;
i++) {
429 last_atlas->AddTypefaceGlyphPositionAndBounds(
430 new_glyphs[
i], glyph_positions[
i], glyph_sizes[
i]);
431 }
432
433 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
434 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
435
437 blit_pass->EncodeCommands(context.GetResourceAllocator());
438 context.GetCommandQueue()->Submit({std::move(cmd_buffer)});
439 });
440
441
442
443
444
446 last_atlas->GetTexture(), new_glyphs, 0,
447 first_missing_index)) {
448 return nullptr;
449 }
450
451
452 if (first_missing_index == new_glyphs.size()) {
453 return last_atlas;
454 }
455 }
456
457 int64_t height_adjustment = atlas_context->GetAtlasSize().height;
458 const int64_t max_texture_height =
459 context.GetResourceAllocator()->GetMaxTextureSizeSupported().height;
460
461
462
463
464
465
466 bool blit_old_atlas = true;
467 std::shared_ptr<GlyphAtlas> new_atlas = last_atlas;
468 if (atlas_context->GetAtlasSize().height >= max_texture_height ||
470 blit_old_atlas = false;
471 first_missing_index = 0;
472 glyph_positions.clear();
473 height_adjustment = 0;
474 new_atlas = std::make_shared<GlyphAtlas>(
type);
475 atlas_context->UpdateRectPacker(nullptr);
476 atlas_context->UpdateGlyphAtlas(new_atlas, {0, 0}, 0);
477 }
478
479
481 new_glyphs,
482 glyph_positions,
483 glyph_sizes,
484 first_missing_index,
485 max_texture_height
486 );
487
488 atlas_context->UpdateGlyphAtlas(new_atlas, atlas_size, height_adjustment);
489 if (atlas_size.IsEmpty()) {
490 return nullptr;
491 }
492 FML_DCHECK(new_glyphs.size() == glyph_positions.size());
493
494 TextureDescriptor descriptor;
497 descriptor.format =
498 context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
499 break;
502 break;
503 }
504 descriptor.size = atlas_size;
507 std::shared_ptr<Texture> new_texture =
508 context.GetResourceAllocator()->CreateTexture(descriptor);
509 if (!new_texture) {
510 return nullptr;
511 }
512
513 new_texture->SetLabel("GlyphAtlas");
514
515 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
516 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
517
518
519
520
521 {
523 size_t byte_size =
524 new_texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
527
529 byte_size);
532 }
533
535 blit_pass->EncodeCommands(context.GetResourceAllocator());
536 context.GetCommandQueue()->Submit({std::move(cmd_buffer)});
537 });
538
539
540 if (new_atlas->GetTexture() && blit_old_atlas) {
541 blit_pass->AddCopy(new_atlas->GetTexture(), new_texture,
543 {0, 0});
544 }
545
546
547 new_atlas->SetTexture(std::move(new_texture));
548
549
550
551
552
553 for (
size_t i = first_missing_index;
i < glyph_positions.size();
i++) {
554 new_atlas->AddTypefaceGlyphPositionAndBounds(
555 new_glyphs[
i], glyph_positions[
i], glyph_sizes[
i]);
556 }
557
558
559
560
561
563 new_atlas->GetTexture(), new_glyphs,
564 first_missing_index, new_glyphs.size())) {
565 return nullptr;
566 }
567
568
569
570
571 return new_atlas;
572}
@ kSlight
minimal modification to improve constrast
@ kAntiAlias
may have transparent pixels on glyph edges
Wraps a closure that is invoked in the destructor unless released by the caller.
static TypefaceSkia & Cast(Typeface &base)
const sk_sp< SkTypeface > & GetSkiaTypeface() const
virtual bool IsValid() const
#define FML_DCHECK(condition)
std::function< void()> closure
static Rect ComputeGlyphSize(const SkFont &font, const SubpixelGlyph &glyph, Scalar scale)
static size_t AppendToExistingAtlas(const std::shared_ptr< GlyphAtlas > &atlas, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, const std::vector< Rect > &glyph_sizes, ISize atlas_size, int64_t height_adjustment, const std::shared_ptr< RectanglePacker > &rect_packer)
static ISize ComputeNextAtlasSize(const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, const std::vector< Rect > &glyph_sizes, size_t glyph_index_start, int64_t max_texture_height)
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, std::shared_ptr< BlitPass > &blit_pass, HostBuffer &host_buffer, const std::shared_ptr< Texture > &texture, const std::vector< FontGlyphPair > &new_pairs, size_t start_index, size_t end_index)
constexpr size_t DefaultUniformAlignment()
static constexpr TRect MakeSize(const TSize< U > &size)
#define TRACE_EVENT0(category_group, name)