|
#! /usr/bin/env fontforge |
|
import argparse |
|
import sys |
|
|
|
try: |
|
import fontforge |
|
import psMat |
|
except ImportError: |
|
print('Please run this script through FontForge.') |
|
sys.exit(1) |
|
|
|
argparser = argparse.ArgumentParser() |
|
argparser.add_argument('in_file', help='Path to font file to fix') |
|
argparser.add_argument( |
|
'-s', '--startglyph', type=int, help='Start glyph', dest='start_glyph', default=32 |
|
) |
|
argparser.add_argument( |
|
'-e', '--endglyph', type=int, help='End glyph', dest='end_glyph', default=127 |
|
) |
|
argparser.add_argument( |
|
'-o', |
|
'--out', |
|
help='Path to output file. If unset, the input file is overwritten', |
|
dest='out_file', |
|
default=None, |
|
) |
|
args = argparser.parse_args() |
|
|
|
# No need to select the font file, this will work on the font you have currently open: |
|
font = fontforge.open(args.in_file) |
|
|
|
for i in range(args.start_glyph, args.end_glyph + 1): |
|
if i not in font: |
|
print(f'Glyph {i} not found, skipping') |
|
continue |
|
|
|
ytop = font[i].boundingBox()[-1] # counted from baseline, excluding descent |
|
ybot = font[i].boundingBox()[1] |
|
|
|
# Calculation method: |
|
# Midpoint of entire space = (ascent + descent) / 2 |
|
# Current midpoint of glyph (counted from baseline) = (ytop + ybot) / 2 |
|
# Current midpoint of glyph (counted with descent) = (ytop + ybot) / 2 + descent |
|
# Vertical translation = midpoint of entire space - current midpoint of glyph (counted with descent) |
|
# That is: (ascent + descent) / 2 - ((ytop + ybot) / 2 + descent) |
|
# Simplified: (ascent - descent - (ytop + ybot)) / 2 |
|
translation = (font.ascent - font.descent - (ytop + ybot)) / 2 |
|
font[i].transform(psMat.translate(0, translation)) |
|
|
|
print(f'Glyph {i} translated by {translation} units') |
|
|
|
# This bit for flags and bitmaps is taken from Nerd Fonts' font-patcher script |
|
# No idea if this is necessary, but just in case |
|
if int(fontforge.version()) >= 20201107: |
|
gen_flags = ('opentype', 'no-FFTM-table') |
|
else: |
|
gen_flags = ('opentype',) |
|
|
|
bitmaps = str() |
|
if len(font.bitmapSizes): |
|
print(f'Preserving bitmaps {font.bitmapSizes}') |
|
bitmaps = str('otf') # otf/ttf, both are bf_ttf |
|
|
|
out_file = args.out_file or args.in_file |
|
|
|
font.generate(out_file, bitmap_type=bitmaps, flags=gen_flags) |
|
print(f'Font patched successfully and saved to {out_file}') |