0
# UFO Tools
1
2
Specialized tools for font interpolation using UFO (Unified Font Object) data with designspace document processing. These tools provide font-specific functionality built on top of the core MutatorMath objects.
3
4
## Capabilities
5
6
### Designspace Builder
7
8
Convenience function for processing designspace documents and generating UFO instances.
9
10
```python { .api }
11
def build(documentPath, outputUFOFormatVersion=2, roundGeometry=True,
12
verbose=True, logPath=None, progressFunc=None) -> list:
13
"""
14
Simple builder for UFO designspaces.
15
16
Parameters:
17
- documentPath: str, filepath to .designspace document or directory
18
- outputUFOFormatVersion: int, UFO format version for output (default 2)
19
- roundGeometry: bool, whether to round geometry coordinates (default True)
20
- verbose: bool, enable verbose output (default True)
21
- logPath: str, optional filepath to log file
22
- progressFunc: callable, optional progress callback function
23
24
Returns:
25
- list: Processing results from designspace execution
26
"""
27
```
28
29
#### Progress Callback Function
30
31
```python { .api }
32
def tokenProgressFunc(state="update", action=None, text=None, tick=0):
33
"""
34
Token progress callback function for designspace processing.
35
36
Parameters:
37
- state: str, processing state ("update", "reading sources", "wrapping up")
38
- action: str, action type ("stop", "start")
39
- text: str, additional information (e.g., UFO name)
40
- tick: float, progress value between 0 and 1
41
"""
42
```
43
44
#### Build Usage Examples
45
46
```python
47
from mutatorMath.ufo import build
48
49
# Process single designspace document
50
results = build("MyFont.designspace",
51
outputUFOFormatVersion=3,
52
verbose=True)
53
54
# Process all designspace files in directory
55
results = build("/path/to/designspaces/",
56
roundGeometry=False,
57
logPath="build.log")
58
59
# With custom progress callback
60
def my_progress(state, action, text, tick):
61
print(f"Progress: {state} - {text} ({tick*100:.1f}%)")
62
63
results = build("MyFont.designspace", progressFunc=my_progress)
64
```
65
66
### DesignSpace Document Writer
67
68
Writer for creating designspace XML documents that describe interpolation spaces and masters.
69
70
```python { .api }
71
class DesignSpaceDocumentWriter(object):
72
"""
73
Writer for designspace XML documents.
74
"""
75
def __init__(self, path, toolVersion=3, verbose=False):
76
"""
77
Create designspace document writer.
78
79
Parameters:
80
- path: str, output path for designspace document
81
- toolVersion: int, tool version for format compatibility
82
- verbose: bool, enable verbose logging
83
"""
84
85
def save(self, pretty=True):
86
"""
87
Save the designspace XML document.
88
89
Parameters:
90
- pretty: bool, format XML with indentation
91
"""
92
93
def addAxis(self, tag, name, minimum, maximum, default, warpMap=None):
94
"""
95
Add axis definition to designspace.
96
97
Parameters:
98
- tag: str, 4-character axis tag
99
- name: str, axis name
100
- minimum: float, minimum axis value
101
- maximum: float, maximum axis value
102
- default: float, default axis value
103
- warpMap: list, optional warp map for non-linear axis
104
"""
105
106
def addSource(self, fileName, location, copyLib=False, copyGroups=False,
107
copyInfo=False, muteKerning=False, muteInfo=False,
108
muteFeatures=True, name=None, familyName=None, styleName=None):
109
"""
110
Add source/master to designspace.
111
112
Parameters:
113
- fileName: str, path to UFO source file
114
- location: Location object with axis coordinates
115
- copyLib: bool, copy lib data from source
116
- copyGroups: bool, copy groups from source
117
- copyInfo: bool, copy info from source
118
- muteKerning: bool, mute kerning for this source
119
- muteInfo: bool, mute info for this source
120
- muteFeatures: bool, mute features for this source
121
- name: str, optional source name
122
- familyName: str, optional family name
123
- styleName: str, optional style name
124
"""
125
126
def startInstance(self, name=None, familyName=None, styleName=None,
127
fileName=None, postScriptFontName=None, styleMapFamilyName=None,
128
styleMapStyleName=None):
129
"""
130
Start defining an instance in the designspace.
131
132
Parameters:
133
- name: str, optional instance name
134
- familyName: str, optional family name
135
- styleName: str, optional style name
136
- fileName: str, optional output UFO path
137
- postScriptFontName: str, optional PostScript font name
138
- styleMapFamilyName: str, optional style map family name
139
- styleMapStyleName: str, optional style map style name
140
"""
141
142
def endInstance(self):
143
"""End current instance definition."""
144
145
def writeGlyph(self, glyphName, location=None, unicodes=None, masters=None):
146
"""
147
Write glyph definition to current instance.
148
149
Parameters:
150
- glyphName: str, glyph name
151
- location: Location object, optional location for glyph
152
- unicodes: list, optional unicode values
153
- masters: list, optional master configurations
154
"""
155
156
def writeInfo(self, location=None, masters=None):
157
"""
158
Write info definition to current instance.
159
160
Parameters:
161
- location: Location object, optional location
162
- masters: list, optional master configurations
163
"""
164
165
def writeKerning(self, location=None, masters=None):
166
"""
167
Write kerning definition to current instance.
168
169
Parameters:
170
- location: Location object, optional location
171
- masters: list, optional master configurations
172
"""
173
174
def writeWarp(self, warpDict):
175
"""
176
Write warp/bending transformations to designspace.
177
178
Parameters:
179
- warpDict: dict, warp transformation definitions
180
"""
181
```
182
183
### DesignSpace Document Reader
184
185
Reader and processor for designspace XML documents that generates UFO instances.
186
187
```python { .api }
188
class DesignSpaceDocumentReader(object):
189
"""
190
Reader and processor for designspace XML documents.
191
"""
192
def __init__(self, path, ufoVersion=2, roundGeometry=True,
193
verbose=True, logPath=None, progressFunc=None):
194
"""
195
Create designspace document reader.
196
197
Parameters:
198
- path: str, path to designspace document
199
- ufoVersion: int, UFO format version for output
200
- roundGeometry: bool, round geometry coordinates
201
- verbose: bool, enable verbose output
202
- logPath: str, optional log file path
203
- progressFunc: callable, optional progress callback
204
"""
205
206
def process(self):
207
"""
208
Process the designspace document and generate instances.
209
Populates self.results with processing outcomes.
210
"""
211
212
@property
213
def results(self) -> list:
214
"""Get processing results after calling process()."""
215
```
216
217
#### DesignSpace Usage Examples
218
219
```python
220
from mutatorMath.ufo.document import DesignSpaceDocumentWriter, DesignSpaceDocumentReader
221
from mutatorMath.objects.location import Location
222
223
# Create designspace document
224
writer = DesignSpaceDocumentWriter("MyFont.designspace")
225
226
# Define weight axis
227
writer.startAxis("weight", 100, 400, 900, "wght")
228
writer.endAxis()
229
230
# Add master sources
231
writer.startSource("Light.ufo", familyName="MyFont", styleName="Light")
232
writer.writeLocation(Location(weight=100))
233
writer.endSource()
234
235
writer.startSource("Bold.ufo", familyName="MyFont", styleName="Bold")
236
writer.writeLocation(Location(weight=900))
237
writer.endSource()
238
239
# Add instances
240
writer.startInstance(familyName="MyFont", styleName="Regular", fileName="Regular.ufo")
241
writer.writeLocation(Location(weight=400))
242
writer.endInstance()
243
244
writer.save()
245
246
# Process designspace to generate instances
247
reader = DesignSpaceDocumentReader("MyFont.designspace",
248
ufoVersion=3,
249
verbose=True)
250
reader.process()
251
print(reader.results)
252
```
253
254
### Instance Writer
255
256
Object for building UFO instances from interpolation data.
257
258
```python { .api }
259
class InstanceWriter(object):
260
"""
261
Simple object to build a UFO instance.
262
Collects interpolation data and generates UFO as efficiently as possible.
263
"""
264
def __init__(self, path, ufoVersion=1, roundGeometry=False,
265
axes=None, verbose=False, logger=None):
266
"""
267
Create instance writer.
268
269
Parameters:
270
- path: str, output path for UFO instance
271
- ufoVersion: int, UFO format version
272
- roundGeometry: bool, round coordinate values
273
- axes: dict, optional axis definitions for bending
274
- verbose: bool, enable verbose output
275
- logger: logging.Logger, optional logger instance
276
"""
277
278
def save(self):
279
"""Save the UFO instance to disk."""
280
281
def writeGlyph(self, glyphName, glyph):
282
"""
283
Write glyph data to instance.
284
285
Parameters:
286
- glyphName: str, glyph name
287
- glyph: glyph object with outline data
288
"""
289
290
def writeInfo(self, info):
291
"""
292
Write font info to instance.
293
294
Parameters:
295
- info: font info object
296
"""
297
298
def writeKerning(self, kerning):
299
"""
300
Write kerning data to instance.
301
302
Parameters:
303
- kerning: kerning data object
304
"""
305
306
def writeLib(self, lib):
307
"""
308
Write lib data to instance.
309
310
Parameters:
311
- lib: lib data dict
312
"""
313
```
314
315
#### Instance Writer Usage Examples
316
317
```python
318
from mutatorMath.ufo.instance import InstanceWriter
319
320
# Create instance writer
321
writer = InstanceWriter("output/Regular.ufo",
322
ufoVersion=3,
323
roundGeometry=True,
324
verbose=True)
325
326
# Write interpolated data (typically done by DesignSpaceDocumentReader)
327
# writer.writeGlyph("A", interpolated_glyph_A)
328
# writer.writeInfo(interpolated_info)
329
# writer.writeKerning(interpolated_kerning)
330
331
# Save UFO to disk
332
writer.save()
333
```
334
335
### Helper Functions
336
337
Utility functions for designspace processing.
338
339
```python { .api }
340
def initializeLogger(proposedLogPath):
341
"""
342
Initialize logging for designspace processing.
343
344
Parameters:
345
- proposedLogPath: str, path for log file
346
"""
347
```