[WIP] [designspaceLib] designspace docs edits (#1750)
Various changes in the designspaceLib readme.rst - added docs for DesignSpaceDocument object, methods and attributes - removed comments on validation, localisation and generating UFO instances. - added note that axis minimum, default and maximum are in userspace coordinates. - added clarification to map input (userpace!) / output (designspace!) values. - added note that sourceDescriptor location is in designspace coordinates. - moved comment on rule subs to rule descriptor object. - added proposed "processing" flag to rules element - move note on sub element - implementation differences - varlib vs. mutatormath - older versions - rules and generating static ufo instances - Updated the description of the `copyInfo` flag of the sourceDescriptor. - Change the example import. - Remove additional mention of copyInfo.
This commit is contained in:
parent
9df78f303b
commit
b8fafdd259
@ -2,23 +2,22 @@
|
||||
DesignSpaceDocument Specification
|
||||
#################################
|
||||
|
||||
An object to read, write and edit interpolation systems for typefaces.
|
||||
An object to read, write and edit interpolation systems for typefaces. Define sources, axes, rules and instances.
|
||||
|
||||
- the format was originally written for MutatorMath.
|
||||
- the format is now also used in fontTools.varlib.
|
||||
- Define sources, axes and instances.
|
||||
- Not all values might be required by all applications.
|
||||
- `The Python API of the objects <#python-api>`_
|
||||
- `The document XML structure <#document-xml-structure>`_
|
||||
|
||||
A couple of differences between things that use designspaces:
|
||||
|
||||
- Varlib does not support anisotropic interpolations.
|
||||
- MutatorMath and Superpolator will extrapolate over the boundaries of
|
||||
the axes. Varlib can not (at the moment).
|
||||
- Varlib requires much less data to define an instance than
|
||||
MutatorMath.
|
||||
- The goals of Varlib and MutatorMath are different, so not all
|
||||
attributes are always needed.
|
||||
- Need to expand the description of FDK use of designspace files.
|
||||
**********
|
||||
Python API
|
||||
**********
|
||||
|
||||
|
||||
|
||||
.. _designspacedocument-object:
|
||||
|
||||
DesignSpaceDocument object
|
||||
==========================
|
||||
|
||||
The DesignSpaceDocument object can read and write ``.designspace`` data.
|
||||
It imports the axes, sources and instances to very basic **descriptor**
|
||||
@ -28,87 +27,71 @@ adding them to the document. This makes it easy to integrate this object
|
||||
in different contexts.
|
||||
|
||||
The **DesignSpaceDocument** object can be subclassed to work with
|
||||
different objects, as long as they have the same attributes.
|
||||
different objects, as long as they have the same attributes. Reader and
|
||||
Writer objects can be subclassed as well.
|
||||
|
||||
.. example-1:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from designSpaceDocument import DesignSpaceDocument
|
||||
from fontTools.designspaceLib import DesignSpaceDocument
|
||||
doc = DesignSpaceDocument()
|
||||
doc.read("some/path/to/my.designspace")
|
||||
doc.axes
|
||||
doc.sources
|
||||
doc.instances
|
||||
|
||||
**********
|
||||
Validation
|
||||
**********
|
||||
Attributes
|
||||
----------
|
||||
|
||||
Some validation is done when reading.
|
||||
- ``axes``: list of axisDescriptors
|
||||
- ``sources``: list of sourceDescriptors
|
||||
- ``instances``: list of instanceDescriptors
|
||||
- ``rules``: list if ruleDescriptors
|
||||
- ``readerClass``: class of the reader object
|
||||
- ``writerClass``: class of the writer object
|
||||
- ``lib``: dict for user defined, custom data that needs to be stored
|
||||
in the designspace. Use reverse-DNS notation to identify your own data.
|
||||
Respect the data stored by others.
|
||||
- ``rulesProcessingLast``: This flag indicates whether the substitution rules should be applied before or after other glyph substitution features. False: before, True: after.
|
||||
|
||||
Axes
|
||||
====
|
||||
Methods
|
||||
-------
|
||||
|
||||
- If the ``axes`` element is available in the document then all
|
||||
locations will check their dimensions against the defined axes. If a
|
||||
location uses an axis that is not defined it will be ignored.
|
||||
- If there are no ``axes`` in the document, locations will accept all
|
||||
axis names, so that we can..
|
||||
- Use ``doc.checkAxes()`` to reconstruct axes definitions based on the
|
||||
``source.location`` values. If you save the document the axes will be
|
||||
there.
|
||||
- ``read(path)``: read a designspace file from ``path``
|
||||
- ``write(path)``: write this designspace to ``path``
|
||||
- ``addSource(aSourceDescriptor)``: add this sourceDescriptor to
|
||||
``doc.sources``.
|
||||
- ``addInstance(anInstanceDescriptor)``: add this instanceDescriptor
|
||||
to ``doc.instances``.
|
||||
- ``addAxis(anAxisDescriptor)``: add this instanceDescriptor to ``doc.axes``.
|
||||
- ``newDefaultLocation()``: returns a dict with the default location
|
||||
in designspace coordinates.
|
||||
- ``updateFilenameFromPath(masters=True, instances=True, force=False)``:
|
||||
set a descriptor filename attr from the path and this document.
|
||||
- ``newAxisDescriptor()``: return a new axisDescriptor object.
|
||||
- ``newSourceDescriptor()``: return a new sourceDescriptor object.
|
||||
- ``newInstanceDescriptor()``: return a new instanceDescriptor object.
|
||||
- ``getAxisOrder()``: return a list of axisnames
|
||||
- ``findDefault()``: return the sourceDescriptor that is on the default
|
||||
location. Returns None if there isn't one.
|
||||
- ``normalizeLocation(aLocation)``: return a dict with normalized axis values.
|
||||
- ``normalize()``: normalize the geometry of this designspace: scale all the
|
||||
locations of all masters and instances to the ``-1 - 0 - 1`` value.
|
||||
- ``loadSourceFonts()``: Ensure SourceDescriptor.font attributes are loaded,
|
||||
and return list of fonts.
|
||||
- ``tostring(encoding=None)``: Returns the designspace as a string. Default
|
||||
encoding `utf-8`.
|
||||
|
||||
Default font
|
||||
============
|
||||
Class Methods
|
||||
-------------
|
||||
- ``fromfile(path)``
|
||||
- ``fromstring(string)``
|
||||
|
||||
- The source with the ``copyInfo`` flag indicates this is the default
|
||||
font.
|
||||
- In mutatorMath the default font is selected automatically. A warning
|
||||
is printed if the mutatorMath default selection differs from the one
|
||||
set by ``copyInfo``. But the ``copyInfo`` source will be used.
|
||||
- If no source has a ``copyInfo`` flag, mutatorMath will be used to
|
||||
select one. This source gets its ``copyInfo`` flag set. If you save
|
||||
the document this flag will be set.
|
||||
- Use ``doc.checkDefault()`` to set the default font.
|
||||
|
||||
************
|
||||
Localisation
|
||||
************
|
||||
|
||||
Some of the descriptors support localised names. The names are stored in
|
||||
dictionaries using the language code as key. That means that there are
|
||||
now two places to store names: the old attribute and the new localised
|
||||
dictionary, ``obj.stylename`` and ``obj.localisedStyleName['en']``.
|
||||
|
||||
*****
|
||||
Rules
|
||||
*****
|
||||
|
||||
Rules describe designspace areas in which one glyph should be replaced by another.
|
||||
A rule has a name and a number of conditionsets. The rule also contains a list of
|
||||
glyphname pairs: the glyphs that need to be substituted. For a rule to be triggered
|
||||
**only one** of the conditionsets needs to be true, ``OR``. Within a conditionset
|
||||
**all** conditions need to be true, ``AND``.
|
||||
|
||||
The ``sub`` element contains a pair of glyphnames. The ``name`` attribute is the glyph that should be visible when the rule evaluates to **False**. The ``with`` attribute is the glyph that should be visible when the rule evaluates to **True**.
|
||||
|
||||
UFO instances
|
||||
=============
|
||||
|
||||
- When making instances as UFOs however, we need to swap the glyphs so
|
||||
that the original shape is still available. For instance, if a rule
|
||||
swaps ``a`` for ``a.alt``, but a glyph that references ``a`` in a
|
||||
component would then show the new ``a.alt``.
|
||||
- But that can lead to unexpected results. So, if there are no rules
|
||||
for ``adieresis`` (assuming it references ``a``) then that glyph
|
||||
**should not change appearance**. That means that when the rule swaps
|
||||
``a`` and ``a.alt`` it also swaps all components that reference these
|
||||
glyphs so they keep their appearance.
|
||||
- The swap function also needs to take care of swapping the names in
|
||||
kerning data.
|
||||
|
||||
**********
|
||||
Python API
|
||||
**********
|
||||
|
||||
SourceDescriptor object
|
||||
=======================
|
||||
@ -138,8 +121,7 @@ Attributes
|
||||
- ``copyLib``: bool. Indicates if the contents of the font.lib need to
|
||||
be copied to the instances. MutatorMath.
|
||||
- ``copyInfo`` bool. Indicates if the non-interpolating font.info needs
|
||||
to be copied to the instances. Also indicates this source is expected
|
||||
to be the default font. MutatorMath + Varlib
|
||||
to be copied to the instances. MutatorMath
|
||||
- ``copyGroups`` bool. Indicates if the groups need to be copied to the
|
||||
instances. MutatorMath.
|
||||
- ``copyFeatures`` bool. Indicates if the feature text needs to be
|
||||
@ -182,6 +164,7 @@ InstanceDescriptor object
|
||||
|
||||
.. attributes-1:
|
||||
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
||||
@ -284,10 +267,9 @@ AxisDescriptor object
|
||||
- ``default``: number. The default value for this axis, i.e. when a new
|
||||
location is created, this is the value this axis will get in user
|
||||
space. MutatorMath + Varlib.
|
||||
- ``map``: list of input / output values that can describe a warp of user space
|
||||
to design space coordinates. If no map values are present, it is assumed user
|
||||
space is the same as design space, as in [(minimum, minimum), (maximum, maximum)].
|
||||
Varlib.
|
||||
- ``map``: list of input / output values that can describe a warp
|
||||
of user space to design space coordinates. If no map values are present, it is assumed user space is the same as design space, as
|
||||
in [(minimum, minimum), (maximum, maximum)]. Varlib.
|
||||
|
||||
.. code:: python
|
||||
|
||||
@ -312,6 +294,16 @@ RuleDescriptor object
|
||||
- ``subs``: list of substitutions
|
||||
- Each substitution is stored as tuples of glyphnames, e.g. ("a", "a.alt").
|
||||
|
||||
Evaluating rules
|
||||
----------------
|
||||
|
||||
- ``evaluateRule(rule, location)``: Return True if any of the rule's conditionsets
|
||||
matches the given location.
|
||||
- ``evaluateConditions(conditions, location)``: Return True if all the conditions
|
||||
matches the given location.
|
||||
- ``processRules(rules, location, glyphNames)``: Apply all the rules to the list
|
||||
of glyphNames. Return a new list of glyphNames with substitutions applied.
|
||||
|
||||
.. code:: python
|
||||
|
||||
r1 = RuleDescriptor()
|
||||
@ -320,6 +312,7 @@ RuleDescriptor object
|
||||
r1.conditionsSets.append([dict(...), dict(...)])
|
||||
r1.subs.append(("a", "a.alt"))
|
||||
|
||||
|
||||
.. _subclassing-descriptors:
|
||||
|
||||
Subclassing descriptors
|
||||
@ -400,9 +393,9 @@ Attributes
|
||||
location elements.
|
||||
- ``tag``: required, string, 4 letters. Some axis tags are registered
|
||||
in the OpenType Specification.
|
||||
- ``minimum``: required, number. The minimum value for this axis.
|
||||
- ``maximum``: required, number. The maximum value for this axis.
|
||||
- ``default``: required, number. The default value for this axis.
|
||||
- ``minimum``: required, number. The minimum value for this axis, in user space coordinates.
|
||||
- ``maximum``: required, number. The maximum value for this axis, in user space coordinates.
|
||||
- ``default``: required, number. The default value for this axis, in user space coordinates.
|
||||
- ``hidden``: optional, 0 or 1. Records whether this axis needs to be
|
||||
hidden in interfaces.
|
||||
|
||||
@ -433,7 +426,7 @@ Value
|
||||
|
||||
- The natural language name of this axis.
|
||||
|
||||
.. example-1:
|
||||
.. example-2:
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -448,12 +441,12 @@ Example
|
||||
1.2 map element
|
||||
===============
|
||||
|
||||
- Defines a single node in a series of input value / output value
|
||||
pairs.
|
||||
- Defines a single node in a series of input value (user space coordinate)
|
||||
to output value (designspace coordinate) pairs.
|
||||
- Together these values transform the designspace.
|
||||
- Child of ``axis`` element.
|
||||
|
||||
.. example-2:
|
||||
.. example-3:
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -507,7 +500,7 @@ Attributes
|
||||
- ``yvalue``: optional, number. Separate value for anisotropic
|
||||
interpolations.
|
||||
|
||||
.. example-3:
|
||||
.. example-4:
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -524,8 +517,9 @@ Example
|
||||
3. source element
|
||||
=================
|
||||
|
||||
- Defines a single font that contributes to the designspace.
|
||||
- Defines a single font or layer that contributes to the designspace.
|
||||
- Child element of ``sources``
|
||||
- Location in designspace coordinates.
|
||||
|
||||
.. attributes-5:
|
||||
|
||||
@ -584,9 +578,7 @@ There are two meanings for the ``lib`` element:
|
||||
- Child element of ``source``
|
||||
- Defines if the instances can inherit the non-interpolating font info
|
||||
from this source.
|
||||
- MutatorMath + Varlib
|
||||
- NOTE: **This presence of this element indicates this source is to be
|
||||
the default font.**
|
||||
- MutatorMath
|
||||
|
||||
.. 33-features-element:
|
||||
|
||||
@ -638,7 +630,7 @@ Attributes
|
||||
include the kerning of this source in the calculation.
|
||||
- MutatorMath only
|
||||
|
||||
.. example-4:
|
||||
.. example-5:
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -669,6 +661,7 @@ Example
|
||||
- MutatorMath uses the ``glyphs`` element to describe how certain
|
||||
glyphs need different masters, mainly to describe the effects of
|
||||
conditional rules in Superpolator.
|
||||
- Location in designspace coordinates.
|
||||
|
||||
.. attributes-8:
|
||||
|
||||
@ -774,7 +767,7 @@ with an ``xml:lang`` attribute:
|
||||
- stylemapstylename
|
||||
- stylemapfamilyname
|
||||
|
||||
.. example-5:
|
||||
.. example-6:
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -798,7 +791,7 @@ Attributes
|
||||
- ``source``: the identifier name of the source this master glyph needs
|
||||
to be loaded from
|
||||
|
||||
.. example-6:
|
||||
.. example-7:
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -846,6 +839,19 @@ Example
|
||||
- Container for ``rule`` elements
|
||||
- The rules are evaluated in this order.
|
||||
|
||||
Rules describe designspace areas in which one glyph should be replaced by another.
|
||||
A rule has a name and a number of conditionsets. The rule also contains a list of
|
||||
glyphname pairs: the glyphs that need to be substituted. For a rule to be triggered
|
||||
**only one** of the conditionsets needs to be true, ``OR``. Within a conditionset
|
||||
**all** conditions need to be true, ``AND``.
|
||||
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
||||
- ``processing``: flag, optional. Valid values are [``first``, ``last``]. This flag indicates whether the substitution rules should be applied before or after other glyph substitution features.
|
||||
- If no ``processing`` attribute is given, interpret as ``first``.
|
||||
|
||||
.. 51-rule-element:
|
||||
|
||||
5.1 rule element
|
||||
@ -853,8 +859,8 @@ Example
|
||||
|
||||
- Defines a named rule.
|
||||
- Each ``rule`` element contains one or more ``conditionset`` elements.
|
||||
- Only one ``conditionset`` needs to be true to trigger the rule.
|
||||
- All conditions in a ``conditionset`` must be true to make the ``conditionset`` true.
|
||||
- **Only one** ``conditionset`` needs to be true to trigger the rule.
|
||||
- **All** conditions in a ``conditionset`` must be true to make the ``conditionset`` true.
|
||||
- For backwards compatibility a ``rule`` can contain ``condition`` elements outside of a conditionset. These are then understood to be part of a single, implied, ``conditionset``. Note: these conditions should be written wrapped in a conditionset.
|
||||
- A rule element needs to contain one or more ``sub`` elements in order to be compiled to a variable font.
|
||||
- Rules without sub elements should be ignored when compiling a font.
|
||||
@ -881,9 +887,10 @@ Attributes
|
||||
=======================
|
||||
|
||||
- Child element of ``conditionset``
|
||||
- Between the ``minimum`` and ``maximum`` this rule is ``True``.
|
||||
- If ``minimum`` is not available, assume it is ``axis.minimum``.
|
||||
- If ``maximum`` is not available, assume it is ``axis.maximum``.
|
||||
- Between the ``minimum`` and ``maximum`` this condition is ``True``.
|
||||
- ``minimum`` and ``maximum`` are in designspace coordinates.
|
||||
- If ``minimum`` is not available, assume it is ``axis.minimum``, mapped to designspace coordinates.
|
||||
- If ``maximum`` is not available, assume it is ``axis.maximum``, mapped to designspace coordinates.
|
||||
- The condition must contain at least a minimum or maximum or both.
|
||||
|
||||
.. attributes-12:
|
||||
@ -893,8 +900,8 @@ Attributes
|
||||
|
||||
- ``name``: string, required. Must match one of the defined ``axis``
|
||||
name attributes.
|
||||
- ``minimum``: number, required*. The low value.
|
||||
- ``maximum``: number, required*. The high value.
|
||||
- ``minimum``: number, required*. The low value, in designspace coordinates.
|
||||
- ``maximum``: number, required*. The high value, in designspace coordinates.
|
||||
|
||||
.. 513-sub-element:
|
||||
|
||||
@ -903,6 +910,9 @@ Attributes
|
||||
|
||||
- Child element of ``rule``.
|
||||
- Defines which glyph to replace when the rule evaluates to **True**.
|
||||
- The ``sub`` element contains a pair of glyphnames. The ``name`` attribute is the glyph that should be visible when the rule evaluates to **False**. The ``with`` attribute is the glyph that should be visible when the rule evaluates to **True**.
|
||||
|
||||
Axis values in Conditions are in designspace coordinates.
|
||||
|
||||
.. attributes-13:
|
||||
|
||||
@ -914,7 +924,7 @@ Attributes
|
||||
- ``with``: string, required. The name of the glyph it is replaced
|
||||
with.
|
||||
|
||||
.. example-7:
|
||||
.. example-8:
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -924,7 +934,7 @@ contained in a conditionset.
|
||||
|
||||
.. code:: xml
|
||||
|
||||
<rules>
|
||||
<rules processing="last">
|
||||
<rule name="named.rule.1">
|
||||
<condition minimum="250" maximum="750" name="weight" />
|
||||
<condition minimum="50" maximum="100" name="width" />
|
||||
@ -1059,9 +1069,75 @@ any of the UFOs. If the lib key is empty or not present in the Designspace, all
|
||||
glyphs should be exported, regardless of what the same lib key in any of the
|
||||
UFOs says.
|
||||
|
||||
.. 8-this-document:
|
||||
.. 8-implementation-and-differences:
|
||||
|
||||
8 This document
|
||||
|
||||
8 Implementation and differences
|
||||
================================
|
||||
|
||||
The designspace format has gone through considerable development.
|
||||
|
||||
- the format was originally written for MutatorMath.
|
||||
- the format is now also used in fontTools.varlib.
|
||||
- not all values are be required by all implementations.
|
||||
|
||||
8.1 Varlib vs. MutatorMath
|
||||
--------------------------
|
||||
|
||||
There are some differences between the way MutatorMath and fontTools.varlib handle designspaces.
|
||||
|
||||
- Varlib does not support anisotropic interpolations.
|
||||
- MutatorMath will extrapolate over the boundaries of
|
||||
the axes. Varlib can not (at the moment).
|
||||
- Varlib requires much less data to define an instance than
|
||||
MutatorMath.
|
||||
- The goals of Varlib and MutatorMath are different, so not all
|
||||
attributes are always needed.
|
||||
|
||||
8.2 Older versions
|
||||
------------------
|
||||
|
||||
- In some implementations that preceed Variable Fonts, the `copyInfo`
|
||||
flag in a source indicated the source was to be treated as the default.
|
||||
This is no longer compatible with the assumption that the default font
|
||||
is located on the default value of each axis.
|
||||
- Older implementations did not require axis records to be present in
|
||||
the designspace file. The axis extremes for instance were generated
|
||||
from the locations used in the sources. This is no longer possible.
|
||||
|
||||
8.3 Rules and generating static UFO instances
|
||||
---------------------------------------------
|
||||
|
||||
When making instances as UFOs from a designspace with rules, it can
|
||||
be useful to evaluate the rules so that the characterset of the ufo
|
||||
reflects, as much as possible, the state of a variable font when seen
|
||||
at the same location. This can be done by some swapping and renaming of
|
||||
glyphs.
|
||||
|
||||
While useful for proofing or development work, it should be noted that
|
||||
swapping and renaming leaves the UFOs with glyphnames that are no longer
|
||||
descriptive. For instance, after a swap `dollar.bar` could contain a shape
|
||||
without a bar. Also, when the swapped glyphs are part of other GSUB variations
|
||||
it can become complex very quickly. So proceed with caution.
|
||||
|
||||
- Assuming `rulesProcessingLast = True`:
|
||||
- We need to swap the glyphs so that the original shape is still available.
|
||||
For instance, if a rule swaps ``a`` for ``a.alt``, a glyph
|
||||
that references ``a`` in a component would then show the new ``a.alt``.
|
||||
- But that can lead to unexpected results, the two glyphs may have different
|
||||
widths or height. So, glyphs that are not specifically referenced in a rule
|
||||
**should not change appearance**. That means that the implementation that swaps
|
||||
``a`` and ``a.alt`` also swap all components that reference these
|
||||
glyphs in order to preserve their appearance.
|
||||
- The swap function also needs to take care of swapping the names in
|
||||
kerning data and any GPOS code.
|
||||
|
||||
|
||||
.. 9-this-document
|
||||
|
||||
9 This document
|
||||
===============
|
||||
|
||||
- The package is rather new and changes are to be expected.
|
||||
- Changes are to be expected.
|
||||
|
||||
|
||||
|
@ -182,7 +182,7 @@ def evaluateConditions(conditions, location):
|
||||
|
||||
|
||||
def processRules(rules, location, glyphNames):
|
||||
""" Apply these rules at this location to these glyphnames.minimum
|
||||
""" Apply these rules at this location to these glyphnames
|
||||
- rule order matters
|
||||
"""
|
||||
newNames = []
|
||||
|
Loading…
x
Reference in New Issue
Block a user