mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
FreeType: Make font fallback slightly more robust
On Ubuntu 25.10, which includes Noto Color Emoji, I was seeing that the FontsDemo would assert when attempting to render non-emoji text using this font. It appears that FontConfig will tend to return Noto Color Emoji when this family name is passed, even though the font may not cover the required character set. The new strategy is to use FontConfig as before, but then to check the resolved font for coverage of the string. If the resolved font still can't render the string, we relax the font matching constraints by removing the family name from the pattern, then try matching again.
This commit is contained in:
parent
37cc73ad9f
commit
2f1c74981f
1 changed files with 38 additions and 23 deletions
|
|
@ -429,37 +429,52 @@ public:
|
|||
if (cache == nullptr)
|
||||
return {};
|
||||
|
||||
FcPatternPtr pattern { FcPatternCreate() };
|
||||
|
||||
const auto makeBasicPattern = [&]
|
||||
{
|
||||
FcPatternPtr pattern { FcPatternCreate() };
|
||||
|
||||
{
|
||||
FcValue value{};
|
||||
value.type = FcTypeString;
|
||||
value.u.s = unalignedPointerCast<const FcChar8*> (ftFace->face->style_name);
|
||||
FcPatternAdd (pattern.get(), FC_STYLE, value, FcFalse);
|
||||
}
|
||||
|
||||
{
|
||||
const FcCharSetPtr charset { FcCharSetCreate() };
|
||||
for (const auto& character : text)
|
||||
FcCharSetAddChar (charset.get(), (FcChar32) character);
|
||||
FcPatternAddCharSet (pattern.get(), FC_CHARSET, charset.get());
|
||||
}
|
||||
|
||||
if (language.isNotEmpty())
|
||||
{
|
||||
const FcLangSetPtr langset { FcLangSetCreate() };
|
||||
FcLangSetAdd (langset.get(), unalignedPointerCast<const FcChar8*> (language.toRawUTF8()));
|
||||
FcPatternAddLangSet (pattern.get(), FC_LANG, langset.get());
|
||||
}
|
||||
|
||||
return pattern;
|
||||
};
|
||||
|
||||
const auto fallbackWithFamily = std::invoke ([&]
|
||||
{
|
||||
auto pattern = makeBasicPattern();
|
||||
|
||||
FcValue value{};
|
||||
value.type = FcTypeString;
|
||||
value.u.s = unalignedPointerCast<const FcChar8*> (ftFace->face->family_name);
|
||||
FcPatternAddWeak (pattern.get(), FC_FAMILY, value, FcFalse);
|
||||
}
|
||||
|
||||
{
|
||||
FcValue value{};
|
||||
value.type = FcTypeString;
|
||||
value.u.s = unalignedPointerCast<const FcChar8*> (ftFace->face->style_name);
|
||||
FcPatternAddWeak (pattern.get(), FC_STYLE, value, FcFalse);
|
||||
}
|
||||
return fromPattern (pattern.get());
|
||||
});
|
||||
|
||||
{
|
||||
const FcCharSetPtr charset { FcCharSetCreate() };
|
||||
for (const auto& character : text)
|
||||
FcCharSetAddChar (charset.get(), (FcChar32) character);
|
||||
FcPatternAddCharSet (pattern.get(), FC_CHARSET, charset.get());
|
||||
}
|
||||
if (text.isEmpty() || fallbackWithFamily->getNominalGlyphForCodepoint (*text.getCharPointer()).has_value())
|
||||
return fallbackWithFamily;
|
||||
|
||||
if (language.isNotEmpty())
|
||||
{
|
||||
const FcLangSetPtr langset { FcLangSetCreate() };
|
||||
FcLangSetAdd (langset.get(), unalignedPointerCast<const FcChar8*> (language.toRawUTF8()));
|
||||
FcPatternAddLangSet (pattern.get(), FC_LANG, langset.get());
|
||||
}
|
||||
|
||||
return fromPattern (pattern.get());
|
||||
const auto fallbackWithoutFamily = fromPattern (makeBasicPattern().get());
|
||||
jassert (fallbackWithoutFamily->getNominalGlyphForCodepoint (*text.getCharPointer()).has_value());
|
||||
return fallbackWithoutFamily;
|
||||
#else
|
||||
// Font substitution will not work unless fontconfig is enabled.
|
||||
jassertfalse;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue