googlefonts / googlefonts/fontmake

Noto complex variable fonts

Open
#748 7 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
888
Forks
97
Avg merge
4d 52m
Merged PRs (30d)
1

Description

I have been asked to share the findings of my investigation of making variable fonts for Noto complex scripts here on GitHub. It seems best to summarise this as one issue. This can always be split up into separate issues for the various projects that are part of fontmake, if the need arrises.

First I have to say, that if I generate a variable font from a Glyphs file with _fontmake_, I do not have the Glyphs.app hassle of having to add all sorts of custom parameters and to change values that I have to change back if I want to generate stand alone fonts. I like that.

GPOS:

There do not seem to be GPOS problems when we have external OTL sources in Monotype's FontDame format. (But I was surprised to see the decompiled binary class-kerning lookups using a different numbering as the sources, which makes it quite a puzzle to check the values.)

Noto Serif Devanagari and Noto Serif Kannada use embedded feature code with a _dist_ feature with context rules. For the instances the _dist_ feature is modified by a "replacement feature" custom parameter. These are lost when generating a variable font. The values for the regular are used for all instances. A possible solution might be to use instance UFO's rather than master UFO's to generate variable fonts (I will get back about that). Another option is to try Glyphs 3 ability to add _number values_ to masters and refer to them in GPOS code.

For all complex scripts with Glyphs files with embedded feature code, the font generating tools are responsible for assembling kerning and attachment features. We discovered an anchor issue with Noto Serif Devanagari this week. From when we last supplied source files, I remember there were less noticeable issues with anchors too. It may make sense to get something in place to make certain it is working as should be. (It may also be a good idea to have the designer test their fonts before shipping.)

GSUB:

The Noto's Sans Myanmar, Sans Devanagari, Sans Gujarati and Serif Devanagari have more than one GSUB when we generate stand alone fonts. A am not familiar with the details of Myanmar, but the others have an i-vowel, with different lengths depending on the following base glyphs or half-vorm + base glyph with optional kerning between them. It is quite a puzzle to get a rule set right for 1 weight. Given that relative proportions of glyphs change depending on the weight of stems, we use different rules for weights to approximate the optimal i-vowel length.
For variable fonts we need to create a combined GSUB with the variants of the context lookups and a _Feature Variation Table_ to select the rule needed depending on the axis location.

In principle it is possible to work out differences between source GSUBs for different positions on the axis and generate the variable GSUB on the fly. I haven't tried to do that myself.
But I did update my own old tool to support compiling and decompiling of feature variations. For the Myanmar where there are two GSUBs that differ by two context rules only, I created a combined GSUB in Monotype FontDame format with feature variations table and added that to a variable font generated earlier (without GSUB) with _fontmake_. That works for me, if I were called upon to make variable fonts today. If a hobby programmer like me can make a tool to do this, I guess support for feature variations can be added to _mtiLib_ too and we supply variable GSUB sources.

The Noto Serif Devanagari has its GSUB feature variations stored as replacement features in instance custom parameters, which are ignored by _fontmake_ and Glyphs 2. I do not think Glyphs 3 does any better, because currently it cannot generate font files for Serif Devanagari at all.
In theory Glyphs 3 has support for feature variations, so that may be a path to explore. I do not see an "official" support for feature variations in feature syntax specification of Adobe and current do not know how to make feature variations other than with my own tool or TTX.

document/UI sources:

In the scripts that have a single Glyphs file for document and UI versions there needs to be a solution for sub-setting, re-encoding, separate vertical metrics and the UI y-shift. I now get a document variable, which should be functional, but has all the UI specific glyphs that it does not need. The UI variable is the document variable with the OTL tables of the UI font and that does not work at all.

A simple solution is of course to have two Glyphs files. Not nice, if there is ever a need to update or extend the design.

When I look at _fontmake_, I see it creates a set of master UFOs and a design space file, that are used to generate font files from. For stand alone OTFs or TTFs, it first creates instance UFOs, for a variable the master UFOs are used directly. I think this works in most cases, but not always. In Glyphs the masters are containers for glyph data, and the font files are represented by instance definitions, that grab what they need from the masters. In our document/UI source files every master has two instances at the same axis location. If for every master you generate the matching _instance_ UFO and use that as master to generate font files, I suspect that for stand alone font files the results would be the same as they are now, and we will get a UI and document variable font that are the same where they should be the same and different where they should be different.

The missing master issue:

In the old days of Ikarus, Fontographer and FontLab we could interpolate between 2 font files only. That meant that for a design space with masters in the corners, it did not matter what intermediate masters there were, as you would go trough steps to create intermediate masters anyway.

In Glyphs app all the masters are in one place, and the app tries to figure out interpolation values for any arbitrary combination of masters and instances, which may or may not have solutions which are ambiguous. But if we have masters in the corners of the design space and all the intermediate masters are on the edges of the design space, every instance on these edges is either a master or an unambiguous interpolation between two masters. And I think that settles what is in between the edges too.

For sources with weight and width axis that have 7 masters, the _fontmake_ variable ExtraCondensed Bold is very different from the Glyphs interpolated. And the _fontmake_ stand alone font is different too. I did not expect in 2015 that this could happen. It seems the master UFOs are treated as a variable font masters, rather than interpolation masters. But if you want a variable to match a set of masters designed for interpolation, we will have include the implicit masters that we get for free when interpolating.
I do not want to get into how to do that for any case, but in our simple case my thoughts are:

- We have a design space weight/width with masters in the corner.
- All masters are in corners or on the edge of the design space.
- For all masters there is an instance.
- All instances on the edges are paired on the opposite side of the design space.
Then
- Generate instance UFO's for the masters
- Interpolate the instances that are paired with a master-instance between the nearest instance UFO's on its side of the design space. (Treat the edges as four 1 axis families.)
- Use the resulting instance UFOs as master for the complete set of individual font files or variable fonts.

That is what I would try if I would have to do everything with _fontmake_ without touching the Glyphs file. Of course one could open Glyphs.app to create masters from instances, generate fonts, then remove these masters again. But having a tool that can deal with a wide range of possible sources is preferable.

GASP:

There is a very minimal GASP table. I could not help noticing when I tried out my experimental Sans Myanmar with feature variations in Windows that the little control panel item that allows you to try out variable fonts listed all 36 instances as "Regular". And I blame the GASP for that.

Note from two weeks later:
I was expecting that the instance UFOs produced by fontmake making fonts, would have had applied the instance properties of the Glyphs file instance definitions. In the actual instance UFO's that are currently generated that does not seem the case, and these properties are presumably applied when generating the font files. So when I mention to use instance UFO's to generate variable fonts, I should add that these should be instance UFO's as I expected them to be, not as they are now.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.