question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[varLib.mutator] Support partial VF instances

See original GitHub issue

The current fontTools.varlib.mutator module can fully instantiate a variable font into a static font at a given location along all the axes.

The Google Fonts team is interested in adding support for generating “partial” instances: i.e one wants to keep wght axis but pin the wdth axis to a specific location, either the default or a custom one, dropping all the variation data relating to the pinned axes. Or alternatively one may want to restrict the range (min and/or max) of an axis, producing a new VF with possibly smaller file size.

We have created a new branch partial-instancer in here where we pushed a new module called fontTools.varLib.partialInstancer (the name may change, I’m thinking just “instancer” sounds better). It’s is based on the mutator module and has a similar interface. When it’s complete, potentially it could subsume the functionality of mutator, since the partial instancing can be seen as a more general problem.

The module is still in early stages and can currently only pin-and-drop gvar variation data. Limiting axis ranges is not supported either. We shall probably focus on implementing the axis dropping and pinning first for the rest of the variation tables, as that appear to be a relatively easier problem than limiting ranges, and one that guarantees some size reduction.

Feel free to chime in with suggestions or comments. I’ll keep you updated with the progress.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:20 (17 by maintainers)

github_iconTop GitHub Comments

3reactions
behdadcommented, Mar 20, 2019

I suggest we break this operation down to separate operations that can be chained together. That way the code would be much easier to reason about. I suggest implementing the following:

  1. Dropping an entire axis. This is simplest: any deltaset that has a non-zero peak for the said axis is just dropped completely.

  2. Instantiating an axis to a particular value. The previous operation is a special-case of this one. In this operation, any deltaset that interacts with the axis will get its deltas multiplied by the scalar support of the axis at the desired instantiation point for the deltaset’s tent. If the scalar is 0, drop the deltaset. If it’s 1, leave as is, otherwise multiply the values by it.

  3. Limit min/max of an axis. For each deltaset that participates in the axis, if the deltaset’s tent is fully outside new min/max of axis, drop it. If the tent is fully inside the new range, keep it (just scale the tent min/peak/max to the new normalized axis). If the tent overlaps but also extends beyond new min/max, it becomes interesting. I’ll address that separately in the following comment.

  4. Move the base location. This is harder in the general case and to be done later, separately, if ever.

1reaction
behdadcommented, Mar 20, 2019

Imagine we want to change maximum of ‘axis’ from 1.0 (normalized, always 1.0) to X. Now imagine we have a deltaset with min/peak/max of A<B<C such that A<=X<C. Then do the following:

Divide A,B,C by X to get new normalized values. We now expect that A<=1.0<C. Now, two cases:

  • if the peak falls outside: Ie. 1.0<B. Then scale deltaset by (1-A)/(B-A) and then set B and C to 1.0.

  • if the peak falls inside: If C <= 2.0, keep everything. The format allows for encoding coordinate values in the [-2,+2) range. +2 is not supported but we can store +1.9999999 instead of it. So, just keep the tent as is, extending beyond the axis maximum.

  • if the peak falls inside and C > 2, we need to chop the tent overlap shape into two deltas, because the shape of a triangle with part of one side cut off cannot be represented as a triangle itself. It can be represented as sum of two triangles. This increases font file but is doable.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Source code for fontTools.varLib.instancer
Partially instantiate a variable font. The module exports an `instantiateVariableFont` function and CLI that allow to create full instances (i.e. static ...
Read more >
CJ Dunn on Twitter: "The Slice app provides a handy UI for some ...
You can: – create static instances from a VF – drop selected axes – limit ... [varLib.mutator] Support partial VF instances · Issue...
Read more >
fontTools.varLib.merger.MutatorMerger Example - Program Talk
2 Examples 7 · axisLimits · # · Support partial instancing of JSTF and BASE tables · varfont or varfont · Version ·...
Read more >
NEWS.rst - platform/external/fonttools - Git at Google
[varLib.instancer] Fixed ``TypeError`` exception when instantiating a VF with ... when generating instance via ``varLib.mutator`` (#1614).
Read more >
fonttools Changelog - pyup.io
[TTVarGlyphSet] Support drawing glyph instances from CFF2 variable glyph ... [varLib.instancer] Fixed ``TypeError`` exception when instantiating a VF with
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found