Skip to content

Commit 398e894

Browse files
committed
Mitigate the instability of autoKern
successfully reducing individual patches as a result
1 parent d23ddf3 commit 398e894

7 files changed

Lines changed: 322 additions & 309 deletions

File tree

xkcd-script/font/xkcd-script.otf

5.8 KB
Binary file not shown.

xkcd-script/font/xkcd-script.sfd

Lines changed: 295 additions & 287 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

xkcd-script/font/xkcd-script.ttf

5.8 KB
Binary file not shown.

xkcd-script/font/xkcd-script.woff

2.56 KB
Binary file not shown.

xkcd-script/generator/pt7_font_properties.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def autokern(font):
7777
font.addLookup('kerning', 'gpos_pair', (), [['kern', [['latn', ['dflt']]]]])
7878
font.addLookupSubtable('kerning', 'kern')
7979

80-
def kern(sep, left, right, **kwargs):
80+
def kern(sep, left, right, damper=None, **kwargs):
8181
"""Wraps font.autoKern: expands accented variants and leading/trailing ligatures."""
8282
def expand(chars, left_side):
8383
expanded = _expand_with_variants(font, chars)
@@ -94,7 +94,16 @@ def expand(chars, left_side):
9494
expanded.append(name)
9595
seen.add(name)
9696
return expanded
97-
font.autoKern('kern', sep, expand(left, left_side=True), expand(right, left_side=False), **kwargs)
97+
lefts = expand(left, left_side=True)
98+
rights = expand(right, left_side=False)
99+
font.autoKern('kern', sep, lefts, rights, **kwargs)
100+
if damper and damper != 1.0:
101+
for l in lefts:
102+
tuples = font[l].getPosSub('kern')
103+
new_table = []
104+
for tup in tuples:
105+
if tup[1] == 'Pair' and tup[2] in rights:
106+
font[l].addPosSub('kern', *(tup[2:5] + (int(tup[5] * damper),) + tup[6:]))
98107

99108
def getkern(left, right):
100109
c = font[left]
@@ -119,29 +128,25 @@ def getkern(left, right):
119128
kern(80+a, ['x'], set(lower) - {'i', 'j'}, onlyCloser=True)
120129
kern(100+a, ['f', 't'], set(lower) - {'i', 'j'}, onlyCloser=True)
121130
# Set *Y altogether first: CY, OY, etc. will have appropriate values set in the latter part.
122-
kern(120, roman, ['Y', 'T'], onlyCloser=True)
131+
# CY is a notable example where it is better to use the smaller separation value.
132+
kern(105, roman, ['Y', 'T'], onlyCloser=True, damper=0.75)
133+
kern(35, caps, ['f'], onlyCloser=True, touch=True, damper=0.9)
123134
# F/E are separated from T/J so they can use a tighter target gap.
124-
kern(130, ['F'], set(roman) - {'f', 'j'}, onlyCloser=True)
135+
kern(110, ['F'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
125136
# Since F and z mesh together and the kerning becomes too large,
126-
# reuse the kerning value of the round letterforms.
137+
# reuse the kerning value of one of the round letterforms.
127138
diff_Fo_Fz = getkern('F', 'o') - getkern('F', 'z')
128-
kern(130 + diff_Fo_Fz, ['F'], ['z'], onlyCloser=True)
129-
kern(100, ['E'], set(roman) - {'f', 'j'}, onlyCloser=True)
130-
kern(140, ['E'], ['V'], onlyCloser=True)
131-
kern(150, ['T', 'J'], set(roman) - {'f', 'j'}, onlyCloser=True)
132-
kern(120, ['T', 'J'], ['O', 'R'], onlyCloser=True)
133-
kern(120, ['Y'], set(roman) - {'f', 'j'}, onlyCloser=True)
134-
kern(100, ['V'], set(roman) - {'f', 'j'}, onlyCloser=True)
135-
# C: loosen from the default (was too tight for Ct/Cf/Cj).
136-
kern(65, ['C'], set(roman) - {'f', 'j'}, onlyCloser=True)
137-
kern(30, ['C'], ['V', 't', 'v'], onlyCloser=True, touch=True)
138-
kern(60, ['O', 'P'], set(roman) - {'f', 'j'}, onlyCloser=True)
139-
# For some reason, touch=True creates an unnatural gap in Pe.
140-
kern(40, ['P'], ['X', 'a', 'd', 'g', 'q'], onlyCloser=True, touch=True)
141-
kern(80, ['D'], set(roman) - {'f', 'j'}, onlyCloser=True)
142-
kern(40, ['L'], set(roman) - {'f', 'j'}, onlyCloser=True, touch=True)
143-
kern(40, caps, ['f'], onlyCloser=True, touch=True)
144-
kern(180, roman, ['j'], onlyCloser=True)
139+
kern(110 + int(diff_Fo_Fz / 0.75), ['F'], ['z'], onlyCloser=True, damper=0.75)
140+
kern(90, ['E'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
141+
kern(115, ['T', 'J'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
142+
kern(105, ['Y'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
143+
kern(95, ['V'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
144+
kern(65, ['C'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
145+
kern(40, ['E', 'C'], ['V'], onlyCloser=True, touch=True)
146+
kern(60, ['O', 'P'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
147+
kern(70, ['D'], set(roman) - {'j'}, onlyCloser=True, damper=0.75)
148+
kern(150, roman, ['j'], onlyCloser=True, damper=0.75)
149+
kern(40, ['L'], roman, onlyCloser=True, touch=True, damper=0.9)
145150

146151

147152
autokern(font)
7 Bytes
Loading

xkcd-script/samples/kerning.png

-233 Bytes
Loading

0 commit comments

Comments
 (0)