Font handling

From LilyPond Wiki

Jump to: navigation, search

This page will serve as a place to explain the methods LilyPond uses to handle fonts, and it will suggest ways in which font handling can be improved. If any information included here is incorrect, please change it! Wikis are fun!

Contents

[edit] Explaining the source files

[edit] scm/font.scm

This is where the font "tree" is built, which contains all of the possible fonts LilyPond can use. The source code in this file is quite confusing, because a Scheme OOP system called GOOPS is used, which uses angle brackets to delimit class names.

The tree is built using "font-qualifiers" to denote tree level, font-qualifier values for nodes, and the actual fonts as leaves. The font qualifiers have a "default qualifier order" which defines the level hierarchy. That order is '(font-encoding font-family font-shape font-series). The music fonts (Emmentaler and Aybabtu) only have one font-qualifier (font-encoding), but the pango fonts have all of the font-qualifiers. font-encoding is the root of the tree. Below is the default tree represented in table form:

font-encoding | font-family | font-shape | font-series | (leaves)
-----------------------------------------------------------------
fetaDynamic --> feta ----------------------------------> <Font>
fetaNumber ---> feta ----------------------------------> <Font>
fetaMusic ----> feta ----------------------------------> <Font>
fetaBraces ---> feta ----------------------------------> <Font>
fetaDynamic --> gonville ------------------------------> <Font>
fetaNumber ---> gonville ------------------------------> <Font>
fetaMusic ----> gonville ------------------------------> <Font>
fetaBraces ---> gonville ------------------------------> <Font>
latin1 -------> roman ------> upright ---> normal -----> <Font>
latin1 -------> roman ------> caps ------> normal -----> <Font>
latin1 -------> roman ------> upright ---> bold -------> <Font>
latin1 -------> roman ------> italic ----> normal -----> <Font>
latin1 -------> roman ------> italic ----> bold -------> <Font>
latin1 -------> sans -------> upright ---> normal -----> <Font>
latin1 -------> sans -------> caps ------> normal -----> <Font>
latin1 -------> sans -------> upright ---> bold -------> <Font>
latin1 -------> sans -------> italic ----> normal -----> <Font>
latin1 -------> sans -------> italic ----> bold -------> <Font>
latin1 -------> typewriter -> upright ---> normal -----> <Font>
latin1 -------> typewriter -> caps ------> normal -----> <Font>
latin1 -------> typewriter -> upright ---> bold -------> <Font>
latin1 -------> typewriter -> italic ----> normal -----> <Font>
latin1 -------> typewriter -> italic ----> bold -------> <Font>

The table above defines every "path" a font can take for LilyPond to recognize it. For example, a font with #'font-shape = #'caps and #'font-series = #'bold will never work, because a path between these two nodes does not exist in the tree.

[edit] Debugging the tree

To debug the font tree in scm/font.scm, change the lookup-font procedure to this:

(define (lookup-font node alist-chain)
  (display node)
  (g-lookup-font node alist-chain))

[edit] lily/pango-select.cc

This is where the PangoFontDescription strings are constructed for the Pango fonts in the font-tree (scm/font.scm). These strings are of the form "[FONT-FAMILY] [STYLE-OPTIONS] [SIZE]", where FONT-FAMILY is a single font-family name or a comma-separated list of font families; STYLE-OPTIONS is an optional space-separated list of keywords for various font styles, weights, variants, and stretch values; and SIZE is the font size.

The various functions in this file choose the appropriate contents for a PangoFontDescription string based on the given font qualifiers (except for font-encoding, which is always latin1 for Pango fonts). For example, if the value of 'font-shape is 'italic, then the constant PANGO_STYLE_ITALIC is handed to the PangoFontDescription, and the string "Italic" is inserted into the PangoFontDescription string. Another example: if the value of 'font-shape is 'caps, then PANGO_VARIANT_SMALL_CAPS is selected, and "Small-Caps" is inserted into the PangoFontDescription string.

In the end, the PangoFontDescription could look like "Century Schoolbook L Bold Italic 3.86805230664", and this value is used in the backends for selecting the appropriate font.

[edit] The feta-alphabet issue

Keep this section here for historical purposes; we might want to find a more elegant solution someday, but this issue was fixed a few days ago. Pnorcks 04:39, 10 March 2010 (UTC)

  • The feta-alphabet Type1 fonts should not be used anymore, because they are a subset of Emmentaler. It looks like the goal is to have all fonts loaded with Pango, but neither Pango nor Fontconfig can classify the Emmentaler fonts according to their design size.
    • I should have searched the archives first; Werner posted a long description about this a few months ago here.
      • While it would be nice to add a `font-style' property to LilyPond and use that for the design sizes, as Werner suggested, this would be impossible with Pango; Pango only recognizes normal, oblique, and italic for font-style values. Also, values like 11, 13, or 20 are not valid XML font-styles either. We would need to implement a custom interface, I suppose, that supports such values; if a backend (right now, just the PS backend) requests the design size, Pango_font would know about it. Pnorcks 08:55, 3 November 2009 (UTC)
    • This is a really challenging issue. I still can't wrap my head around it completely. There are various issues to consider: 1) Fontforge should add information to the Emmentaler OTF fonts that can be used to distinguish between design sizes, 2) Fontconfig needs support for recognizing this information, 3) Pango needs to support it too, and 4) everything must work with the PS and SVG backends. Maybe we need to embed another OTF table with this information, instead of doing it through Fontforge? Pnorcks 08:31, 3 November 2009 (UTC)
      • I might be confusing the issues here. Fonts are either loaded by LilyPond or by Pango. But the fonts loaded by Pango (and its Fontconfig interface) might not have access to the custom OTF tables. Hmm.. Pnorcks 08:35, 3 November 2009 (UTC)

[edit] Other problems

There is a major issue with LilyPond's "make test" output: sometimes fonts are embedded in regtests when those fonts are not even used! See [1].

  • My patch [2] will be used to fix this issue for now, but it's only a temporary workaround. A real solution requires a reworking of the entire Pango font-selection mechanism. The details of the problem can be found in the comments for the issue referenced above.

[edit] Ideas for improvement

  • A user should be able to specify any combination of font "styles" in order to help choose the correct font. Currently, the user is limited to the choosing the style combinations found in scm/font.scm. Ideally, this limitation should not exist.
  • There are many PangoFontDescription values in lily/pango-select.cc that are not accessible for similar reasons.
  • I think the current font qualifier names (font-interface properties) should be renamed so that they correspond to the W3C recommendations. The current set of names is as follows:
font-family
font-shape
font-series

I think they should be changed to:

font-family
font-style
font-variant
font-weight
font-stretch

The conversions would be

  1. font-weight --> font-series
  2. font-shape split into font-style and font-variant
  3. font-stretch would be a new property, so no conversion needed
  • The PangoFontDescription regular expressions in scm/output-svg.scm would start to get very hairy if the font tree is enlarged to accommodate more font qualifier values (such as "ultrabold" and "oblique"). One solution would be to pass a Pango_font smob to utf-8-string instead, and use callback functions to extract the appropriate information from PangoFontDescriptions (instead of using regular expressions for this task).
    • This would still be ugly though. It might be better to fix the description on the C++ end before sending it to the SVG backend.
  • Think about reworking the entire Pango-font selection framework, or make Pango do more of the work, if possible.
Personal tools