[Fontconfig] Marking glyphs as deliberately blank, per font

Nicolas Mailhot nicolas.mailhot at laposte.net
Thu Nov 26 16:10:21 PST 2009


Le jeudi 26 novembre 2009 à 23:07 +0100, Nicolas Mailhot a écrit :
> Le jeudi 26 novembre 2009 à 22:06 +0100, Krzysztof Kotlenga a écrit
>  
> > It doesn't solve any of my pains :)
> 
> It solves the "part of the font file has bogus blank glyphs"

To expand yet more (thinking loud), the core fontconfig syntax no one
ever had any problem with is 

<alias>
  <family>serif</family>
  <prefer>
    <family>Bitstream Vera Serif</family>
    <family>DejaVu Serif</family>
  </prefer>
</alias>

It is easy to understand because is clearly states
1. the question: what fontconfig is resolving (serif)
2. the priorized list of possible answer
3. that it constructs a virtual alias

in a compact declarative syntax and not an intermingling of XML and
functional code-like statements

Looking back at the most common fontconfig statements we use in Fedora
you find:

A. Declaring which generic a font contributes to:

<alias>
  <family>[genericname]</family>
  <prefer>
    <family>[fontname]</family>
  </prefer>
</alias>

(basic rule already discussed)


B. Declaring where to take elements to complete a font (usually a
generic)

<alias>
  <family>[fontname]</family>
  <default>
    <family>[genericname]</family>
  </default>
</alias>

Except things already start going downhill, what was prefer before is
default now for no clear reason. Why can't prefer be used in both cases?

<alias>
  <family>[fontname]</family>
  <prefer>
    <family>[genericname]</family>
  </prefer>
</alias>

C. Declaring a font can be used as replacement for another font if this
other font is absent

<alias binding="same">
  <family>[otherfontname]</family>
  <accept>
    <family>[fontname]</family>
  </accept>
</alias>

Now it's not default or prefer but accept. And there is a weird binding
thinguie. To keep syntax consistent, it should have been

<alias>
  <family>[otherfontname]</family>
  <prefer>
    <family>[otherfontname]</family>
    <family>[fontname]</family>
  </prefer>
</alias>

Which is a little more verbose, but uses the same verbs as A.

D. Then you have locale overrides (the most painful part right now)

<match>
  <test name="lang">
    <string>[loc]</string>
  </test>
  <test name="family">
    <string>[genericname]</string>
  </test>
  <edit name="family" mode="prepend" binding="same">
    <string>[fontname]</string>
  </edit>
</match>

Things continue to devolve in special syntax. And this block BTW is very
confusing to packagers : since it uses prepend, the last such block will
win, when it's the first one for other rules. Also it will slap a whole
font at the top of the stack when the packager really only wanted to
change glyphs associated with loc (not all glyphs when lang is loc)

To keep syntax consistent with A. and have a reliable rule the packager
understands, it should have been

<alias>
  <font>
    <family>[genericname]</family>
    <lang>[loc]</lang>
  </font>
  <prefer>
    <font>
      <family>[fontname]</family>
      <lang>[loc]</lang>
    </font>
  </prefer>
</alias>

And here we can even forget unicode han unification, we've just stated
succintly that when fontconfig needs the loc lang bits in genericname,
it should take the loc lang bits in fontname (and only them). As a bonus
there is no need of evil prepending black magic anymore to fight for
priority with other CJK fonts

E. And font rescaling

<match target="font">
  <test name="family" mode="eq">
    <string>[fontname]</string>
  </test>
  <edit name="matrix" mode="assign">
    <times>
      <name>matrix</name>
      <matrix>
        <double>[factor]</double>
        <double>0</double>
        <double>0</double>
        <double>[factor]</double>
      </matrix>
    </times>
  </edit>
</match>

should have been

<alias>
  <family>[fontname]</family>
  <prefer>
    <font>
      <family>[fontname]</family>
      <matrix>...</matrix>
    </font>
  </prefer>
</alias>

