summaryrefslogtreecommitdiffstats
path: root/lib/silfont/scripts/psfcheckinterpolatable.py
blob: abcf5263d1e8825e780f138c0ecc79b4feb93059 (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
#!/usr/bin/env python
__doc__ = '''Check that the ufos in a designspace file are interpolatable'''
__url__ = 'http://github.com/silnrsi/pysilfont'
__copyright__ = 'Copyright (c) 2021 SIL International (http://www.sil.org)'
__license__ = 'Released under the MIT License (http://opensource.org/licenses/MIT)'
__author__ = 'David Raymond'

from silfont.core import execute
from fontParts.world import OpenFont
import fontTools.designspaceLib as DSD

argspec = [
    ('designspace', {'help': 'Design space file'}, {'type': 'filename'}),
    ('-l','--log', {'help': 'Log file'}, {'type': 'outfile', 'def': '_checkinterp.log'}),
    ]

def doit(args) :
    logger = args.logger

    ds = DSD.DesignSpaceDocument()
    ds.read(args.designspace)
    if len(ds.sources) == 1: logger.log("The design space file has only one source UFO", "S")

    # Find all the UFOs from the DS Sources.  Where there are more than 2, the primary one will be considered to be
    # the one where info copy="1" is set (as per psfsyncmasters).  If not set for any, use the first ufo.
    pufo = None
    otherfonts = {}
    for source in ds.sources:
        ufo = source.path
        try:
            font = OpenFont(ufo)
        except Exception as e:
            logger.log("Unable to open " + ufo, "S")
        if source.copyInfo:
            if pufo: logger.log('Multiple fonts with <info copy="1" />', "S")
            pufo = ufo
            pfont = font
        else:
            otherfonts[ufo] = font
    if pufo is None: # If we can't identify the primary font by conyInfo, just use the first one
        pufo = ds.sources[0].path
        pfont = otherfonts[pufo]
        del otherfonts[pufo]

    pinventory = set(glyph.name for glyph in pfont)
    
    for oufo in otherfonts:      
        logger.log(f'Comparing {pufo} with {oufo}', 'P')
        ofont = otherfonts[oufo]
        oinventory = set(glyph.name for glyph in ofont)
    
        if pinventory != oinventory:
            logger.log("The glyph inventories in the two UFOs differ", "E")
            for glyphn in sorted(pinventory - oinventory):
                logger.log(f'{glyphn} is only in {pufo}', "W")
            for glyphn in sorted(oinventory - pinventory):
                logger.log(f'{glyphn} is only in {oufo}', "W")
        else:
            logger.log("The UFOs have the same glyph inventories", "P")
        # Are glyphs compatible for interpolation
        incompatibles = {}
        for glyphn in pinventory & oinventory:
            compatible, report = pfont[glyphn].isCompatible(ofont[glyphn])
            if not compatible: incompatibles[glyphn] = report
        if incompatibles:
            logger.log(f'{len(incompatibles)} glyphs are not interpolatable', 'E')
            for glyphn in sorted(incompatibles):
                logger.log(f'{glyphn} is not interpolatable', 'W')
                logger.log(incompatibles[glyphn], "I")
            if logger.scrlevel == "W": logger.log("To see detailed reports run with scrlevel and/or loglevel set to I")
        else:
            logger.log("All the glyphs are interpolatable", "P")

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