Skip to content

Commit 191d6f0

Browse files
committed
Implement font fallback for libraqm
1 parent 32a3832 commit 191d6f0

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

360-
std::set<FT_String*> glyph_seen_fonts;
361-
glyph_seen_fonts.insert(face->family_name);
362-
363360
if (!raqm_layout(rq)) {
364361
throw std::runtime_error("failed to layout text");
365362
}
366363

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

368416
size_t num_glyphs = 0;
369417
auto const& rq_glyphs = raqm_get_glyphs(rq, &num_glyphs);

0 commit comments

Comments
 (0)