Please add <group> → <like>
This is a part of: #200
The core feature provided by fontconfig is the ability to substitute fonts, when an exact match is not available. That requires tracking font family similarity. And, similarity is a two-way street.
However, the current similarity syntax is unidirectional, and subject to complex priorization rules. As a result, managing a big pool of fontconfig substitution rules, for example at the Linux distribution level, is a hard task.
The aim of the proposed syntax element is to create bi-directional links by default, with a clear priorization model that obviates the current requirement for fine-grained config file ordering.
like contains an ordered list of the font families which are similar to the family associated with the
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <!-- SPDX-License-Identifier: MIT --> <fontconfig> <group> <target>@canonical_family_name@</target> <like> <family>@similar_family_name@</family> <family>@generic_family_name@</family> </like> </group> </fontconfig>
All the font families declared in a
like block, can be used as substitution fallbacks, when the files associated, directly or via
merge, with an
group target family, are insufficient to satisfy a query.
merge, the font families listed in
like are not consumed by the rule and are still available as-is in font lists. Font families consumed by a
merge can not participate in a
The substitution rule is multi-directional:
- the font family associated with the
groupelement, is also automatically declared as suitable substitute for all the families listed in
- all the families in
likeare also added as substitutes to one another (intra substitution)
Fontconfig should at least warn, when a
like block, contains families, that already have a substitution relationship, with a generic, that differs from the one used in the
To avoid the problems induced by the current substitution syntax,
like comes with a strong ordering model. The substitution list for a specific font family is constructed the following way:
- all the non-generic families in its own
likeblock, in their declaration order (merging
groupblocks if several blocks for the same family exist)
- all the non-generic families declared as suitable substitutes some other way, in declaration order (classical fontconfig substitution rules, reverse
groupsubstitution rules, intra-
likesubstitution rules, etc)
- the generic font family its own
likeblock (using multiple generics should be treated as an error, the whole point of generics is to force classification of fonts in distinct classes).
- the first generic declared as suitable substitute for one of the other families, if no generic was declared in the family’s own
The first consequence of this ordering model is that the
group element for a font family clearly owns the top of the substitution list for this font family, and everything else is just lower-priority additions.
There is no need to agonize how config files for different font families should be priorized.
There is no need to split rules for a specific font family in a high-priority config file with direct substitution rules, and a low priority file with indirect substitution rules.
The second consequence of this ordering model, is that converting generics, to
group, is sufficient to take back control of default font ordering for a system, without needing to change anything else, and without losing the low priority additions provided by all the other fontconfig configuration files.
The low-level elements of this proposal correspond to the classical:
- reverse generic substitution
<alias> <family>@generic_family_name@</family> <prefer> <family>@canonical_family_name@</family> </prefer> </alias>
- direct generic substitution
<alias> <family>@canonical_family_name@</family> <default> <family>@generic_family_name@</family> </default> </alias>
- direct substitution
<alias binding="same"> <family>>@canonical_family_name@</family> <accept> <family>@similar_family_name@</family> </accept> </alias>
- indirect substitution
<alias binding="same"> <family>@similar_family_name@</family> <accept> <family>@canonical_family_name@</family> </accept> </alias>
However, since this syntax forces separate declaration of all the substitution links, and separate declaration of every direction in those links, it is very easy for a human to lose track of all the declarations, even for a limited number of font families.
Moreover, the current declaration order logic of fontconfig, would require splitting those blocks in multiple configuration files, that correspond to the position of the link in each substitution chain. That is prohibitively complex, no one does that, that is one reason the substitution order is so suboptimal at a distribution level.
The new syntax proposal, just by making all substitution links multidirectional by default, and setting clear priorization rules, that depend on the intent of each configuration block, not on its position among a forest of other configuration files, makes substitution ordering manageable again.
Minimal real-world example
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <!-- SPDX-License-Identifier: MIT --> <fontconfig> <group> <target>DejaVu Sans Mono</target> <like> <family>DejaVu LGC Sans Mono</family> <family>Bitstream Vera Sans Mono</family> <family>monospace</family> </like> </group> </fontconfig>