Add font patcher script
This commit is contained in:
parent
af1f3ec7bd
commit
9a5b94dc28
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
try:
|
||||
import fontforge
|
||||
import psMat
|
||||
except ImportError:
|
||||
sys.stderr.write('The required FontForge modules could not be loaded.\n\n')
|
||||
|
||||
if sys.version_info.major > 2:
|
||||
sys.stderr.write('FontForge only supports Python 2. Please run this script with the Python 2 executable - e.g. "python2 {0}"\n'.format(sys.argv[0]))
|
||||
else:
|
||||
sys.stderr.write('You need FontForge with Python bindings for this script to work.\n')
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
# Handle command-line arguments
|
||||
parser = argparse.ArgumentParser(description='Font patcher for Powerline. Requires FontForge with Python bindings. Stores the patched font as a new, renamed font file by default.')
|
||||
|
||||
parser.add_argument('target_fonts', help='font files to patch', metavar='font', nargs='+', type=argparse.FileType('rb'))
|
||||
parser.add_argument('--no-rename', help='don\'t add " for Powerline" to the font name', default=True, action='store_false', dest='rename_font')
|
||||
parser.add_argument('--source-font', help='source symbol font', metavar='font', dest='source_font', default='{0}/fontpatcher-symbols.sfd'.format(sys.path[0]), type=argparse.FileType('rb'))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
class FontPatcher(object):
|
||||
def __init__(self, source_font, target_fonts, rename_font=True):
|
||||
self.source_font = fontforge.open(source_font.name)
|
||||
self.target_fonts = (fontforge.open(target_font.name) for target_font in target_fonts)
|
||||
self.rename_font = rename_font
|
||||
|
||||
def patch(self):
|
||||
for target_font in self.target_fonts:
|
||||
source_font = self.source_font
|
||||
|
||||
target_font.encoding = 'ISO10646'
|
||||
|
||||
# Rename font
|
||||
if self.rename_font:
|
||||
target_font.familyname += ' for Powerline'
|
||||
target_font.fullname += ' for Powerline'
|
||||
target_font.fontname += 'ForPowerline'
|
||||
target_font.appendSFNTName('English (US)', 'Preferred Family', target_font.familyname)
|
||||
target_font.appendSFNTName('English (US)', 'Compatible Full', target_font.fullname)
|
||||
|
||||
source_bb = source_font['block'].boundingBox()
|
||||
target_bb = [0, 0, 0, 0]
|
||||
|
||||
# Find the biggest char width and height in the Latin-1 extended range and the box drawing range
|
||||
# This isn't ideal, but it works fairly well - some fonts may need tuning after patching
|
||||
for cp in range(0x00, 0x17f) + range(0x2500, 0x2600):
|
||||
try:
|
||||
bbox = target_font[cp].boundingBox()
|
||||
except TypeError:
|
||||
continue
|
||||
|
||||
if bbox[0] < target_bb[0]: target_bb[0] = bbox[0]
|
||||
if bbox[1] < target_bb[1]: target_bb[1] = bbox[1]
|
||||
if bbox[2] > target_bb[2]: target_bb[2] = bbox[2]
|
||||
if bbox[3] > target_bb[3]: target_bb[3] = bbox[3]
|
||||
|
||||
# Find source and target size difference for scaling
|
||||
x_ratio = (target_bb[2] - target_bb[0]) / (source_bb[2] - source_bb[0])
|
||||
y_ratio = (target_bb[3] - target_bb[1]) / (source_bb[3] - source_bb[1])
|
||||
scale = psMat.scale(x_ratio, y_ratio)
|
||||
|
||||
# Find source and target midpoints for translating
|
||||
x_diff = target_bb[0] - source_bb[0]
|
||||
y_diff = (target_bb[3] + target_bb[1]) - (source_bb[3] + source_bb[1])
|
||||
|
||||
translate = psMat.translate(x_diff, y_diff)
|
||||
|
||||
transform = psMat.compose(scale, translate)
|
||||
|
||||
# Create new glyphs from symbol font
|
||||
for source_glyph in source_font.glyphs():
|
||||
if source_glyph == source_font['block']:
|
||||
# Skip the symbol font block glyph
|
||||
continue
|
||||
|
||||
# Select and copy symbol from its encoding point
|
||||
source_font.selection.select(source_glyph.encoding)
|
||||
source_font.copy()
|
||||
|
||||
# Select and paste symbol to its unicode code point
|
||||
target_font.selection.select(source_glyph.unicode)
|
||||
target_font.paste()
|
||||
|
||||
# Transform the glyph
|
||||
target_font.transform(transform)
|
||||
|
||||
# Generate patched font
|
||||
target_font.generate('{0}.otf'.format(target_font.fullname))
|
||||
|
||||
fp = FontPatcher(args.source_font, args.target_fonts, args.rename_font)
|
||||
fp.patch()
|
Loading…
Reference in New Issue