summaryrefslogtreecommitdiffstats
path: root/src/silfont/scripts/psfwoffit.py
blob: 286133a24c7d60d242675a17f4cf5cfdfefb82eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3
__doc__ = 'Convert font between ttf, woff, woff2'
__url__ = 'https://github.com/silnrsi/pysilfont'
__copyright__ = 'Copyright (c) 2021 SIL International (https://www.sil.org)'
__license__ = 'Released under the MIT License (https://opensource.org/licenses/MIT)'
__author__ = 'Bob Hallissy'

from silfont.core import execute
from fontTools.ttLib import TTFont
from fontTools.ttLib.sfnt import WOFFFlavorData
from fontTools.ttLib.woff2 import WOFF2FlavorData
import os.path

argspec = [
    ('infont', {'help': 'Source font file (can be ttf, woff, or woff2)'}, {}),
    ('-m', '--metadata', {'help': 'file containing XML WOFF metadata', 'default': None}, {}),
    ('--privatedata', {'help': 'file containing WOFF privatedata', 'default': None}, {}),
    ('-v', '--version', {'help': 'woff font version number in major.minor', 'default': None}, {}),
    ('--ttf',   {'help': 'name of ttf file to be written',   'nargs': '?', 'default': None, 'const': '-'}, {}),
    ('--woff',  {'help': 'name of woff file to be written',  'nargs': '?', 'default': None, 'const': '-'}, {}),
    ('--woff2', {'help': 'name of woff2 file to be written', 'nargs': '?', 'default': None, 'const': '-'}, {}),
    ('-l', '--log', {'help': 'Log file'}, {'type': 'outfile', 'def': '_woffit.log'})]

def doit(args):
    logger = args.logger
    infont = args.infont
    font = TTFont(args.infont)
    defaultpath = os.path.splitext(infont)[0]
    inFlavor = font.flavor or 'ttf'
    logger.log(f'input font {infont} is a {inFlavor}', 'I')

    # Read & parse version, if provided
    flavorData = WOFFFlavorData()  # Initializes all fields to None

    if args.version:
        try:
            version = float(args.version)
            if version < 0:
                raise ValueError('version cannot be negative')
            flavorData.majorVersion, flavorData.minorVersion = map(int, format(version, '.3f').split('.'))
        except:
            logger.log(f'invalid version syntax "{args.version}": should be MM.mmm', 'S')
    else:
        try:
            flavorData.majorVersion = font.flavorData.majorVersion
            flavorData.minorVersion = font.flavorData.minorVersion
        except:
            # Pull version from head table
            head = font['head']
            flavorData.majorVersion, flavorData.minorVersion =map(int, format(head.fontRevision, '.3f').split('.'))

    # Read metadata if provided, else get value from input font
    if args.metadata:
        try:
            with open(args.metadata, 'rb') as f:
                flavorData.metaData = f.read()
        except:
            logger.log(f'Unable to read file "{args.metadata}"', 'S')
    elif inFlavor != 'ttf':
        flavorData.metaData = font.flavorData.metaData

    # Same process for private data
    if args.privatedata:
        try:
            with open(args.privatedata, 'rb') as f:
                flavorData.privData = f.read()
        except:
            logger.log(f'Unable to read file "{args.privatedata}"', 'S')
    elif inFlavor != 'ttf':
        flavorData.privData = font.flavorData.privData

    if args.woff:
        font.flavor = 'woff'
        font.flavorData = flavorData
        fname =  f'{defaultpath}.{font.flavor}' if args.woff2 == '-' else args.woff
        logger.log(f'Writing {font.flavor} font to "{fname}"', 'P')
        font.save(fname)

    if args.woff2:
        font.flavor = 'woff2'
        font.flavorData = WOFF2FlavorData(data=flavorData)
        fname =  f'{defaultpath}.{font.flavor}' if args.woff2 == '-' else args.woff2
        logger.log(f'Writing {font.flavor} font to "{fname}"', 'P')
        font.save(fname)

    if args.ttf:
        font.flavor = None
        font.flavorData = None
        fname =  f'{defaultpath}.ttf' if args.ttf == '-' else args.ttf
        logger.log(f'Writing ttf font to "{fname}"', 'P')
        font.save(fname)

    font.close()

def cmd() : execute('FT',doit, argspec)
if __name__ == "__main__": cmd()