1####################################################### 2designspaceLib: Read, write, and edit designspace files 3####################################################### 4 5Implements support for reading and manipulating ``designspace`` files. 6Allows the users to define axes, rules, sources, variable fonts and instances, 7and their STAT information. 8 9.. toctree:: 10 :maxdepth: 1 11 12 python 13 xml 14 scripting 15 16 17Notes 18===== 19 20Paths and filenames 21------------------- 22 23A designspace file needs to store many references to UFO files. 24 25- designspace files can be part of versioning systems and appear on 26 different computers. This means it is not possible to store absolute 27 paths. 28- So, all paths are relative to the designspace document path. 29- Using relative paths allows designspace files and UFO files to be 30 **near** each other, and that they can be **found** without enforcing 31 one particular structure. 32- The **filename** attribute in the ``SourceDescriptor`` and 33 ``InstanceDescriptor`` classes stores the preferred relative path. 34- The **path** attribute in these objects stores the absolute path. It 35 is calculated from the document path and the relative path in the 36 filename attribute when the object is created. 37- Only the **filename** attribute is written to file. 38- Both **filename** and **path** must use forward slashes (``/``) as 39 path separators, even on Windows. 40 41Right before we save we need to identify and respond to the following 42situations: 43 44In each descriptor, we have to do the right thing for the filename 45attribute. Before writing to file, the ``documentObject.updatePaths()`` 46method prepares the paths as follows: 47 48**Case 1** 49 50:: 51 52 descriptor.filename == None 53 descriptor.path == None 54 55**Action** 56 57- write as is, descriptors will not have a filename attr. Useless, but 58 no reason to interfere. 59 60**Case 2** 61 62:: 63 64 descriptor.filename == "../something" 65 descriptor.path == None 66 67**Action** 68 69- write as is. The filename attr should not be touched. 70 71**Case 3** 72 73:: 74 75 descriptor.filename == None 76 descriptor.path == "~/absolute/path/there" 77 78**Action** 79 80- calculate the relative path for filename. We're not overwriting some 81 other value for filename, it should be fine. 82 83**Case 4** 84 85:: 86 87 descriptor.filename == '../somewhere' 88 descriptor.path == "~/absolute/path/there" 89 90**Action** 91 92- There is a conflict between the given filename, and the path. The 93 difference could have happened for any number of reasons. Assuming 94 the values were not in conflict when the object was created, either 95 could have changed. We can't guess. 96- Assume the path attribute is more up to date. Calculate a new value 97 for filename based on the path and the document path. 98 99Recommendation for editors 100-------------------------- 101 102- If you want to explicitly set the **filename** attribute, leave the 103 path attribute empty. 104- If you want to explicitly set the **path** attribute, leave the 105 filename attribute empty. It will be recalculated. 106- Use ``documentObject.updateFilenameFromPath()`` to explicitly set the 107 **filename** attributes for all instance and source descriptors. 108 109 110Common Lib Key Registry 111======================= 112 113public.skipExportGlyphs 114----------------------- 115 116This lib key works the same as the UFO lib key with the same name. The 117difference is that applications using a Designspace as the corner stone of the 118font compilation process should use the lib key in that Designspace instead of 119any of the UFOs. If the lib key is empty or not present in the Designspace, all 120glyphs should be exported, regardless of what the same lib key in any of the 121UFOs says. 122 123public.fontInfo 124----------------------- 125 126This lib key, when included in the ``<lib>`` element inside an ``<instance>`` 127or ``<variable-font>`` tag, or the ``<lib>`` element at the root of a 128designspace document, allows for direct manipulation of font info data in 129instances and variable fonts. The lib value must follow the 130`UFO3 fontinfo.plist specification <https://unifiedfontobject.org/versions/ufo3/fontinfo.plist/>`_, 131and should functionally appear to be a property list dictionary with the same 132structure as the ``fontinfo.plist`` file in a UFO. 133 134All font info items in the UFO fontinfo.plist specification should be able to 135be defined in the ``public.fontInfo`` lib. Checking validity of the data using 136``fontTools.ufoLib.validators`` is recommended but not required. 137 138All font info items for a variable font or an instance must be inherited using 139the following order, in order of descending priority: 140 141#. The ``public.fontInfo`` key in the ``<lib>`` element of the ``<variable-font>`` 142 or ``<instance>`` elements. 143#. XML attributes for names (i.e. ``familyname``, ``stylename``, etc.), if the 144 target is an ``<instance>`` element. 145#. The ``public.fontInfo`` key found in the ``<lib>`` element of the designspace 146 document's root. 147#. The ``fontinfo.plist`` in the UFO source at the origin of the interpolation 148 space. 149 150Absence of a font info key from the value of a ``public.fontInfo`` lib does 151**not** mean a that piece of font info should be interpreted as being undefined. 152A tool generating the variable font or instance should recursively continue on 153to the next level of the inheritence order and apply the value found there, if 154any. If the tool makes it to the end of the inheritence order without finding a 155valid value for a given font info key, it should then be considered undefined. 156In the case of any conflicting values for a font info key, the value highest in 157the inheritance order must be chosen over the others. 158 159Implementation and differences 160============================== 161 162The designspace format has gone through considerable development. 163 164 - the format was originally written for MutatorMath. 165 - the format is now also used in fontTools.varLib. 166 - not all values are be required by all implementations. 167 168varLib vs. MutatorMath 169---------------------- 170 171There are some differences between the way MutatorMath and fontTools.varLib handle designspaces. 172 173 - varLib does not support anisotropic interpolations. 174 - MutatorMath will extrapolate over the boundaries of 175 the axes. varLib can not (at the moment). 176 - varLib requires much less data to define an instance than 177 MutatorMath. 178 - The goals of varLib and MutatorMath are different, so not all 179 attributes are always needed. 180 181 182Rules and generating static UFO instances 183----------------------------------------- 184 185When making instances as UFOs from a designspace with rules, it can 186be useful to evaluate the rules so that the characterset of the UFO 187reflects, as much as possible, the state of a variable font when seen 188at the same location. This can be done by some swapping and renaming of 189glyphs. 190 191While useful for proofing or development work, it should be noted that 192swapping and renaming leaves the UFOs with glyphnames that are no longer 193descriptive. For instance, after a swap ``dollar.bar`` could contain a shape 194without a bar. Also, when the swapped glyphs are part of other GSUB variations 195it can become complex very quickly. So proceed with caution. 196 197 - Assuming ``rulesProcessingLast = True``: 198 - We need to swap the glyphs so that the original shape is still available. 199 For instance, if a rule swaps ``a`` for ``a.alt``, a glyph 200 that references ``a`` in a component would then show the new ``a.alt``. 201 - But that can lead to unexpected results, the two glyphs may have different 202 widths or height. So, glyphs that are not specifically referenced in a rule 203 **should not change appearance**. That means that the implementation that swaps 204 ``a`` and ``a.alt`` also swap all components that reference these 205 glyphs in order to preserve their appearance. 206 - The swap function also needs to take care of swapping the names in 207 kerning data and any GPOS code. 208 209Version history 210=============== 211 212Version 5.1 213----------- 214 215The format was extended to support arbitrary mapping between input and output 216designspace locations. The ``<axes>`` elements now can have a ``<mappings>`` 217element that specifies such mappings, which when present carries data that is 218used to compile to an ``avar`` version 2 table. 219 220Version 5.0 221----------- 222 223The format was extended to describe the entire design space of a reasonably 224regular font family in one file, with global data about the family to reduce 225repetition in sub-sections. "Reasonably regular" means that the sources and 226instances across the previously multiple Designspace files are positioned on a 227grid and derive their metadata (like style name) in a way that's compatible with 228the STAT model, based on their axis positions. Axis mappings must be the same 229across the entire space. 230 2311. Each axis can have labels attached to stops within the axis range, analogous to the 232 `OpenType STAT <https://docs.microsoft.com/en-us/typography/opentype/spec/stat>`_ 233 table. Free-standing labels for locations are also allowed. The data is intended 234 to be compiled into a ``STAT`` table. 2352. The axes can be discrete, to say that they do not interpolate, like a distinctly 236 constructed upright and italic variant of a family. 2373. The data can be used to derive style and PostScript names for instances. 2384. A new ``variable-fonts`` element can subdivide the Designspace into multiple subsets that 239 mix and match the globally available axes. It is possible for these sub-spaces to have 240 a different default location from the global default location. It is required if the 241 Designspace contains a discrete axis and you want to produce a variable font. 242 243What is currently not supported is e.g. 244 2451. A setup where different sources sit at the same logical location in the design space, 246 think "MyFont Regular" and "MyFont SmallCaps Regular". (this situation could be 247 encoded by adding a "SmallCaps" discrete axis, if that makes sense). 2482. Anisotropic locations for axis labels. 249 250Older versions 251-------------- 252 253- In some implementations that preceed Variable Fonts, the `copyInfo` 254 flag in a source indicated the source was to be treated as the default. 255 This is no longer compatible with the assumption that the default font 256 is located on the default value of each axis. 257- Older implementations did not require axis records to be present in 258 the designspace file. The axis extremes for instance were generated 259 from the locations used in the sources. This is no longer possible. 260 261