Skip to content

Commit f8dea40

Browse files
committed
Implement font fallback for libraqm
1 parent accb524 commit f8dea40

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed
Binary file not shown.

lib/matplotlib/tests/baseline_images/test_ft2font/last_resort.svg

Lines changed: 3 additions & 3 deletions
Loading

src/ft2font.cpp

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -444,13 +444,61 @@ void FT2Font::set_text(
444444
throw std::runtime_error("failed to set text flags for layout");
445445
}
446446

447-
std::set<FT_String*> glyph_seen_fonts;
448-
glyph_seen_fonts.insert(face->family_name);
449-
450447
if (!raqm_layout(rq)) {
451448
throw std::runtime_error("failed to layout text");
452449
}
453450

451+
std::vector<std::pair<size_t, const FT_Face&>> face_substitutions;
452+
std::set<FT_String*> glyph_seen_fonts;
453+
glyph_seen_fonts.insert(face->family_name);
454+
455+
// Attempt to use fallback fonts if necessary.
456+
for (auto const& fallback : fallbacks) {
457+
size_t num_glyphs = 0;
458+
auto const& rq_glyphs = raqm_get_glyphs(rq, &num_glyphs);
459+
bool new_fallback_used = false;
460+
461+
for (size_t i = 0; i < num_glyphs; i++) {
462+
auto const& rglyph = rq_glyphs[i];
463+
464+
if (rglyph.index == 0) {
465+
face_substitutions.emplace_back(rglyph.cluster, fallback->face);
466+
new_fallback_used = true;
467+
}
468+
}
469+
470+
if (new_fallback_used) {
471+
// If a fallback was used, then re-attempt the layout with the new fonts.
472+
if (!fallback->warn_if_used) {
473+
glyph_seen_fonts.insert(fallback->face->family_name);
474+
}
475+
476+
raqm_clear_contents(rq);
477+
if (!raqm_set_text(rq,
478+
reinterpret_cast<const uint32_t *>(text.data()),
479+
text.size()))
480+
{
481+
throw std::runtime_error("failed to set text for layout");
482+
}
483+
if (!raqm_set_freetype_face(rq, face)) {
484+
throw std::runtime_error("failed to set text face for layout");
485+
}
486+
for (auto [cluster, face] : face_substitutions) {
487+
raqm_set_freetype_face_range(rq, face, cluster, 1);
488+
}
489+
if (!raqm_set_freetype_load_flags(rq, flags)) {
490+
throw std::runtime_error("failed to set text flags for layout");
491+
}
492+
493+
if (!raqm_layout(rq)) {
494+
throw std::runtime_error("failed to layout text");
495+
}
496+
} else {
497+
// If we never used a fallback, then we're good to go with the existing
498+
// layout we have already made.
499+
break;
500+
}
501+
}
454502

455503
size_t num_glyphs = 0;
456504
auto const& rq_glyphs = raqm_get_glyphs(rq, &num_glyphs);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy