Skip to content

Commit fdd68b4

Browse files
committed
make goadbWriter testable, add tests
1 parent 75c6c4a commit fdd68b4

File tree

204 files changed

+1823
-34
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

204 files changed

+1823
-34
lines changed

goadbWriter.py

Lines changed: 75 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22

33
'''
4-
GOADB writer -- write a GOADB file using a UFO as an input.
4+
GOADB writer -- write a GlyphOrderAndAliasDB file using a UFO as an input.
55
Relies on the agl glyph names which come in fontTools’ agl module.
66
77
More reading on the GOADB format:
@@ -13,11 +13,21 @@
1313

1414
import argparse
1515
import re
16+
from pathlib import Path
1617
from fontTools import agl
1718
from defcon import Font, Glyph
1819

1920

20-
def get_args():
21+
def check_input_file(parser, file_name):
22+
fn = Path(file_name)
23+
if fn.suffix.lower() != '.ufo':
24+
parser.error(f'{fn.name} is not a UFO file')
25+
if not fn.exists():
26+
parser.error(f'{fn.name} does not exist')
27+
return file_name
28+
29+
30+
def get_args(args=None):
2131
parser = argparse.ArgumentParser(
2232
description=__doc__,
2333
)
@@ -37,12 +47,13 @@ def get_args():
3747
)
3848

3949
parser.add_argument(
40-
'ufo',
50+
'input_file',
51+
type=lambda f: check_input_file(parser, f),
4152
action='store',
4253
help='UFO file',
4354
)
4455

45-
return parser.parse_args()
56+
return parser.parse_args(args)
4657

4758

4859
def get_glyph_order(f, include_template_glyphs=False):
@@ -54,8 +65,9 @@ def get_glyph_order(f, include_template_glyphs=False):
5465
5566
In the case that the public.glyphOrder key does not exist, resort to
5667
unrefined sorting:
57-
* by code point (if encoded)
58-
* alphabetically by name (if unencoded)
68+
* encoded: by code point
69+
* unencoded: following code point sorting (deduced by glyph name)
70+
* unencoded: alphabetically by name (for the rest)
5971
6072
NB: defcon and RF have different ways of determining template glyphs.
6173
in defcon, f.glyphOrder includes template glyphs
@@ -84,15 +96,32 @@ def get_glyph_order(f, include_template_glyphs=False):
8496
else:
8597
# first, all encoded glyphs are sorted by code point
8698
# then, the rest is sorted alphabetically.
99+
100+
# all glyphs
87101
glyphs_encoded = sorted(
88102
[g for g in f if g.unicode], key=lambda g: g.unicode)
89-
glyphs_unencoded = sorted(
90-
[g for g in f if g.unicode is None and g.name != '.notdef'],
91-
key=lambda g: g.name)
92-
order = (
93-
['.notdef'] +
94-
[g.name for g in glyphs_encoded] +
95-
[g.name for g in glyphs_unencoded])
103+
gnames_encoded = [g.name for g in glyphs_encoded]
104+
105+
glyphs_unencoded = [
106+
g for g in f if g.unicode is None and g.name != '.notdef']
107+
108+
# more specific sub-groups:
109+
# glyphs which alternates of the encoded glyphs
110+
glyphs_alternates = [
111+
g for g in glyphs_unencoded if
112+
g.name.split('.')[0] in gnames_encoded]
113+
# sort names by their suffix first,
114+
# then by the order of related names of encoded glyphs.
115+
gnames_alternates = sorted(
116+
[g.name for g in glyphs_alternates],
117+
key=lambda gn: (gn.split('.')[1], gnames_encoded.index(gn.split('.')[0])))
118+
119+
# glyphs not related to encoded glyphs are sorted alphabetically
120+
glyphs_rest = [
121+
g for g in glyphs_unencoded if g not in glyphs_alternates]
122+
gnames_rest = sorted([g.name for g in glyphs_rest])
123+
124+
order = ['.notdef'] + gnames_encoded + gnames_alternates + gnames_rest
96125

97126
return order
98127

@@ -205,11 +234,11 @@ class GlyphBaptism(object):
205234
206235
'''
207236

