1from fontTools.pens.t2CharStringPen import T2CharStringPen 2import unittest 3 4 5class T2CharStringPenTest(unittest.TestCase): 6 7 def __init__(self, methodName): 8 unittest.TestCase.__init__(self, methodName) 9 10 def assertAlmostEqualProgram(self, expected, actual): 11 self.assertEqual(len(expected), len(actual)) 12 for i1, i2 in zip(expected, actual): 13 if isinstance(i1, str): 14 self.assertIsInstance(i2, str) 15 self.assertEqual(i1, i2) 16 else: 17 self.assertAlmostEqual(i1, i2) 18 19 def test_draw_h_v_lines(self): 20 pen = T2CharStringPen(100, {}) 21 pen.moveTo((0, 0)) 22 pen.lineTo((10, 0)) 23 pen.lineTo((10, 10)) 24 pen.lineTo((0, 10)) 25 pen.closePath() # no-op 26 pen.moveTo((10, 10)) 27 pen.lineTo((10, 20)) 28 pen.lineTo((0, 20)) 29 pen.lineTo((0, 10)) 30 pen.closePath() 31 charstring = pen.getCharString(None, None) 32 33 self.assertEqual( 34 [100, 35 0, 'hmoveto', 36 10, 10, -10, 'hlineto', 37 10, 'hmoveto', 38 10, -10, -10, 'vlineto', 39 'endchar'], 40 charstring.program) 41 42 def test_draw_lines(self): 43 pen = T2CharStringPen(100, {}) 44 pen.moveTo((5, 5)) 45 pen.lineTo((25, 15)) 46 pen.lineTo((35, 35)) 47 pen.lineTo((15, 25)) 48 pen.closePath() # no-op 49 charstring = pen.getCharString(None, None) 50 51 self.assertEqual( 52 [100, 53 5, 5, 'rmoveto', 54 20, 10, 10, 20, -20, -10, 'rlineto', 55 'endchar'], 56 charstring.program) 57 58 def test_draw_h_v_curves(self): 59 pen = T2CharStringPen(100, {}) 60 pen.moveTo((0, 0)) 61 pen.curveTo((10, 0), (20, 10), (20, 20)) 62 pen.curveTo((20, 30), (10, 40), (0, 40)) 63 pen.endPath() # no-op 64 charstring = pen.getCharString(None, None) 65 66 self.assertEqual( 67 [100, 68 0, 'hmoveto', 69 10, 10, 10, 10, 10, -10, 10, -10, 'hvcurveto', 70 'endchar'], 71 charstring.program) 72 73 def test_draw_curves(self): 74 pen = T2CharStringPen(100, {}) 75 pen.moveTo((95, 25)) 76 pen.curveTo((115, 44), (115, 76), (95, 95)) 77 pen.curveTo((76, 114), (44, 115), (25, 95)) 78 pen.endPath() # no-op 79 charstring = pen.getCharString(None, None) 80 81 self.assertEqual( 82 [100, 83 95, 25, 'rmoveto', 84 20, 19, 0, 32, -20, 19, -19, 19, -32, 1, -19, -20, 'rrcurveto', 85 'endchar'], 86 charstring.program) 87 88 def test_draw_more_curves(self): 89 pen = T2CharStringPen(100, {}) 90 pen.moveTo((10, 10)) 91 pen.curveTo((20, 10), (50, 10), (60, 10)) 92 pen.curveTo((60, 20), (60, 50), (60, 60)) 93 pen.curveTo((50, 50), (40, 60), (30, 60)) 94 pen.curveTo((40, 50), (30, 40), (30, 30)) 95 pen.curveTo((30, 25), (25, 19), (20, 20)) 96 pen.curveTo((15, 20), (9, 25), (10, 30)) 97 pen.curveTo((7, 25), (6, 15), (10, 10)) 98 pen.endPath() # no-op 99 charstring = pen.getCharString(None, None) 100 101 self.assertEqual( 102 [100, 103 10, 10, 'rmoveto', 104 10, 30, 0, 10, 'hhcurveto', 105 10, 0, 30, 10, 'vvcurveto', 106 -10, -10, -10, 10, -10, 'hhcurveto', 107 10, -10, -10, -10, -10, 'vvcurveto', 108 -5, -5, -6, -5, 1, 'vhcurveto', 109 -5, -6, 5, 5, 1, 'hvcurveto', 110 -3, -5, -1, -10, 4, -5, 'rrcurveto', 111 'endchar'], 112 charstring.program) 113 114 def test_default_width(self): 115 pen = T2CharStringPen(None, {}) 116 charstring = pen.getCharString(None, None) 117 self.assertEqual(['endchar'], charstring.program) 118 119 def test_no_round(self): 120 pen = T2CharStringPen(100.1, {}, roundTolerance=0.0) 121 pen.moveTo((0, 0)) 122 pen.curveTo((10.1, 0.1), (19.9, 9.9), (20.49, 20.49)) 123 pen.curveTo((20.49, 30.49), (9.9, 39.9), (0.1, 40.1)) 124 pen.closePath() 125 charstring = pen.getCharString(None, None) 126 127 self.assertAlmostEqualProgram( 128 [100, # we always round the advance width 129 0, 'hmoveto', 130 10.1, 0.1, 9.8, 9.8, 0.59, 10.59, 'rrcurveto', 131 10, -10.59, 9.41, -9.8, 0.2, 'vhcurveto', 132 'endchar'], 133 charstring.program) 134 135 def test_round_all(self): 136 pen = T2CharStringPen(100.1, {}, roundTolerance=0.5) 137 pen.moveTo((0, 0)) 138 pen.curveTo((10.1, 0.1), (19.9, 9.9), (20.49, 20.49)) 139 pen.curveTo((20.49, 30.5), (9.9, 39.9), (0.1, 40.1)) 140 pen.closePath() 141 charstring = pen.getCharString(None, None) 142 143 self.assertEqual( 144 [100, 145 0, 'hmoveto', 146 10, 10, 10, 10, 11, -10, 9, -10, 'hvcurveto', 147 'endchar'], 148 charstring.program) 149 150 def test_round_some(self): 151 pen = T2CharStringPen(100, {}, roundTolerance=0.2) 152 pen.moveTo((0, 0)) 153 # the following two are rounded as within the tolerance 154 pen.lineTo((10.1, 0.1)) 155 pen.lineTo((19.9, 9.9)) 156 # this one is not rounded as it exceeds the tolerance 157 pen.lineTo((20.49, 20.49)) 158 pen.closePath() 159 charstring = pen.getCharString(None, None) 160 161 self.assertAlmostEqualProgram( 162 [100, 163 0, 'hmoveto', 164 10, 'hlineto', 165 10, 10, 0.49, 10.49, 'rlineto', 166 'endchar'], 167 charstring.program) 168 169 def test_invalid_tolerance(self): 170 self.assertRaisesRegex( 171 ValueError, 172 "Rounding tolerance must be positive", 173 T2CharStringPen, None, {}, roundTolerance=-0.1) 174 175 176if __name__ == '__main__': 177 import sys 178 sys.exit(unittest.main()) 179