|
9 | 9 | from fontTools.pens.ttGlyphPen import TTGlyphPen |
10 | 10 | from argparse import ArgumentParser |
11 | 11 | import pathops |
| 12 | +import subprocess |
| 13 | +import os |
12 | 14 |
|
| 15 | +def simpleDlig2calt(fontPath, inplace=False): |
| 16 | + """ |
| 17 | + A simple way to change a "dlig" feature to "calt." |
13 | 18 |
|
14 | | -# codeLigs = {} # probably not needed |
| 19 | + Assumes the fontPath hasn’t already been converted to a TTX file, |
| 20 | + as that would confuse the variables below. |
| 21 | + """ |
15 | 22 |
|
16 | | -def dlig2calt(fontPath, inplace=False): |
| 23 | + # convert font’s GSUB table to a TTX file |
| 24 | + subprocess.run(["ttx", "-t", "GSUB", fontPath]) |
| 25 | + |
| 26 | + # make the path for a ttx |
| 27 | + ttxPath = fontPath.replace(".ttf",".ttx") |
| 28 | + |
| 29 | + # Read in the TTX file |
| 30 | + with open(ttxPath, 'r') as file: |
| 31 | + ttxData = file.read() |
| 32 | + |
| 33 | + # Replace the target string to update the dlig feature tags to calt feature tags |
| 34 | + ttxData = ttxData.replace('"dlig"', '"calt"') |
| 35 | + |
| 36 | + # Write the TTX file out again |
| 37 | + with open(ttxPath, 'w') as file: |
| 38 | + file.write(ttxData) |
| 39 | + |
| 40 | + # merge TTX back into font: |
| 41 | + # ttx -m fontname.ttf fontname.ttx |
| 42 | + |
| 43 | + # save font |
| 44 | + if inplace: |
| 45 | + subprocess.run(["ttx", "-f", "-m", fontPath, ttxPath]) |
| 46 | + print("\nCode ligatures are now under the calt feature and on by default.\n") |
| 47 | + else: |
| 48 | + newFontPath = fontPath.replace('.ttf','.calt_ligs.ttf') |
| 49 | + subprocess.run(["ttx", "-o", newFontPath, "-m", fontPath, ttxPath]) |
| 50 | + print("Saved font with feature 'dlig' changed to 'calt' at ", newFontPath) |
| 51 | + |
| 52 | + # clean up the temporary TTX file |
| 53 | + os.remove(ttxPath) |
| 54 | + |
| 55 | + |
| 56 | +def makeCodeLigsMonospace(fontPath, inplace=False): |
| 57 | + """ |
| 58 | + Takes code ligatures with different widths, and makes them all exactly one monospace character wide. |
| 59 | +
|
| 60 | + The extra width goes over the left bound, and the space is made up for by a newly-created "LIG" glyph. |
| 61 | + """ |
17 | 62 |
|
18 | 63 | font = ttLib.TTFont(fontPath) |
19 | 64 |
|
20 | 65 | # set unit width / tabular width ... assumes the "=" symbol will have a tabular width for any code font |
21 | 66 | # 600 for most monospace fonts w/ UPM=1000 |
22 | 67 | unitWidth = font['hmtx']['equal'][0] |
23 | 68 |
|
24 | | - # make "LIG" glyph |
| 69 | + # create the "LIG" glyph to fill in gaps for code ligatures made into single-unit-wide glyphs |
25 | 70 | font['glyf'].__setitem__('LIG', font['glyf']['space']) |
26 | | - |
27 | 71 | font['hmtx'].__setitem__('LIG', font['hmtx']['space']) |
28 | 72 |
|
29 | 73 | # set /LIG glyph width to /equal width, not /space, to allow proportional fonts |
30 | | - |
31 | | - # print(font['glyf']._getPhantomPoints('LIG', font['hmtx'].metrics)) |
32 | | - |
33 | | - # newPhantomPoints = [(0,0), (600,0), (0, 0), (0, 0)] |
34 | | - |
35 | 74 | font['glyf']._setCoordinates('LIG', [(0,0), (600,0), (0, 0), (0, 0)], font['hmtx'].metrics) |
36 | 75 |
|
37 | 76 |
|
@@ -62,29 +101,31 @@ def dlig2calt(fontPath, inplace=False): |
62 | 101 | newCoords = adjustedCoords+adjustedPhantoms |
63 | 102 | font['glyf']._setCoordinates(glyphName, newCoords, font['hmtx'].metrics) |
64 | 103 |
|
65 | | - |
66 | 104 | # add new feature code, using calt rather than dlig |
67 | 105 | builder.addOpenTypeFeatures(font,"font-data/features/calt-generated--code_fonts_only.fea") |
68 | 106 |
|
69 | | - |
70 | 107 | # save font |
71 | 108 | if inplace: |
72 | 109 | font.save(fontPath) |
73 | 110 | print("\nCode ligatures are now on by default.\n") |
74 | 111 | else: |
75 | | - newPath = fontPath.replace('.ttf','.calt_ligs.ttf') |
76 | | - font.save(newPath) |
77 | | - print("Saved font with feature 'dlig' changed to 'calt' at ", newPath) |
| 112 | + fontPath = fontPath.replace('.ttf','.calt_ligs.ttf') |
| 113 | + font.save(fontPath) |
| 114 | + print("Saved font with feature 'dlig' changed to 'calt' at ", fontPath) |
78 | 115 |
|
79 | 116 |
|
80 | 117 | def main(): |
81 | | - description = "Change dlig features to calt features." |
82 | | - parser = ArgumentParser(description=description) |
83 | | - parser.add_argument('font', nargs=1) |
84 | | - parser.add_argument('--inplace', action='store_true') |
85 | | - args = parser.parse_args() |
86 | | - |
87 | | - dlig2calt(args.font[0], args.inplace) |
| 118 | + description = "Change dlig features to calt features." |
| 119 | + parser = ArgumentParser(description=description) |
| 120 | + parser.add_argument('font', nargs=1) |
| 121 | + parser.add_argument('--inplace', action='store_true') |
| 122 | + parser.add_argument('--mono', '-m', action='store_true') |
| 123 | + args = parser.parse_args() |
| 124 | + |
| 125 | + if args.mono: |
| 126 | + makeCodeLigsMonospace(args.font[0], args.inplace) |
| 127 | + else: |
| 128 | + simpleDlig2calt(args.font[0], args.inplace) |
88 | 129 |
|
89 | 130 |
|
90 | 131 | if __name__ == '__main__': |
|
0 commit comments