diff options
Diffstat (limited to 'Tests/pens/qu2cuPen_test.py')
-rw-r--r-- | Tests/pens/qu2cuPen_test.py | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/Tests/pens/qu2cuPen_test.py b/Tests/pens/qu2cuPen_test.py new file mode 100644 index 00000000..94449194 --- /dev/null +++ b/Tests/pens/qu2cuPen_test.py @@ -0,0 +1,253 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import unittest + +from fontTools.pens.qu2cuPen import Qu2CuPen +from fontTools.pens.recordingPen import RecordingPen +from textwrap import dedent +import pytest + +try: + from .utils import CUBIC_GLYPHS, QUAD_GLYPHS + from .utils import DummyGlyph + from .utils import DummyPen +except ImportError as e: + pytest.skip(str(e), allow_module_level=True) + +MAX_ERR = 1.0 + + +class _TestPenMixin(object): + """Collection of tests that are shared by both the SegmentPen and the + PointPen test cases, plus some helper methods. + Note: We currently don't have a PointPen. + """ + + maxDiff = None + + def diff(self, expected, actual): + import difflib + + expected = str(self.Glyph(expected)).splitlines(True) + actual = str(self.Glyph(actual)).splitlines(True) + diff = difflib.unified_diff( + expected, actual, fromfile="expected", tofile="actual" + ) + return "".join(diff) + + def convert_glyph(self, glyph, **kwargs): + # draw source glyph onto a new glyph using a Cu2Qu pen and return it + converted = self.Glyph() + pen = getattr(converted, self.pen_getter_name)() + cubicpen = self.Qu2CuPen(pen, MAX_ERR, all_cubic=True, **kwargs) + getattr(glyph, self.draw_method_name)(cubicpen) + return converted + + def expect_glyph(self, source, expected): + converted = self.convert_glyph(source) + self.assertNotEqual(converted, source) + if not converted.approx(expected): + print(self.diff(expected, converted)) + self.fail("converted glyph is different from expected") + + def test_convert_simple_glyph(self): + self.expect_glyph(QUAD_GLYPHS["a"], CUBIC_GLYPHS["a"]) + self.expect_glyph(QUAD_GLYPHS["A"], CUBIC_GLYPHS["A"]) + + def test_convert_composite_glyph(self): + source = CUBIC_GLYPHS["Aacute"] + converted = self.convert_glyph(source) + # components don't change after quadratic conversion + self.assertEqual(converted, source) + + def test_reverse_direction(self): + for name in ("a", "A", "Eacute"): + source = QUAD_GLYPHS[name] + normal_glyph = self.convert_glyph(source) + reversed_glyph = self.convert_glyph(source, reverse_direction=True) + + # the number of commands is the same, just their order is iverted + self.assertTrue(len(normal_glyph.outline), len(reversed_glyph.outline)) + self.assertNotEqual(normal_glyph, reversed_glyph) + + def test_stats(self): + stats = {} + for name in QUAD_GLYPHS.keys(): + source = QUAD_GLYPHS[name] + self.convert_glyph(source, stats=stats) + + self.assertTrue(stats) + self.assertTrue("2" in stats) + self.assertEqual(type(stats["2"]), int) + + def test_addComponent(self): + pen = self.Pen() + cubicpen = self.Qu2CuPen(pen, MAX_ERR) + cubicpen.addComponent("a", (1, 2, 3, 4, 5.0, 6.0)) + + # components are passed through without changes + self.assertEqual( + str(pen).splitlines(), + [ + "pen.addComponent('a', (1, 2, 3, 4, 5.0, 6.0))", + ], + ) + + +class TestQu2CuPen(unittest.TestCase, _TestPenMixin): + def __init__(self, *args, **kwargs): + super(TestQu2CuPen, self).__init__(*args, **kwargs) + self.Glyph = DummyGlyph + self.Pen = DummyPen + self.Qu2CuPen = Qu2CuPen + self.pen_getter_name = "getPen" + self.draw_method_name = "draw" + + def test_qCurveTo_1_point(self): + pen = DummyPen() + cubicpen = Qu2CuPen(pen, MAX_ERR) + cubicpen.moveTo((0, 0)) + cubicpen.qCurveTo((1, 1)) + cubicpen.closePath() + + self.assertEqual( + str(pen).splitlines(), + [ + "pen.moveTo((0, 0))", + "pen.qCurveTo((1, 1))", + "pen.closePath()", + ], + ) + + def test_qCurveTo_2_points(self): + pen = DummyPen() + cubicpen = Qu2CuPen(pen, MAX_ERR) + cubicpen.moveTo((0, 0)) + cubicpen.qCurveTo((1, 1), (2, 2)) + cubicpen.closePath() + + self.assertEqual( + str(pen).splitlines(), + [ + "pen.moveTo((0, 0))", + "pen.qCurveTo((1, 1), (2, 2))", + "pen.closePath()", + ], + ) + + def test_qCurveTo_3_points_no_conversion(self): + pen = DummyPen() + cubicpen = Qu2CuPen(pen, MAX_ERR) + cubicpen.moveTo((0, 0)) + cubicpen.qCurveTo((0, 3), (1, 3), (1, 0)) + cubicpen.closePath() + + self.assertEqual( + str(pen).splitlines(), + [ + "pen.moveTo((0, 0))", + "pen.qCurveTo((0, 3), (1, 3), (1, 0))", + "pen.closePath()", + ], + ) + + def test_qCurveTo_no_oncurve_points(self): + pen = DummyPen() + cubicpen = Qu2CuPen(pen, MAX_ERR) + cubicpen.qCurveTo((0, 0), (1, 0), (1, 1), (0, 1), None) + cubicpen.closePath() + + self.assertEqual( + str(pen).splitlines(), + ["pen.qCurveTo((0, 0), (1, 0), (1, 1), (0, 1), None)", "pen.closePath()"], + ) + + def test_curveTo_1_point(self): + pen = DummyPen() + cubicpen = Qu2CuPen(pen, MAX_ERR) + cubicpen.moveTo((0, 0)) + cubicpen.curveTo((1, 1)) + cubicpen.closePath() + + self.assertEqual( + str(pen).splitlines(), + [ + "pen.moveTo((0, 0))", + "pen.curveTo((1, 1))", + "pen.closePath()", + ], + ) + + def test_curveTo_2_points(self): + pen = DummyPen() + cubicpen = Qu2CuPen(pen, MAX_ERR) + cubicpen.moveTo((0, 0)) + cubicpen.curveTo((1, 1), (2, 2)) + cubicpen.closePath() + + self.assertEqual( + str(pen).splitlines(), + [ + "pen.moveTo((0, 0))", + "pen.curveTo((1, 1), (2, 2))", + "pen.closePath()", + ], + ) + + def test_curveTo_3_points(self): + pen = DummyPen() + cubicpen = Qu2CuPen(pen, MAX_ERR) + cubicpen.moveTo((0, 0)) + cubicpen.curveTo((1, 1), (2, 2), (3, 3)) + cubicpen.closePath() + + self.assertEqual( + str(pen).splitlines(), + [ + "pen.moveTo((0, 0))", + "pen.curveTo((1, 1), (2, 2), (3, 3))", + "pen.closePath()", + ], + ) + + def test_all_cubic(self): + inPen = RecordingPen() + inPen.value = [ + ("moveTo", ((1204, 347),)), + ("qCurveTo", ((1255, 347), (1323, 433), (1323, 467))), + ("qCurveTo", ((1323, 478), (1310, 492), (1302, 492))), + ("qCurveTo", ((1295, 492), (1289, 484))), + ("lineTo", ((1272, 461),)), + ("qCurveTo", ((1256, 439), (1221, 416), (1200, 416))), + ("qCurveTo", ((1181, 416), (1141, 440), (1141, 462))), + ("qCurveTo", ((1141, 484), (1190, 565), (1190, 594))), + ("qCurveTo", ((1190, 607), (1181, 634), (1168, 634))), + ("qCurveTo", ((1149, 634), (1146, 583), (1081, 496), (1081, 463))), + ("qCurveTo", ((1081, 417), (1164, 347), (1204, 347))), + ("closePath", ()), + ] + + outPen = RecordingPen() + q2cPen = Qu2CuPen(outPen, 1.0, all_cubic=True) + inPen.replay(q2cPen) + + print(outPen.value) + + assert not any(typ == "qCurveTo" for typ, _ in outPen.value) + + +if __name__ == "__main__": + unittest.main() |