fantasque-sans/Scripts/features.py

81 lines
2.4 KiB
Python

# Generate features for ligatures
#
# Adapted from https://github.com/tonsky/FiraCode/blob/master/gen_calt.clj
from textwrap import dedent
import tempfile
def update_features(font):
"""Find ligatures in the font and generate features for them."""
# [ ["dash" "greater" "greater"] ... ]
ligas = [name[:-len('.liga')].split('_')
for name in font if name.endswith('.liga') and
font[name].isWorthOutputting()]
rules = '\n\n'.join(rule(liga)
for liga in sorted(ligas, key=lambda l: -len(l)))
fea_code = dedent('''\
languagesystem DFLT dflt;
languagesystem latn dflt;
languagesystem grek dflt;
languagesystem cyrl dflt;
feature calt {{
{}
}} calt;
''').format(indent(rules, ' '))
# print(fea_code) # DEBUG
# Add the dummy "LIG" glyph
lig = font.createChar(-1, 'LIG')
lig.width = font['space'].width
with tempfile.NamedTemporaryFile(suffix='.fea') as f:
f.write(fea_code)
f.seek(0)
font.mergeFeature(f.name)
def rule(liga):
"""
[f f i] => { [LIG LIG i] f_f_i.liga
[LIG f i] LIG
[ f f i] LIG }
"""
if len(liga) == 2:
return dedent('''\
lookup {0}_{1} {{
ignore sub {0} {0}' {1};
ignore sub {0}' {1} {1};
sub {0}' {1} by LIG;
sub LIG {1}' by {0}_{1}.liga;
}} {0}_{1};
''').format(*liga)
elif len(liga) == 3:
return dedent('''\
lookup {0}_{1}_{2} {{
ignore sub {0} {0}' {1} {2};
ignore sub {0}' {1} {2} {2};
sub {0}' {1} {2} by LIG;
sub LIG {1}' {2} by LIG;
sub LIG LIG {2}' by {0}_{1}_{2}.liga;
}} {0}_{1}_{2};
''').format(*liga)
elif len(liga) == 4:
return dedent('''\
lookup {0}_{1}_{2}_{3} {{
ignore sub {0} {0}' {1} {2} {3};
ignore sub {0}' {1} {2} {3} {3};
sub {0}' {1} {2} {3} by LIG;
sub LIG {1}' {2} {3} by LIG;
sub LIG LIG {2}' {3} by LIG;
sub LIG LIG LIG {3}' by {0}_{1}_{2}_{3}.liga;
}} {0}_{1}_{2}_{3};
''').format(*liga)
def indent(text, prefix):
return '\n'.join(prefix + line for line in text.split('\n'))