208-
def __init__(self, gn_friendly, glyph=None, gn_final=None, cp_override=None):
209-
if glyph is None:
237+
def __init__(self, gn_friendly, g=None, gn_final=None, cp_override=None):
238+
if g is None:
210239
self.glyph = Glyph()
211240
else:
212-
self.glyph = glyph
241+
self.glyph = g
213242

214243
self.gn_friendly = gn_friendly
215244
self.gn_final = gn_final
@@ -269,11 +298,11 @@ def assign_final_and_cp_override(self):
269298
expected_codepoint = int(cp_hex, 16)
270299
actual_codepoint = self.glyph.unicode
271300
if expected_codepoint == actual_codepoint:
272-
# codepoint is the expected one.
301+
# codepoint is the expected one
273302
self.gn_final = self.gn_friendly
274303
else:
275-
# codepoint is different from what we expect
276-
# (weird but OK)
304+
# codepoint is different from what the name implies
305+
# (weird flex but OK)
277306
self.gn_final = get_uni_name(self.glyph.unicode)
278307

279308
# custom glyph name
@@ -303,7 +332,17 @@ def fill_gn_dict(gb, glyph_name_dict):
303332
return glyph_name_dict
304333

305334

306-
def make_glyph_name_dict(f):
335+
def get_glyph(f, gname):
336+
try:
337+
glyph = f[gname]
338+
except KeyError:
339+
# template glyph
340+
glyph = Glyph()
341+
glyph.name = gname
342+
return glyph
343+
344+
345+
def make_glyph_name_dict(f, glyph_order):
307346
'''
308347
make a dictionary:
309348
{friendly name: gb object}
@@ -329,18 +368,19 @@ def make_glyph_name_dict(f):
329368
# alternate, or is it an alternate ligature in itself?
330369
# I interpret it as a combination of two fs and one l.alt.
331370

332-
base_glyphs = [g for g in f if not any(['.' in g.name, '_' in g.name])]
371+
base_glyphs = [gn for gn in glyph_order if not any(['.' in gn, '_' in gn])]
333372
alt_glyphs = [
334-
g for g in f if '.' in g.name and
335-
'_' not in g.name and
336-
g.name != '.notdef']
337-
liga_glyphs = {g for g in f if '_' in g.name}
373+
gn for gn in glyph_order if '.' in gn and '_' not in gn and
374+
gn != '.notdef']
375+
liga_glyphs = [gn for gn in glyph_order if '_' in gn]
338376

339-
for g in base_glyphs:
377+
for gn in base_glyphs:
378+
g = get_glyph(f, gn)
340379
gb = GlyphBaptism(g.name, g)
341380
glyph_name_dict = fill_gn_dict(gb, glyph_name_dict)
342381

343-
for g in alt_glyphs:
382+
for gn in alt_glyphs:
383+
g = get_glyph(f, gn)
344384
stem, suffixes = g.name.split('.', 1)
345385
if stem in glyph_name_dict:
346386
final_name_stem = glyph_name_dict.get(stem).gn_final
@@ -357,7 +397,8 @@ def make_glyph_name_dict(f):
357397

358398
glyph_name_dict = fill_gn_dict(gb, glyph_name_dict)
359399

360-
for g in liga_glyphs:
400+
for gn in liga_glyphs:
401+
g = get_glyph(f, gn)
361402
liga_chunks = g.name.split('_')
362403
liga_chunks_final = []
363404
for chunk in liga_chunks:
@@ -380,7 +421,7 @@ def make_glyph_name_dict(f):
380421
return glyph_name_dict
381422

382423

383-
def get_goadb(glyph_order, glyph_name_dict):
424+
def build_goadb(glyph_order, glyph_name_dict):
384425
goadb = []
385426
for gname in glyph_order:
386427
gb = glyph_name_dict.get(gname)
@@ -391,12 +432,12 @@ def get_goadb(glyph_order, glyph_name_dict):
391432
return '\n'.join(goadb)
392433

393434

394-
def main():
395-
args = get_args()
396-
f = Font(args.ufo)
435+
def main(test_args=None):
436+
args = get_args(test_args)
437+
f = Font(args.input_file)
397438
glyph_order = get_glyph_order(f, args.template)
398-
glyph_name_dict = make_glyph_name_dict(f)
399-
goadb = get_goadb(glyph_order, glyph_name_dict)
439+
glyph_name_dict = make_glyph_name_dict(f, glyph_order)
440+
goadb = build_goadb(glyph_order, glyph_name_dict)
400441
if args.output:
401442
with open(args.output, 'w') as blob:
402443
blob.write(goadb)

tests/goadb_full

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.notdef .notdef
2+
A A
3+
B B
4+
uni0815 C
5+
Zacute Zacute uni0179,uni017A
6+
asd asd
7+
asdasd asdasd
8+
eiurwoue eiurwoue
9+
uni348F Zglibber
10+
uni348F.alt Zglibber.alt
11+
uni6666 uni6666
12+
uni6668 uni6667
13+
uni6669 uni6669
14+
uniFFFF uniFFFF uni8888,uni8889
15+
u10000 u10000
16+
uni348F.01 Zglibber.01
17+
uni348F.02 Zglibber.02
18+
Zglibber Z-glibber
19+
A_B A_B
20+
uni0390 idieresistonos
21+
uni0390.alt idieresistonos.alt
22+
uni0390.alt_uni0390 idieresistonos.alt_idieresistonos
23+
illegal .illegal
24+
cents 2cents
25+
dummy 666
26+
dummy0000 667
27+
f_f_uni0390 f_f_idieresistonos
28+
f_f_i f_f_i uniFB03
29+
dummy0001 668
30+
dummy0002 669
31+
wt wät
32+
dummy0003 🥳
33+
u55555 beyondFFFF
34+
multitude multitude uni0061,uni0062,uni0063,uni0064,uni0065,uni0066,uni0067,uni0068,uni0069,uni006A,uni006B,uni006C,uni006D,uni006E,uni006F,uni0070,uni0071,uni0072,uni0073,uni0074,uni0075,uni0076,uni0077,uni0078,uni0079,uni007A
35+
zero zero
36+
zero.sups zero.sups uni2070
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>ascender</key>
6+
<integer>750</integer>
7+
<key>capHeight</key>
8+
<integer>750</integer>
9+
<key>descender</key>
10+
<integer>-250</integer>
11+
<key>postscriptBlueValues</key>
12+
<array>
13+
</array>
14+
<key>postscriptFamilyBlues</key>
15+
<array>
16+
</array>
17+
<key>postscriptFamilyOtherBlues</key>
18+
<array>
19+
</array>
20+
<key>postscriptOtherBlues</key>
21+
<array>
22+
</array>
23+
<key>postscriptStemSnapH</key>
24+
<array>
25+
</array>
26+
<key>postscriptStemSnapV</key>
27+
<array>
28+
</array>
29+
<key>unitsPerEm</key>
30+
<integer>1000</integer>
31+
<key>xHeight</key>
32+
<integer>500</integer>
33+
</dict>
34+
</plist>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<glyph name="2cents" format="2">
3+
</glyph>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<glyph name="666" format="2">
3+
</glyph>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<glyph name="667" format="2">
3+
</glyph>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<glyph name="668" format="2">
3+
</glyph>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<glyph name="669" format="2">
3+
</glyph>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<glyph name="A" format="2">
3+
<unicode hex="0041"/>
4+
<advance width="661"/>
5+
</glyph>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<glyph name="A_B" format="2">
3+
</glyph>

0 commit comments

Comments
 (0)