File: kerningTest.py

package info (click to toggle)
mutatormath 3.0.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,820 kB
  • sloc: python: 2,581; makefile: 10
file content (141 lines) | stat: -rw-r--r-- 4,750 bytes parent folder | download | duplicates (3)
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# -*- coding: utf-8 -*-
from __future__ import print_function
from defcon.objects.font import Font
from fontMath import MathKerning

#from ufoLib.validators import kerningValidatorReportPairs
from fontMath.mathKerning import MathKerning

from mutatorMath.ufo.document import DesignSpaceDocumentWriter, DesignSpaceDocumentReader
from mutatorMath.objects.location import Location

import os, sys, shutil

"""

This is a test for a very specific problem that can occur
when two or more masters have valid kerning and groups,
but interpolations receive exceptions from both masters.
These exceptions can be in conflict.
It is hard to predict these conflicts exclusively on the input.
But they are easy to detect using the kerning validator from
ufoLib.

20160425 Changes in the validation of kerning in Defcon made this test irrelevant.
"""

def addGlyphs(font):
    # we need to add the glyphs
    for n in ['glyphOne', 'glyphTwo', 'glyphThree', 'glyphFour']:
        font.newGlyph(n)
        g = font[n]
        p = g.getPen()
        p.moveTo((100,100))
        p.lineTo((200,200))
        p.lineTo((0,100))
        p.closePath()

def makeTestFonts(rootPath):
    """ Make some test fonts that have the kerning problem."""
    path1 = os.path.join(rootPath, "validMaster1.ufo")
    path2 = os.path.join(rootPath, "validMaster2.ufo")
    path3 = os.path.join(rootPath, "invalidInstance.ufo")

    # Two masters
    f1 = Font()
    f1.groups['public.kern1.@MMK_L_one'] = ['glyphOne', 'glyphTwo']
    f1.groups['public.kern2.@MMK_R_two'] = ['glyphThree', 'glyphFour']
    addGlyphs(f1)

    f2 = Font()
    f2.groups.update(f1.groups)
    # both masters have the same groups

    addGlyphs(f2)
    assert f1.groups == f2.groups

    # a normal group / group pair in each master
    f1.kerning[('public.kern1.@MMK_L_one', 'public.kern2.@MMK_R_two')] = 1000
    f1.kerning[('a', 'b')] = 10
    f2.kerning[('public.kern1.@MMK_L_one', 'public.kern2.@MMK_R_two')] = 2000
    f2.kerning[('a', 'b')] = 10

    # a valid exception to this pair in each master
    f1.kerning[('public.kern1.@MMK_L_one', 'glyphThree')] = -500
    f2.kerning[('glyphOne', 'public.kern2.@MMK_R_two')] = -800

    # make sure the kerning and groups in each master validate.
    #assert kerningValidatorReportPairs(f1.kerning, f1.groups) == (True, [], [])
    #assert kerningValidatorReportPairs(f2.kerning, f2.groups) == (True, [], [])

    # save
    f1.save(path1, 3)
    f2.save(path2, 3)
    return path1, path2, path3

def testingProgressFunc(state, action, text, tick):
    """ Progress function that gets passed to the DesignSpaceDocumentReader should
        report on the faulty kerning pairs it found.
    """
    failPair1 = "invalidInstance.ufo:\nThese kerning pairs failed validation and have been removed:\nglyphOne, public.kern2.@MMK_R_two (-400) conflicts with public.kern1.@MMK_L_one, glyphThree (-250)\npublic.kern1.@MMK_L_one, glyphThree (-250) conflicts with glyphOne, public.kern2.@MMK_R_two (-400)"
    if state == "error" and action == 'kerning':
        assert failPair1 in text

def testOuroborosKerning(rootPath, cleanUp=True):
    # that works, let's do it via MutatorMath
    path1, path2, path3 = makeTestFonts(rootPath)
    documentPath = os.path.join(rootPath, 'kerningTest.designspace')

    doc = DesignSpaceDocumentWriter(documentPath, verbose=True)
    doc.addSource(
            path1,
            name="master_1", 
            location=dict(width=0), 
            copyLib=True,
            copyGroups=True,
            copyInfo=True, 
            copyFeatures=True,
            )
    doc.addSource(
            path2,
            name="master_2", 
            location=dict(width=1000), 
            copyLib=False,
            copyGroups=False,
            copyInfo=False, 
            copyFeatures=False,
            )
    doc.startInstance(fileName=path3,
            familyName="TestInstance",
            styleName="Regular",
            location=dict(width=100)
            )
    doc.writeKerning(location=dict(width=500))
    doc.endInstance()
    doc.save()

    # execute the designspace. Kerning errors should be tripped by the 
    doc = DesignSpaceDocumentReader(documentPath, 2, roundGeometry=True, verbose=True, progressFunc=testingProgressFunc)
    doc.process(makeGlyphs=True, makeKerning=True, makeInfo=True)

    if cleanUp:
        # remove the mess
        shutil.rmtree(path1)
        shutil.rmtree(path2)
        shutil.rmtree(path3)

    return True


    def test1():
        """
        >>> import time
        >>> import os
        >>> testOuroborosKerning(os.path.join(os.getcwd(), "testData"), cleanUp=True)
        True
        """


if __name__ == "__main__":
    import doctest
    sys.exit(doctest.testmod().failed)