Skip to content

Commit 6df3eed

Browse files
committed
Implement font fallback for libraqm
1 parent 00037f8 commit 6df3eed

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
@@ -351,13 +351,61 @@ void FT2Font::set_text(
351351
throw std::runtime_error("failed to set text flags for layout");
352352
}
353353

354-
std::set<FT_String*> glyph_seen_fonts;
355-
glyph_seen_fonts.insert(face->family_name);
356-
357354
if (!raqm_layout(rq)) {
358355
throw std::runtime_error("failed to layout text");
359356
}
360357

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

362410
size_t num_glyphs = 0;
363411
auto const& rq_glyphs = raqm_get_glyphs(rq, &num_glyphs);

0 commit comments

Comments
 (0)