[Fontconfig] FcSort and proper fontfallback

Behdad Esfahbod behdad at behdad.org
Sun Feb 7 00:14:06 UTC 2021


Most likely explanation is that your distro's config file for Noto Color
Emoji is appending that family name to any request patterns you make...

The FcFontSort() returned list is definitely designed to be used for
fallback.  In general, Noto Color Emoji being there as second should not
cause your fallback any problems. If it does, that might point to another
problem in your fallback scheme design.

HTH,
behdad
http://behdad.org/


On Fri, Feb 5, 2021 at 9:19 AM Christian Parpart <christian at parpart.family>
wrote:

> Hey guys.
>
> This is my first post, so I hope i'm doing it right and that's the right
> place (couldn't find a better one).
>
> I am using fontconfig to get a font and a related list of fallback fonts
> for styles such as regular/bold/italic/bold-italic but also a font with
> font family "emoji".
>
> While it works in general, I wonder why - not matter what - it seems that
> "Noto Color Emoji" font family is placed on second place of the fonts
> returned by FcFontSort.
>
> This is what I do:
>
>         auto const family = string(_family);
>         auto pat = unique_ptr<FcPattern,
> void(*)(FcPattern*)>(FcPatternCreate(), [](auto p) { FcPatternDestroy(p);
> });
>
>         FcPatternAddBool(pat.get(), FC_OUTLINE, true);
>         FcPatternAddBool(pat.get(), FC_SCALABLE, true);
>         //FcPatternAddBool(pat.get(), FC_EMBEDDED_BITMAP, false);
>
>         FcPatternAddBool(pat.get(), FC_COLOR, _color); // with _color
> being bool (either true or false)
>
>         if (!_family.empty()) // such as "Fira Code" or "emoji"
>             FcPatternAddString(pat.get(), FC_FAMILY, (FcChar8 const*)
> family.c_str());
>
>         if (_monospace)
>         {
>             if (_family != "monospace")
>                 FcPatternAddString(pat.get(), FC_FAMILY, (FcChar8 const*)
> "monospace");
>             FcPatternAddInteger(pat.get(), FC_SPACING, FC_MONO); // in
> monospace (non-emoji), mono and dual are okay.
>             FcPatternAddInteger(pat.get(), FC_SPACING, FC_DUAL); // tried
> with and without this line
>         }
>
>         if (int(_style) & int(FontStyle::Bold))
>             FcPatternAddInteger(pat.get(), FC_WEIGHT, FC_WEIGHT_BOLD);
>
>         if (int(_style) & int(FontStyle::Italic))
>             FcPatternAddInteger(pat.get(), FC_SLANT, FC_SLANT_ITALIC);
>
>         FcConfigSubstitute(nullptr, pat.get(), FcMatchPattern);
>         FcDefaultSubstitute(pat.get());
>
>         FcResult result = FcResultNoMatch;
>         auto fs = unique_ptr<FcFontSet, void(*)(FcFontSet*)>(
>             FcFontSort(nullptr, pat.get(), /*unicode-trim*/FcTrue,
> /*FcCharSet***/nullptr, &result),
>             [](auto p) { FcFontSetDestroy(p); });
>
>
> Now, fs contains the FontSet prioritized by closeness (that's what the
> docs are saying), so I believe that means, I can use that as font fallback
> list.
> With first font being the requested one (or close match), and a
> prioritized list of fallbacks to walk through in case needed.
>
> For some reason, the second font in the list for regular fonts (font
> family is NOT "emoji" and _color is set to false) is actually "Noto Color
> Emoji Regular".
> I really tried hard to get it to a point where FcFontSort gets me only
> what I requested via FcPatternAddXXX, but it sometimes looks like
> all my FcPatternAddXXX don't mean anything.
>
> Secondly, when I request monospace fonts (_monospace == true, _color =
> false), then FcFontSort also returns fonts
> whose FC_SPACING  is not FC_MONO or FC_MONO, in fact:
>
>             int spacing = -1; // ignore font if we cannot retrieve spacing
> information
>             FcPatternGetInteger(font, FC_SPACING, 0, &spacing);
>             if (_monospace && spacing < FC_DUAL) continue; /* don't
> include non-monospace fonts if not requested).
>
> This call to FcPatternGetInteger(... FC_SPACING, ...) seems to fail
> quite often (does not store the value in spacing, as it remains -1.
>
> Whereas the following:
>
>             FcBool color = FcFalse;
>             FcPatternGetInteger(font, FC_COLOR, 0, &color);
>
> never yields true/FcTrue not even for Noto Color Emoji.
>
> (If that matters, this was tested on Ubuntu 20.10).
>
> It is really not the easiest to find good examples on how to use this API,
> so I may as well just be doing it wrong.
> But if so, I'd really appreciate some hint or indication of what I could
> do to achieve that.
>
> The purpose of all this is, that I am developing a terminal emulator where
> I use fontconfig to find monospace fonts (with font fallback)
> as well as emoji in color and emoji text versions (for emoji text
> versions, it seems I can use use the regular monospace font,
> iff it wouldn't include "Noto Color Emoji" so far on top in the priority
> list. Explicitely hardcoding it out via a hacky if-statement
> yields the expected result, but that can't be it.
> At the same time, gnome-terminal & kitty chose the right fonts (with
> everything configured the same).
> For kitty I know it's not using FcFontSort, as it priorizes manually,
> maybe because of the above?
>
> I'd realy appreciate some feedback here,
> Many thanks in advance,
> Christian Parpart.
>
>
>
>
> _______________________________________________
> Fontconfig mailing list
> Fontconfig at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/fontconfig
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/fontconfig/attachments/20210206/140f3e7f/attachment.htm>


More information about the Fontconfig mailing list