1from __future__ import print_function, division, absolute_import 2from fontTools.misc.py23 import * 3from fontTools.pens.basePen import \ 4 BasePen, decomposeSuperBezierSegment, decomposeQuadraticSegment 5from fontTools.misc.loggingTools import CapturingLogHandler 6import unittest 7 8 9class _TestPen(BasePen): 10 def __init__(self): 11 BasePen.__init__(self, glyphSet={}) 12 self._commands = [] 13 14 def __repr__(self): 15 return " ".join(self._commands) 16 17 def getCurrentPoint(self): 18 return self._getCurrentPoint() 19 20 def _moveTo(self, pt): 21 self._commands.append("%s %s moveto" % (pt[0], pt[1])) 22 23 def _lineTo(self, pt): 24 self._commands.append("%s %s lineto" % (pt[0], pt[1])) 25 26 def _curveToOne(self, bcp1, bcp2, pt): 27 self._commands.append("%s %s %s %s %s %s curveto" % 28 (bcp1[0], bcp1[1], 29 bcp2[0], bcp2[1], 30 pt[0], pt[1])) 31 32 def _closePath(self): 33 self._commands.append("closepath") 34 35 def _endPath(self): 36 self._commands.append("endpath") 37 38 39class _TestGlyph: 40 def draw(self, pen): 41 pen.moveTo((0.0, 0.0)) 42 pen.lineTo((0.0, 100.0)) 43 pen.curveTo((50.0, 75.0), (60.0, 50.0), (50.0, 25.0), (0.0, 0.0)) 44 pen.closePath() 45 46 47class BasePenTest(unittest.TestCase): 48 def test_moveTo(self): 49 pen = _TestPen() 50 pen.moveTo((0.5, -4.3)) 51 self.assertEqual("0.5 -4.3 moveto", repr(pen)) 52 self.assertEqual((0.5, -4.3), pen.getCurrentPoint()) 53 54 def test_lineTo(self): 55 pen = _TestPen() 56 pen.moveTo((4, 5)) 57 pen.lineTo((7, 8)) 58 self.assertEqual("4 5 moveto 7 8 lineto", repr(pen)) 59 self.assertEqual((7, 8), pen.getCurrentPoint()) 60 61 def test_curveTo_zeroPoints(self): 62 pen = _TestPen() 63 pen.moveTo((0.0, 0.0)) 64 self.assertRaises(AssertionError, pen.curveTo) 65 66 def test_curveTo_onePoint(self): 67 pen = _TestPen() 68 pen.moveTo((0.0, 0.0)) 69 pen.curveTo((1.0, 1.1)) 70 self.assertEqual("0.0 0.0 moveto 1.0 1.1 lineto", repr(pen)) 71 self.assertEqual((1.0, 1.1), pen.getCurrentPoint()) 72 73 def test_curveTo_twoPoints(self): 74 pen = _TestPen() 75 pen.moveTo((0.0, 0.0)) 76 pen.curveTo((6.0, 3.0), (3.0, 6.0)) 77 self.assertEqual("0.0 0.0 moveto 4.0 2.0 5.0 4.0 3.0 6.0 curveto", 78 repr(pen)) 79 self.assertEqual((3.0, 6.0), pen.getCurrentPoint()) 80 81 def test_curveTo_manyPoints(self): 82 pen = _TestPen() 83 pen.moveTo((0.0, 0.0)) 84 pen.curveTo((1.0, 1.1), (2.0, 2.1), (3.0, 3.1), (4.0, 4.1)) 85 self.assertEqual("0.0 0.0 moveto " 86 "1.0 1.1 1.5 1.6 2.0 2.1 curveto " 87 "2.5 2.6 3.0 3.1 4.0 4.1 curveto", repr(pen)) 88 self.assertEqual((4.0, 4.1), pen.getCurrentPoint()) 89 90 def test_qCurveTo_zeroPoints(self): 91 pen = _TestPen() 92 pen.moveTo((0.0, 0.0)) 93 self.assertRaises(AssertionError, pen.qCurveTo) 94 95 def test_qCurveTo_onePoint(self): 96 pen = _TestPen() 97 pen.moveTo((0.0, 0.0)) 98 pen.qCurveTo((77.7, 99.9)) 99 self.assertEqual("0.0 0.0 moveto 77.7 99.9 lineto", repr(pen)) 100 self.assertEqual((77.7, 99.9), pen.getCurrentPoint()) 101 102 def test_qCurveTo_manyPoints(self): 103 pen = _TestPen() 104 pen.moveTo((0.0, 0.0)) 105 pen.qCurveTo((6.0, 3.0), (3.0, 6.0)) 106 self.assertEqual("0.0 0.0 moveto 4.0 2.0 5.0 4.0 3.0 6.0 curveto", 107 repr(pen)) 108 self.assertEqual((3.0, 6.0), pen.getCurrentPoint()) 109 110 def test_qCurveTo_onlyOffCurvePoints(self): 111 pen = _TestPen() 112 pen.moveTo((0.0, 0.0)) 113 pen.qCurveTo((6.0, -6.0), (12.0, 12.0), (18.0, -18.0), None) 114 self.assertEqual("0.0 0.0 moveto " 115 "12.0 -12.0 moveto " 116 "8.0 -8.0 7.0 -3.0 9.0 3.0 curveto " 117 "11.0 9.0 13.0 7.0 15.0 -3.0 curveto " 118 "17.0 -13.0 16.0 -16.0 12.0 -12.0 curveto", repr(pen)) 119 self.assertEqual((12.0, -12.0), pen.getCurrentPoint()) 120 121 def test_closePath(self): 122 pen = _TestPen() 123 pen.lineTo((3, 4)) 124 pen.closePath() 125 self.assertEqual("3 4 lineto closepath", repr(pen)) 126 self.assertEqual(None, pen.getCurrentPoint()) 127 128 def test_endPath(self): 129 pen = _TestPen() 130 pen.lineTo((3, 4)) 131 pen.endPath() 132 self.assertEqual("3 4 lineto endpath", repr(pen)) 133 self.assertEqual(None, pen.getCurrentPoint()) 134 135 def test_addComponent(self): 136 pen = _TestPen() 137 pen.glyphSet["oslash"] = _TestGlyph() 138 pen.addComponent("oslash", (2, 3, 0.5, 2, -10, 0)) 139 self.assertEqual("-10.0 0.0 moveto " 140 "40.0 200.0 lineto " 141 "127.5 300.0 131.25 290.0 125.0 265.0 curveto " 142 "118.75 240.0 102.5 200.0 -10.0 0.0 curveto " 143 "closepath", repr(pen)) 144 self.assertEqual(None, pen.getCurrentPoint()) 145 146 def test_addComponent_skip_missing(self): 147 pen = _TestPen() 148 with CapturingLogHandler(pen.log, "WARNING") as captor: 149 pen.addComponent("nonexistent", (1, 0, 0, 1, 0, 0)) 150 captor.assertRegex("glyph '.*' is missing from glyphSet; skipped") 151 152 153class DecomposeSegmentTest(unittest.TestCase): 154 def test_decomposeSuperBezierSegment(self): 155 decompose = decomposeSuperBezierSegment 156 self.assertRaises(AssertionError, decompose, []) 157 self.assertRaises(AssertionError, decompose, [(0, 0)]) 158 self.assertRaises(AssertionError, decompose, [(0, 0), (1, 1)]) 159 self.assertEqual([((0, 0), (1, 1), (2, 2))], 160 decompose([(0, 0), (1, 1), (2, 2)])) 161 self.assertEqual( 162 [((0, 0), (2, -2), (4, 0)), ((6, 2), (8, 8), (12, -12))], 163 decompose([(0, 0), (4, -4), (8, 8), (12, -12)])) 164 165 def test_decomposeQuadraticSegment(self): 166 decompose = decomposeQuadraticSegment 167 self.assertRaises(AssertionError, decompose, []) 168 self.assertRaises(AssertionError, decompose, [(0, 0)]) 169 self.assertEqual([((0,0), (4, 8))], decompose([(0, 0), (4, 8)])) 170 self.assertEqual([((0,0), (2, 4)), ((4, 8), (9, -9))], 171 decompose([(0, 0), (4, 8), (9, -9)])) 172 self.assertEqual( 173 [((0, 0), (2.0, 4.0)), ((4, 8), (6.5, -0.5)), ((9, -9), (10, 10))], 174 decompose([(0, 0), (4, 8), (9, -9), (10, 10)])) 175 176 177if __name__ == '__main__': 178 import sys 179 sys.exit(unittest.main()) 180