Skip to content

Commit 4a2be84

Browse files
committed
Implement font fallback for libraqm
1 parent da31a3f commit 4a2be84

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

src/ft2font.cpp

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

363-
std::set<FT_String*> glyph_seen_fonts;
364-
glyph_seen_fonts.insert(face->family_name);
365-
366363
if (!raqm_layout(rq)) {
367364
throw std::runtime_error("failed to layout text");
368365
}
369366

367+
std::vector<std::pair<size_t, const FT_Face&>> face_substitutions;
368+
std::set<FT_String*> glyph_seen_fonts;
369+
glyph_seen_fonts.insert(face->family_name);
370+
371+
// Attempt to use fallback fonts if necessary.
372+
for (auto const& fallback : fallbacks) {
373+
size_t num_glyphs = 0;
374+
auto const& rq_glyphs = raqm_get_glyphs(rq, &num_glyphs);
375+
bool new_fallback_used = false;
376+
377+
for (size_t i = 0; i < num_glyphs; i++) {
378+
auto const& rglyph = rq_glyphs[i];
379+
380+
if (rglyph.index == 0) {
381+
face_substitutions.emplace_back(rglyph.cluster, fallback->face);
382+
new_fallback_used = true;
383+
}
384+
}
385+
386+
if (new_fallback_used) {
387+
// If a fallback was used, then re-attempt the layout with the new fonts.
388+
if (!fallback->warn_if_used) {
389+
glyph_seen_fonts.insert(fallback->face->family_name);
390+
}
391+
392+
raqm_clear_contents(rq);
393+
if (!raqm_set_text(rq,
394+
reinterpret_cast<const uint32_t *>(text.data()),
395+
text.size()))
396+
{
397+
throw std::runtime_error("failed to set text for layout");
398+
}
399+
if (!raqm_set_freetype_face(rq, face)) {
400+
throw std::runtime_error("failed to set text face for layout");
401+
}
402+
for (auto [cluster, face] : face_substitutions) {
403+
raqm_set_freetype_face_range(rq, face, cluster, 1);
404+
}
405+
if (!raqm_set_freetype_load_flags(rq, flags)) {
406+
throw std::runtime_error("failed to set text flags for layout");
407+
}
408+
409+
if (!raqm_layout(rq)) {
410+
throw std::runtime_error("failed to layout text");
411+
}
412+
} else {
413+
// If we never used a fallback, then we're good to go with the existing
414+
// layout we have already made.
415+
break;
416+
}
417+
}
370418

371419
size_t num_glyphs = 0;
372420
auto const& rq_glyphs = raqm_get_glyphs(rq, &num_glyphs);

0 commit comments

Comments
 (0)