F. Font merging

  <match target="scan">
    <test name="family">
      <string>[fontname]</string>
    </test>
    <edit name="fontversion">
      <int>2</int>
    </edit>
  </match>
  <match target="scan">
    <test name="family">
      <string>[mergedfontname]</string>
    </test>
    <edit name="family">
      <string>[fontname]</string>
    </edit>
    <edit name="fullname">
      <string>[fontname] [fontstyle]</string>
    </edit>
    <edit name="fontversion">
      <int>1</int>
    </edit>
  </match>

should have been

<alias>
  <font>
    <family>[mergedfontname]</family>
    <style>[mergedfontstyle]</style>
  <font>
  <font>
    <fullname>[mergedfullname]</fullname>
  </font>
  <prefer>
    <font>
      <family>[fontname1]</family>
      <style>[fontstyle1]</style>
    <font>
    <font>
      <family>[fontname2]</style>
      <style>[fontstyle2]</style>
    <font>
  </prefer>
</alias>

In this example we alias a font both when it is accessed trough
(mergedfontname and mergedfontstyle) and when it is accessed through
mergedfullname

(I admit that there alias alone is probably insufficient as you want to
tell fontconfig to only display mergedfontname, mergedfontstyle in
lists. But that's the only elements that can not be declared directly
using the same syntax as other examples)

G. Font remapping

<match target="scan">
  <test name="family">
    <string>[problemfontname]</string>
  </test>
  <test name="style">
    <string>[problemfontstyle]</string>
  </test>
  <edit name="family">
    <string>[correctedfontname]</string>
  </edit>
  <edit name="style">
    <string>[correctedfontstyle]</string>
  </edit>
  <edit name="fullname">
    <string>[correctedfontname] [correctedfontstyle]</string>
  </edit>
</match>

Should have been

<alias>
  <font>
    <family>[correctedfontname]</family>
    <style>[correctedfontstyle]</style>
  <font>
  <font>
    <fullname>[correctedfontname] [correctedfontstyle]</fullname>
  </font>  
  <prefer>
    <font>
      <file>location-of-the-problem-file</file>     
    <font>
  </prefer>
</alias>

(like in the previous example, needs a twist to hide the metadata de
problem file declares)

H. When a font has some rotten parts it could be declared with something
like

<alias>
  <family>[fontname]</family>
  <prefer>
    <font>
      <family>[fontname]</family>
      <!-- list of the good parts in the font, or bad parts not-ed -->
      <lang>[loc1]</lang>
      <lang>[loc2]</lang>
    </font>
    <family>[genericname]</family>
  </prefer>
</alias>

ie when requested fontname, use the loc1 and loc2 parts of fontname
only, and fallback to genericname for the rest

I hope those examples make my thoughts clearer. Basically, there are too
many different verbs and special syntax in current fontconfig files,
when the bulk of what people need to declare is always blocks like

1. list of font pattern to resolve (or fake)
2. list of font patterns to try as answer in priority order
3. what the apps should see (actual metadata of the files used as answer
or something else)

I suppose the current system is friendly to people who know fontconfig
code innards, but others do not want to know so much about them.

I've used (and abused) of the A. pattern here, it's probably not the
best syntax to use as a general case, and one could probably do
something cleaner like

<!-- A unit block -->
<rule>
  <!-- (optional) list of font blocks we can resolve, if we need a
context (remapping, merging and creating fake generics does not need a
particular one -->
  <match>
    <font>...</font>
  </match>
  <!-- list of font blocks used to compose the result, by preference
order -->
  <prefer>
    <font>...<font>
    <font>...<font>
  </prefer>
  <!-- (optional) what the apps should display: only a font with those
fake characteristics, only the bits we used to compose it, or both. This
part is useful for remapping, merging and creating fake generics -->
  <fake display="fake/constituants/both">
    <font>...</font>
  </fake>
</rule>

And then you define that a <font> element that only includes one child
can be expressed directly as this child. For example

<font>
 <family>foo</family>
</font>

and

<family>foo</family>

Are the same thing, <font> is only a container to specify multiple
concurrent characteristics.

So, I'm not asking for current fontconfig config syntax to be replaced
with this one, but it would be mighty nice if it could evolve towards
something as simple and generic as this example, with less black magic
sprinkled everywhere.

-- 
Nicolas Mailhot




More information about the Fontconfig mailing list