@@ -40,16 +40,17 @@ def build(self):
40
40
self .generatedFiles = set ()
41
41
42
42
self .operator .loadFonts (reload = True )
43
-
44
- self .makeMasterGlyphsCompatible ()
43
+ self . applySkipExportGlyphs ()
44
+ self .makeSourceGlyphsCompatible ()
45
45
self .decomposedMixedGlyphs ()
46
- self .makeMasterKerningCompatible ()
47
- self .makeMasterOnDefaultLocation ()
48
- self .makeLayerMaster ()
46
+ self .makeSourceKerningCompatible ()
47
+ self .makeSourceOnDefaultLocation ()
48
+ self .makeLayerSource ()
49
+ self .makeSourcesAtAxesExtremes ()
49
50
if self .binaryFormat == "ttf" :
50
- self .makeMasterGlyphsQuadractic ()
51
+ self .makeSourceGlyphsQuadractic ()
51
52
elif self .binaryFormat == "otf" :
52
- self .makeMasterExportOptimizeCharstring ()
53
+ self .makeSourceExportOptimizeCharstring ()
53
54
54
55
self .generate ()
55
56
@@ -62,12 +63,71 @@ def build(self):
62
63
else :
63
64
os .remove (path )
64
65
65
- def makeMasterGlyphsCompatible (self ):
66
+ def applySkipExportGlyphs (self ):
67
+ for font in self .operator .fonts :
68
+ skipExportGlyphs = set (font .lib .get ("public.skipExportGlyphs" , []))
69
+ if skipExportGlyphs :
70
+ # Decompose the listed glyphs everywhere they are used as components.
71
+ for glyph in font :
72
+ for component in glyph .components :
73
+ if component .baseGlyph in skipExportGlyphs :
74
+ glyph .decomposeComponent (component )
75
+ # Remove these glyphs before the compilation run.
76
+ for glyphName in skipExportGlyphs :
77
+ if glyphName in font :
78
+ del font [glyphName ]
79
+ # Prune all groups of the listed glyphs.
80
+ for key , value in list (font .groups .items ()):
81
+ font .groups [key ] = [glyphName for glyphName in value if glyphName not in skipExportGlyphs ]
82
+ # Prune all kerning pairs that contain any of the listed glyphs.
83
+ for side1 , side2 in list (font .kerning .keys ()):
84
+ if side1 in skipExportGlyphs or side2 in skipExportGlyphs :
85
+ del font .kerning [side1 , side2 ]
86
+
87
+ def makeSourcesAtAxesExtremes (self ):
88
+ if self .fitToExtremes :
89
+ self .report .writeTitle ("Add sources at axes extremes" , "'" )
90
+ extremeLocations = []
91
+ for axis in self .operator .axes :
92
+ location = dict ()
93
+ for otherAxis in self .operator .axes :
94
+ if otherAxis == axis :
95
+ continue
96
+ location [otherAxis .name ] = otherAxis .default
97
+
98
+ if hasattr (axis , "values" ):
99
+ for value in axis .values :
100
+ extremeLocations .append (dict (** location , ** {axis .name : value }))
101
+ else :
102
+ extremeLocations .append (dict (** location , ** {axis .name : axis .minimum }))
103
+ extremeLocations .append (dict (** location , ** {axis .name : axis .maximum }))
104
+
105
+ sourceLocations = [sourceDescriptor .location for sourceDescriptor in self .operator .sources ]
106
+ for extremeLocation in extremeLocations :
107
+ if extremeLocation not in sourceLocations :
108
+
109
+ self .report .indent ()
110
+ self .report .write ("Adding source at location:" )
111
+ self .report .indent ()
112
+ self .report .writeDict (extremeLocation )
113
+ self .report .dedent ()
114
+ font = self .operator .makeInstance (extremeLocation )
115
+ self .operator .addSourceDescriptor (
116
+ font = font ,
117
+ name = f"source.{ len (self .operator .sources ) + 1 } " ,
118
+ familyName = font .info .familyName ,
119
+ styleName = font .info .styleName ,
120
+ location = extremeLocation
121
+ )
122
+ self .report .dedent ()
123
+ self .report .newLine ()
124
+
125
+ def makeSourceGlyphsCompatible (self ):
66
126
"""
67
127
Update all sources with missing glyphs.
68
128
All sources must have the same glyphs.
69
129
"""
70
- self .report .writeTitle ("Making master glyphs compatible" , "'" )
130
+ self .report .writeTitle ("Making source glyphs compatible" , "'" )
71
131
self .report .indent ()
72
132
# collect all possible glyph names
73
133
glyphNames = set ()
@@ -77,7 +137,7 @@ def makeMasterGlyphsCompatible(self):
77
137
defaultSource = self .operator .findDefaultFont ()
78
138
# loop over all glyphName
79
139
for glyphName in glyphNames :
80
- # first check if the default master has this glyph
140
+ # first check if the default source has this glyph
81
141
if glyphName not in defaultSource :
82
142
# the default does not have the glyph
83
143
# build a repair glyph
@@ -89,15 +149,15 @@ def makeMasterGlyphsCompatible(self):
89
149
roundGeometry = self .operator .roundGeometry ,
90
150
clip = False
91
151
)
92
- self .report .write (f"Adding missing glyph '{ glyphName } ' in the default master '{ defaultSource .info .familyName } { defaultSource .info .styleName } '" )
93
- # add the glyph to the default master
152
+ self .report .write (f"Adding missing glyph '{ glyphName } ' in the default source '{ defaultSource .info .familyName } { defaultSource .info .styleName } '" )
153
+ # add the glyph to the default source
94
154
glyph = defaultSource .newGlyph (glyphName )
95
155
result .extractGlyph (glyph , onlyGeometry = True )
96
156
glyph .unicodes = list (result .unicodes )
97
157
98
158
sourceGlyphs = []
99
- # fill all masters with missing glyphs
100
- # and collect all glyphs from all masters
159
+ # fill all sources with missing glyphs
160
+ # and collect all glyphs from all sources
101
161
# to send them to optimize contour data
102
162
for sourceDescriptor in self .operator .sources :
103
163
sourceFont = self .operator .fonts [sourceDescriptor .name ]
@@ -114,7 +174,7 @@ def makeMasterGlyphsCompatible(self):
114
174
clip = False
115
175
)
116
176
self .report .write (f"Adding missing glyph '{ glyphName } ' in the source '{ sourceFont .info .familyName } { sourceFont .info .styleName } '" )
117
- # add the glyph to the master
177
+ # add the glyph to the source
118
178
glyph = sourceFont .newGlyph (glyphName )
119
179
result .extractGlyph (glyph , onlyGeometry = True )
120
180
glyph .unicodes = list (result .unicodes )
@@ -165,7 +225,7 @@ def makeGlyphOutlinesCompatible(self, glyphs):
165
225
if types == pointTypes :
166
226
continue
167
227
# add missing off curves
168
- self .report .write (f"Adding missing offcurves in contour { contourIndex } for glyph '{ glyph .name } ' in master '{ font .info .familyName } { font .info .styleName } '" )
228
+ self .report .write (f"Adding missing offcurves in contour { contourIndex } for glyph '{ glyph .name } ' in source '{ font .info .familyName } { font .info .styleName } '" )
169
229
contour = glyph [contourIndex ]
170
230
pen = CompatibleContourPointPen (pointTypes )
171
231
contour .drawPoints (pen )
@@ -185,7 +245,7 @@ def decomposedMixedGlyphs(self):
185
245
if len (glyph ) and len (glyph .components ):
186
246
# found, loop over all components and decompose
187
247
for component in glyph .components :
188
- # get the master font
248
+ # get the source font
189
249
base = fontSource [component .baseGlyph ]
190
250
# get the decompose pen
191
251
decomposePointPen = DecomposePointPen (glyph .layer , glyph .getPointPen (), component .transformation )
@@ -197,29 +257,29 @@ def decomposedMixedGlyphs(self):
197
257
component .drawPoints (decomposePointPen )
198
258
# remove all components
199
259
glyph .clearComponents ()
200
- self .report .write (f"Decomposing glyph '{ glyph .name } ' in master '{ fontSource .info .familyName } { fontSource .info .styleName } '" )
260
+ self .report .write (f"Decomposing glyph '{ glyph .name } ' in source '{ fontSource .info .familyName } { fontSource .info .styleName } '" )
201
261
self .report .dedent ()
202
262
self .report .newLine ()
203
263
204
- def makeMasterGlyphsQuadractic (self ):
264
+ def makeSourceGlyphsQuadractic (self ):
205
265
"""
206
- Optimize and convert all master ufo to quad curves.
266
+ Optimize and convert all source ufo to quad curves.
207
267
"""
208
- # use cu2qu to optimize all masters
268
+ # use cu2qu to optimize all sources
209
269
fonts_to_quadratic (self .operator .fonts .values ())
210
270
211
- def makeMasterExportOptimizeCharstring (self ):
271
+ def makeSourceExportOptimizeCharstring (self ):
212
272
for name , font in self .operator .fonts .items ():
213
273
font .lib ["com.typemytype.robofont.optimizeCharstring" ] = False
214
274
215
- def makeMasterKerningCompatible (self ):
275
+ def makeSourceKerningCompatible (self ):
216
276
"""
217
277
Optimize kerning data.
218
- All masters must have the same kering pairs.
278
+ All sources must have the same kering pairs.
219
279
Build repair mutators for missing kering pairs
220
280
and generate the kerning value within the design space.
221
281
"""
222
- self .report .writeTitle ("Making master kerning compatible" , "'" )
282
+ self .report .writeTitle ("Making source kerning compatible" , "'" )
223
283
self .report .indent ()
224
284
# collect all kerning pairs
225
285
allPairs = set ()
@@ -234,7 +294,7 @@ def makeMasterKerningCompatible(self):
234
294
kerningCache = dict ()
235
295
# loop over all pairs
236
296
for pair in allPairs :
237
- # loop over all masters
297
+ # loop over all sources
238
298
for sourceDescriptor in self .operator .sources :
239
299
sourceFont = self .operator .fonts [sourceDescriptor .name ]
240
300
missingPairs = []
@@ -263,7 +323,7 @@ def makeMasterKerningCompatible(self):
263
323
self .report .dedent ()
264
324
self .report .newLine ()
265
325
266
- def makeMasterOnDefaultLocation (self ):
326
+ def makeSourceOnDefaultLocation (self ):
267
327
"""
268
328
create default location
269
329
which is on the crossing of all axis
@@ -275,19 +335,19 @@ def makeMasterOnDefaultLocation(self):
275
335
# found the default location
276
336
# do nothing
277
337
return
278
- self .report .writeTitle ("Setting a master on the default" , "'" )
338
+ self .report .writeTitle ("Setting a source on the default" , "'" )
279
339
self .report .indent ()
280
- # there is no master at the default location
281
- # change the defaults of each axis so it fits with a given master
340
+ # there is no source at the default location
341
+ # change the defaults of each axis so it fits with a given source
282
342
for axis in self .operator .axes :
283
343
axis .default = axis .map_backward (defaultLocation [axis .name ])
284
344
self .report .writeDict (defaultLocation )
285
345
self .report .dedent ()
286
346
self .report .newLine ()
287
347
288
- def makeLayerMaster (self ):
348
+ def makeLayerSource (self ):
289
349
"""
290
- If there is a layer name in a source description add it as seperate master in the source description.
350
+ If there is a layer name in a source description add it as seperate source in the source description.
291
351
"""
292
352
for sourceDescriptor in self .operator .sources :
293
353
if sourceDescriptor .layerName is not None :
0 commit comments