diff --git a/Lib/fontTools/cffLib/specializer.py b/Lib/fontTools/cffLib/specializer.py index fe6873e77..e61ad26f8 100644 --- a/Lib/fontTools/cffLib/specializer.py +++ b/Lib/fontTools/cffLib/specializer.py @@ -446,9 +446,9 @@ def _convertToBlendCmds(args): i = 0 while i < num_args: arg = args[i] + i += 1 if not isinstance(arg, list): new_args.append(arg) - i += 1 stack_use += 1 else: prev_stack_use = stack_use @@ -458,21 +458,26 @@ def _convertToBlendCmds(args): # up to the max stack limit. num_sources = len(arg) - 1 blendlist = [arg] - i += 1 stack_use += 1 + num_sources # 1 for the num_blends arg - while (i < num_args) and isinstance(args[i], list): + + # if we are here, max stack is the CFF2 max stack. + # I use the CFF2 max stack limit here rather than + # the 'maxstack' chosen by the client, as the default + # maxstack may have been used unintentionally. For all + # the other operators, this just produces a little less + # optimization, but here it puts a hard (and low) limit + # on the number of source fonts that can be used. + # + # Make sure the stack depth does not exceed (maxstack - 1), so + # that subroutinizer can insert subroutine calls at any point. + while ( + (i < num_args) + and isinstance(args[i], list) + and stack_use + num_sources < maxStackLimit + ): blendlist.append(args[i]) i += 1 stack_use += num_sources - if stack_use + num_sources > maxStackLimit: - # if we are here, max stack is the CFF2 max stack. - # I use the CFF2 max stack limit here rather than - # the 'maxstack' chosen by the client, as the default - # maxstack may have been used unintentionally. For all - # the other operators, this just produces a little less - # optimization, but here it puts a hard (and low) limit - # on the number of source fonts that can be used. - break # blendList now contains as many single blend tuples as can be # combined without exceeding the CFF2 stack limit. num_blends = len(blendlist) @@ -504,6 +509,19 @@ def _addArgs(a, b): return a + b +def _argsStackUse(args): + stackLen = 0 + maxLen = 0 + for arg in args: + if type(arg) is list: + # Blended arg + maxLen = max(maxLen, stackLen + _argsStackUse(arg)) + stackLen += arg[-1] + else: + stackLen += 1 + return max(stackLen, maxLen) + + def specializeCommands( commands, ignoreErrors=False, @@ -746,7 +764,7 @@ def specializeCommands( # Make sure the stack depth does not exceed (maxstack - 1), so # that subroutinizer can insert subroutine calls at any point. - if new_op and len(args1) + len(args2) < maxstack: + if new_op and _argsStackUse(args1) + _argsStackUse(args2) < maxstack: commands[i - 1] = (new_op, args1 + args2) del commands[i] diff --git a/Tests/cffLib/specializer_test.py b/Tests/cffLib/specializer_test.py index 6a8e01907..08c137ada 100644 --- a/Tests/cffLib/specializer_test.py +++ b/Tests/cffLib/specializer_test.py @@ -1,3 +1,4 @@ +from fontTools.cffLib import maxStackLimit as maxStack from fontTools.cffLib.specializer import ( programToString, stringToProgram, @@ -10,973 +11,593 @@ from fontTools.cffLib.specializer import ( ) from fontTools.ttLib import TTFont import os -import unittest +import pytest from fontTools.misc.testTools import parseXML, DataFilesHandler -# TODO -# https://github.com/fonttools/fonttools/pull/959#commitcomment-22059841 -# Maybe we should make these data driven. Each entry will have an input string, -# and a generalized and specialized. For the latter two, if they are None, they -# are considered equal to the input. Then we can do roundtripping tests as well... -# There are a few other places (aosp tests for example) where we generate tests -# from data. - -def get_generalized_charstr(charstr, **kwargs): +def charstr_generalize(charstr, **kwargs): return programToString(generalizeProgram(stringToProgram(charstr), **kwargs)) -def get_specialized_charstr(charstr, **kwargs): +def charstr_specialize(charstr, **kwargs): return programToString(specializeProgram(stringToProgram(charstr), **kwargs)) -class CFFGeneralizeProgramTest(unittest.TestCase): - def __init__(self, methodName): - unittest.TestCase.__init__(self, methodName) - # Python 3 renamed assertRaisesRegexp to assertRaisesRegex, - # and fires deprecation warnings if a program uses the old name. - if not hasattr(self, "assertRaisesRegex"): - self.assertRaisesRegex = self.assertRaisesRegexp - - # no arguments/operands - def test_rmoveto_none(self): - test_charstr = "rmoveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_hmoveto_none(self): - test_charstr = "hmoveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_vmoveto_none(self): - test_charstr = "vmoveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_rlineto_none(self): - test_charstr = "rlineto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_hlineto_none(self): - test_charstr = "hlineto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_vlineto_none(self): - test_charstr = "vlineto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_rrcurveto_none(self): - test_charstr = "rrcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_hhcurveto_none(self): - test_charstr = "hhcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_vvcurveto_none(self): - test_charstr = "vvcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_hvcurveto_none(self): - test_charstr = "hvcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_vhcurveto_none(self): - test_charstr = "vhcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_rcurveline_none(self): - test_charstr = "rcurveline" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - def test_rlinecurve_none(self): - test_charstr = "rlinecurve" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_generalized_charstr(test_charstr) - - # rmoveto - def test_rmoveto_zero(self): - test_charstr = "0 0 rmoveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rmoveto_zero_width(self): - test_charstr = "100 0 0 rmoveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rmoveto(self): - test_charstr = ".55 -.8 rmoveto" - xpct_charstr = "0.55 -0.8 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rmoveto_width(self): - test_charstr = "100.5 50 -5.8 rmoveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # hmoveto - def test_hmoveto_zero(self): - test_charstr = "0 hmoveto" - xpct_charstr = "0 0 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hmoveto_zero_width(self): - test_charstr = "100 0 hmoveto" - xpct_charstr = "100 0 0 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hmoveto(self): - test_charstr = ".67 hmoveto" - xpct_charstr = "0.67 0 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hmoveto_width(self): - test_charstr = "100 -70 hmoveto" - xpct_charstr = "100 -70 0 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # vmoveto - def test_vmoveto_zero(self): - test_charstr = "0 vmoveto" - xpct_charstr = "0 0 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vmoveto_zero_width(self): - test_charstr = "100 0 vmoveto" - xpct_charstr = "100 0 0 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vmoveto(self): - test_charstr = "-.24 vmoveto" - xpct_charstr = "0 -0.24 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vmoveto_width(self): - test_charstr = "100 44 vmoveto" - xpct_charstr = "100 0 44 rmoveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # rlineto - def test_rlineto_zero(self): - test_charstr = "0 0 rlineto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rlineto_zero_mult(self): - test_charstr = "0 0 0 0 0 0 rlineto" - xpct_charstr = ("0 0 rlineto " * 3).rstrip() - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rlineto(self): - test_charstr = ".55 -.8 rlineto" - xpct_charstr = "0.55 -0.8 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rlineto_mult(self): - test_charstr = ".55 -.8 .55 -.8 .55 -.8 rlineto" - xpct_charstr = ("0.55 -0.8 rlineto " * 3).rstrip() - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # hlineto - def test_hlineto_zero(self): - test_charstr = "0 hlineto" - xpct_charstr = "0 0 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hlineto_zero_mult(self): - test_charstr = "0 0 0 0 hlineto" - xpct_charstr = ("0 0 rlineto " * 4).rstrip() - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hlineto(self): - test_charstr = ".67 hlineto" - xpct_charstr = "0.67 0 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hlineto_mult(self): - test_charstr = ".67 -6.0 .67 hlineto" - xpct_charstr = "0.67 0 rlineto 0 -6.0 rlineto 0.67 0 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # vlineto - def test_vlineto_zero(self): - test_charstr = "0 vlineto" - xpct_charstr = "0 0 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vlineto_zero_mult(self): - test_charstr = "0 0 0 vlineto" - xpct_charstr = ("0 0 rlineto " * 3).rstrip() - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vlineto(self): - test_charstr = "-.24 vlineto" - xpct_charstr = "0 -0.24 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vlineto_mult(self): - test_charstr = "-.24 +50 30 -4 vlineto" - xpct_charstr = "0 -0.24 rlineto 50 0 rlineto 0 30 rlineto -4 0 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # rrcurveto - def test_rrcurveto(self): - test_charstr = "-1 56 -2 57 -1 57 rrcurveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_mult(self): - test_charstr = "-30 8 -36 15 -37 22 44 54 31 61 22 68 rrcurveto" - xpct_charstr = "-30 8 -36 15 -37 22 rrcurveto 44 54 31 61 22 68 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_d3947b8(self): - test_charstr = "1 2 3 4 5 0 rrcurveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_v0_0h_h0(self): - test_charstr = "0 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = ( - "0 10 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_h0_0h_h0(self): - test_charstr = "10 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = ( - "10 0 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_00_0h_h0(self): - test_charstr = "0 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = ( - "0 0 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_r0_0h_h0(self): - test_charstr = "10 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = ( - "10 10 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_v0_0v_v0(self): - test_charstr = "0 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = ( - "0 10 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_h0_0v_v0(self): - test_charstr = "10 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = ( - "10 0 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_00_0v_v0(self): - test_charstr = "0 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = ( - "0 0 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_r0_0v_v0(self): - test_charstr = "10 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = ( - "10 10 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # hhcurveto - def test_hhcurveto_4(self): - test_charstr = "10 30 0 10 hhcurveto" - xpct_charstr = "10 0 30 0 10 0 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_5(self): - test_charstr = "40 -38 -60 41 -91 hhcurveto" - xpct_charstr = "-38 40 -60 41 -91 0 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_4_4(self): - test_charstr = "43 23 25 18 29 56 42 -84 hhcurveto" - xpct_charstr = "43 0 23 25 18 0 rrcurveto 29 0 56 42 -84 0 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_5_4(self): - test_charstr = "43 23 25 18 29 56 42 -84 79 hhcurveto" - xpct_charstr = "23 43 25 18 29 0 rrcurveto 56 0 42 -84 79 0 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_4_4_4(self): - test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hhcurveto" - xpct_charstr = ( - "1 0 2 3 4 0 rrcurveto 5 0 6 7 8 0 rrcurveto 9 0 10 11 12 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_5_4_4(self): - test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 hhcurveto" - xpct_charstr = ( - "2 1 3 4 5 0 rrcurveto 6 0 7 8 9 0 rrcurveto 10 0 11 12 13 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # vvcurveto - def test_vvcurveto_4(self): - test_charstr = "61 6 52 68 vvcurveto" - xpct_charstr = "0 61 6 52 0 68 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_5(self): - test_charstr = "61 38 35 56 72 vvcurveto" - xpct_charstr = "61 38 35 56 0 72 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_4_4(self): - test_charstr = "-84 -88 -30 -90 -13 19 23 -11 vvcurveto" - xpct_charstr = "0 -84 -88 -30 0 -90 rrcurveto 0 -13 19 23 0 -11 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_5_4(self): - test_charstr = "43 12 17 32 65 68 -6 52 61 vvcurveto" - xpct_charstr = "43 12 17 32 0 65 rrcurveto 0 68 -6 52 0 61 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_4_4_4(self): - test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vvcurveto" - xpct_charstr = ( - "0 1 2 3 0 4 rrcurveto 0 5 6 7 0 8 rrcurveto 0 9 10 11 0 12 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_5_4_4(self): - test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 vvcurveto" - xpct_charstr = ( - "1 2 3 4 0 5 rrcurveto 0 6 7 8 0 9 rrcurveto 0 10 11 12 0 13 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # hvcurveto - def test_hvcurveto_4(self): - test_charstr = "1 2 3 4 hvcurveto" - xpct_charstr = "1 0 2 3 0 4 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_5(self): - test_charstr = "57 44 22 40 34 hvcurveto" - xpct_charstr = "57 0 44 22 34 40 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4(self): - test_charstr = "65 33 -19 -45 -45 -29 -25 -71 hvcurveto" - xpct_charstr = "65 0 33 -19 0 -45 rrcurveto 0 -45 -29 -25 -71 0 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_5(self): - test_charstr = "97 69 41 86 58 -36 34 -64 11 hvcurveto" - xpct_charstr = "97 0 69 41 0 86 rrcurveto 0 58 -36 34 -64 11 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_4(self): - test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hvcurveto" - xpct_charstr = ( - "1 0 2 3 0 4 rrcurveto 0 5 6 7 8 0 rrcurveto 9 0 10 11 0 12 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_5(self): - test_charstr = "-124 -79 104 165 163 82 102 124 56 43 -25 -37 35 hvcurveto" - xpct_charstr = "-124 0 -79 104 0 165 rrcurveto 0 163 82 102 124 0 rrcurveto 56 0 43 -25 35 -37 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_4_4(self): - test_charstr = ( - "32 25 22 32 31 -25 22 -32 -32 -25 -22 -31 -32 25 -22 32 hvcurveto" - ) - xpct_charstr = "32 0 25 22 0 32 rrcurveto 0 31 -25 22 -32 0 rrcurveto -32 0 -25 -22 0 -31 rrcurveto 0 -32 25 -22 32 0 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_4_4_5(self): - test_charstr = "-170 -128 111 195 234 172 151 178 182 95 -118 -161 -130 -71 -77 -63 -55 -19 38 79 20 hvcurveto" - xpct_charstr = "-170 0 -128 111 0 195 rrcurveto 0 234 172 151 178 0 rrcurveto 182 0 95 -118 0 -161 rrcurveto 0 -130 -71 -77 -63 0 rrcurveto -55 0 -19 38 20 79 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # vhcurveto - def test_vhcurveto_4(self): - test_charstr = "-57 43 -30 53 vhcurveto" - xpct_charstr = "0 -57 43 -30 53 0 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_5(self): - test_charstr = "41 -27 19 -46 11 vhcurveto" - xpct_charstr = "0 41 -27 19 -46 11 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4(self): - test_charstr = "1 2 3 4 5 6 7 8 vhcurveto" - xpct_charstr = "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_5(self): - test_charstr = "-64 -23 -25 -45 -30 -24 14 33 -19 vhcurveto" - xpct_charstr = "0 -64 -23 -25 -45 0 rrcurveto -30 0 -24 14 -19 33 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4_4(self): - test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vhcurveto" - xpct_charstr = ( - "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto 0 9 10 11 12 0 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4_5(self): - test_charstr = "108 59 81 98 99 59 -81 -108 -100 -46 -66 -63 -47 vhcurveto" - xpct_charstr = "0 108 59 81 98 0 rrcurveto 99 0 59 -81 0 -108 rrcurveto 0 -100 -46 -66 -63 -47 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4_4_5(self): - test_charstr = "60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto" - xpct_charstr = "0 60 -26 37 -43 0 rrcurveto -33 0 -28 -22 0 -36 rrcurveto 0 -37 27 -20 32 0 rrcurveto 3 0 4 0 3 1 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # rcurveline - def test_rcurveline_6_2(self): - test_charstr = "21 -76 21 -72 24 -73 31 -100 rcurveline" - xpct_charstr = "21 -76 21 -72 24 -73 rrcurveto 31 -100 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rcurveline_6_6_2(self): - test_charstr = "-73 80 -80 121 -49 96 60 65 55 41 54 17 -8 78 rcurveline" - xpct_charstr = ( - "-73 80 -80 121 -49 96 rrcurveto 60 65 55 41 54 17 rrcurveto -8 78 rlineto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rcurveline_6_6_6_2(self): - test_charstr = ( - "1 64 10 51 29 39 15 21 15 20 15 18 47 -89 63 -98 52 -59 91 8 rcurveline" - ) - xpct_charstr = "1 64 10 51 29 39 rrcurveto 15 21 15 20 15 18 rrcurveto 47 -89 63 -98 52 -59 rrcurveto 91 8 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rcurveline_6_6_6_6_2(self): - test_charstr = "1 64 10 51 29 39 15 21 15 20 15 18 46 -88 63 -97 52 -59 -38 -57 -49 -62 -52 -54 96 -8 rcurveline" - xpct_charstr = "1 64 10 51 29 39 rrcurveto 15 21 15 20 15 18 rrcurveto 46 -88 63 -97 52 -59 rrcurveto -38 -57 -49 -62 -52 -54 rrcurveto 96 -8 rlineto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # rlinecurve - def test_rlinecurve_2_6(self): - test_charstr = "21 -76 21 -72 24 -73 31 -100 rlinecurve" - xpct_charstr = "21 -76 rlineto 21 -72 24 -73 31 -100 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rlinecurve_2_2_6(self): - test_charstr = "-73 80 -80 121 -49 96 60 65 55 41 rlinecurve" - xpct_charstr = "-73 80 rlineto -80 121 rlineto -49 96 60 65 55 41 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rlinecurve_2_2_2_6(self): - test_charstr = "1 64 10 51 29 39 15 21 15 20 15 18 rlinecurve" - xpct_charstr = ( - "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 15 20 15 18 rrcurveto" - ) - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - def test_rlinecurve_2_2_2_2_6(self): - test_charstr = "1 64 10 51 29 39 15 21 15 20 15 18 46 -88 rlinecurve" - xpct_charstr = "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 rlineto 15 20 15 18 46 -88 rrcurveto" - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # hstem/vstem - def test_hstem_vstem(self): - test_charstr = "95 0 58 542 60 hstem 89 65 344 67 vstem 89 45 rmoveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # hstemhm/vstemhm - def test_hstemhm_vstemhm(self): - test_charstr = "-16 577 60 24 60 hstemhm 98 55 236 55 vstemhm 343 577 rmoveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # hintmask/cntrmask - def test_hintmask_cntrmask(self): - test_charstr = "52 80 153 61 4 83 -71.5 71.5 hintmask 11011100 94 119 216 119 216 119 cntrmask 1110000 154 -12 rmoveto" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # endchar - def test_endchar(self): - test_charstr = "-255 319 rmoveto 266 57 rlineto endchar" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - # xtra - def test_xtra(self): - test_charstr = "-255 319 rmoveto 266 57 rlineto xtra 90 34" - xpct_charstr = test_charstr - self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr) - - -class CFFSpecializeProgramTest(unittest.TestCase): - def __init__(self, methodName): - unittest.TestCase.__init__(self, methodName) - # Python 3 renamed assertRaisesRegexp to assertRaisesRegex, - # and fires deprecation warnings if a program uses the old name. - if not hasattr(self, "assertRaisesRegex"): - self.assertRaisesRegex = self.assertRaisesRegexp - - # no arguments/operands - def test_rmoveto_none(self): - test_charstr = "rmoveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_hmoveto_none(self): - test_charstr = "hmoveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_vmoveto_none(self): - test_charstr = "vmoveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_rlineto_none(self): - test_charstr = "rlineto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_hlineto_none(self): - test_charstr = "hlineto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_vlineto_none(self): - test_charstr = "vlineto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_rrcurveto_none(self): - test_charstr = "rrcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_hhcurveto_none(self): - test_charstr = "hhcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_vvcurveto_none(self): - test_charstr = "vvcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_hvcurveto_none(self): - test_charstr = "hvcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_vhcurveto_none(self): - test_charstr = "vhcurveto" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_rcurveline_none(self): - test_charstr = "rcurveline" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - def test_rlinecurve_none(self): - test_charstr = "rlinecurve" - with self.assertRaisesRegex(ValueError, r"\[\]"): - get_specialized_charstr(test_charstr) - - # rmoveto - def test_rmoveto_zero(self): - test_charstr = "0 0 rmoveto" - xpct_charstr = "0 hmoveto" - self.assertEqual( - get_specialized_charstr(test_charstr, generalizeFirst=False), xpct_charstr - ) - - def test_rmoveto_zero_mult(self): - test_charstr = "0 0 rmoveto " * 3 - xpct_charstr = "0 hmoveto" - self.assertEqual( - get_specialized_charstr(test_charstr, generalizeFirst=False), xpct_charstr - ) - - def test_rmoveto_zero_width(self): - test_charstr = "100 0 0 rmoveto" - xpct_charstr = "100 0 hmoveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rmoveto(self): - test_charstr = ".55 -.8 rmoveto" - xpct_charstr = "0.55 -0.8 rmoveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rmoveto_mult(self): - test_charstr = "55 -8 rmoveto " * 3 - xpct_charstr = "165 -24 rmoveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rmoveto_width(self): - test_charstr = "100.5 50 -5.8 rmoveto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - # rlineto - def test_rlineto_zero(self): - test_charstr = "0 0 rlineto" - xpct_charstr = "" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rlineto_zero_mult(self): - test_charstr = "0 0 rlineto " * 3 - xpct_charstr = "" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rlineto(self): - test_charstr = ".55 -.8 rlineto" - xpct_charstr = "0.55 -0.8 rlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rlineto_mult(self): - test_charstr = ".55 -.8 rlineto " * 3 - xpct_charstr = "0.55 -0.8 0.55 -0.8 0.55 -0.8 rlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hlineto(self): - test_charstr = ".67 0 rlineto" - xpct_charstr = "0.67 hlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hlineto_zero_mult(self): - test_charstr = "62 0 rlineto " * 3 - xpct_charstr = "186 hlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hlineto_mult(self): - test_charstr = ".67 0 rlineto 0 -6.0 rlineto .67 0 rlineto" - xpct_charstr = "0.67 -6.0 0.67 hlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vlineto(self): - test_charstr = "0 -.24 rlineto" - xpct_charstr = "-0.24 vlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vlineto_zero_mult(self): - test_charstr = "0 -24 rlineto " * 3 - xpct_charstr = "-72 vlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vlineto_mult(self): - test_charstr = "0 -.24 rlineto +50 0 rlineto 0 30 rlineto -4 0 rlineto" - xpct_charstr = "-0.24 50 30 -4 vlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_0lineto_peephole(self): - test_charstr = "1 2 0 0 3 4 rlineto" - xpct_charstr = "1 2 3 4 rlineto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hlineto_peephole(self): - test_charstr = "1 2 5 0 3 4 rlineto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vlineto_peephole(self): - test_charstr = "1 2 0 5 3 4 rlineto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - # rrcurveto - def test_rrcurveto(self): - test_charstr = "-1 56 -2 57 -1 57 rrcurveto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_mult(self): - test_charstr = "-30 8 -36 15 -37 22 rrcurveto 44 54 31 61 22 68 rrcurveto" - xpct_charstr = "-30 8 -36 15 -37 22 44 54 31 61 22 68 rrcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_d3947b8(self): - test_charstr = "1 2 3 4 5 0 rrcurveto" - xpct_charstr = "2 1 3 4 5 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_4(self): - test_charstr = "10 0 30 0 10 0 rrcurveto" - xpct_charstr = "10 30 0 10 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_5(self): - test_charstr = "-38 40 -60 41 -91 0 rrcurveto" - xpct_charstr = "40 -38 -60 41 -91 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_4_4(self): - test_charstr = "43 0 23 25 18 0 rrcurveto 29 0 56 42 -84 0 rrcurveto" - xpct_charstr = "43 23 25 18 29 56 42 -84 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_5_4(self): - test_charstr = "23 43 25 18 29 0 rrcurveto 56 0 42 -84 79 0 rrcurveto" - xpct_charstr = "43 23 25 18 29 56 42 -84 79 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_4_4_4(self): - test_charstr = ( - "1 0 2 3 4 0 rrcurveto 5 0 6 7 8 0 rrcurveto 9 0 10 11 12 0 rrcurveto" - ) - xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_mult_5_4_4(self): - test_charstr = ( - "2 1 3 4 5 0 rrcurveto 6 0 7 8 9 0 rrcurveto 10 0 11 12 13 0 rrcurveto" - ) - xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_4(self): - test_charstr = "0 61 6 52 0 68 rrcurveto" - xpct_charstr = "61 6 52 68 vvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_5(self): - test_charstr = "61 38 35 56 0 72 rrcurveto" - xpct_charstr = "61 38 35 56 72 vvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_4_4(self): - test_charstr = "0 -84 -88 -30 0 -90 rrcurveto 0 -13 19 23 0 -11 rrcurveto" - xpct_charstr = "-84 -88 -30 -90 -13 19 23 -11 vvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_5_4(self): - test_charstr = "43 12 17 32 0 65 rrcurveto 0 68 -6 52 0 61 rrcurveto" - xpct_charstr = "43 12 17 32 65 68 -6 52 61 vvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_4_4_4(self): - test_charstr = ( - "0 1 2 3 0 4 rrcurveto 0 5 6 7 0 8 rrcurveto 0 9 10 11 0 12 rrcurveto" - ) - xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_mult_5_4_4(self): - test_charstr = ( - "1 2 3 4 0 5 rrcurveto 0 6 7 8 0 9 rrcurveto 0 10 11 12 0 13 rrcurveto" - ) - xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 vvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4(self): - test_charstr = "1 0 2 3 0 4 rrcurveto" - xpct_charstr = "1 2 3 4 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_5(self): - test_charstr = "57 0 44 22 34 40 rrcurveto" - xpct_charstr = "57 44 22 40 34 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4(self): - test_charstr = "65 0 33 -19 0 -45 rrcurveto 0 -45 -29 -25 -71 0 rrcurveto" - xpct_charstr = "65 33 -19 -45 -45 -29 -25 -71 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_5(self): - test_charstr = "97 0 69 41 0 86 rrcurveto 0 58 -36 34 -64 11 rrcurveto" - xpct_charstr = "97 69 41 86 58 -36 34 -64 11 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_4(self): - test_charstr = ( - "1 0 2 3 0 4 rrcurveto 0 5 6 7 8 0 rrcurveto 9 0 10 11 0 12 rrcurveto" - ) - xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_5(self): - test_charstr = "-124 0 -79 104 0 165 rrcurveto 0 163 82 102 124 0 rrcurveto 56 0 43 -25 35 -37 rrcurveto" - xpct_charstr = "-124 -79 104 165 163 82 102 124 56 43 -25 -37 35 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_4_4(self): - test_charstr = "32 0 25 22 0 32 rrcurveto 0 31 -25 22 -32 0 rrcurveto -32 0 -25 -22 0 -31 rrcurveto 0 -32 25 -22 32 0 rrcurveto" - xpct_charstr = ( - "32 25 22 32 31 -25 22 -32 -32 -25 -22 -31 -32 25 -22 32 hvcurveto" - ) - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_4_4_4_4_5(self): - test_charstr = "-170 0 -128 111 0 195 rrcurveto 0 234 172 151 178 0 rrcurveto 182 0 95 -118 0 -161 rrcurveto 0 -130 -71 -77 -63 0 rrcurveto -55 0 -19 38 20 79 rrcurveto" - xpct_charstr = "-170 -128 111 195 234 172 151 178 182 95 -118 -161 -130 -71 -77 -63 -55 -19 38 79 20 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4(self): - test_charstr = "0 -57 43 -30 53 0 rrcurveto" - xpct_charstr = "-57 43 -30 53 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_5(self): - test_charstr = "0 41 -27 19 -46 11 rrcurveto" - xpct_charstr = "41 -27 19 -46 11 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4(self): - test_charstr = "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto" - xpct_charstr = "1 2 3 4 5 6 7 8 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_5(self): - test_charstr = "0 -64 -23 -25 -45 0 rrcurveto -30 0 -24 14 -19 33 rrcurveto" - xpct_charstr = "-64 -23 -25 -45 -30 -24 14 33 -19 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4_4(self): - test_charstr = ( - "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto 0 9 10 11 12 0 rrcurveto" - ) - xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4_5(self): - test_charstr = "0 108 59 81 98 0 rrcurveto 99 0 59 -81 0 -108 rrcurveto 0 -100 -46 -66 -63 -47 rrcurveto" - xpct_charstr = "108 59 81 98 99 59 -81 -108 -100 -46 -66 -63 -47 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_4_4_4_5(self): - test_charstr = "0 60 -26 37 -43 0 rrcurveto -33 0 -28 -22 0 -36 rrcurveto 0 -37 27 -20 32 0 rrcurveto 3 0 4 0 3 1 rrcurveto" - xpct_charstr = "60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_v0_0h_h0(self): - test_charstr = "0 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = "10 1 2 0 0 1 2 1 1 3 4 0 vhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_h0_0h_h0(self): - test_charstr = "10 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = "10 1 2 0 hhcurveto 0 1 2 1 1 3 4 0 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_00_0h_h0(self): - test_charstr = "0 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = "1 2 rlineto 0 1 2 1 1 3 4 0 hvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_r0_0h_h0(self): - test_charstr = "10 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto" - xpct_charstr = "10 10 1 2 0 0 1 2 1 1 3 4 0 vvcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_v0_0v_v0(self): - test_charstr = "0 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = "10 1 2 0 vhcurveto 0 1 2 1 1 3 4 0 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_h0_0v_v0(self): - test_charstr = "10 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = "10 1 2 0 0 1 2 1 1 3 4 0 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_00_0v_v0(self): - test_charstr = "0 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = "1 2 rlineto 0 1 2 1 1 3 4 0 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rrcurveto_r0_0v_v0(self): - test_charstr = "10 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto" - xpct_charstr = "10 10 1 2 0 0 1 2 1 1 3 4 0 hhcurveto" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hhcurveto_peephole(self): - test_charstr = "1 2 3 4 5 6 1 2 3 4 5 0 1 2 3 4 5 6 rrcurveto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vvcurveto_peephole(self): - test_charstr = "1 2 3 4 5 6 1 2 3 4 0 6 1 2 3 4 5 6 rrcurveto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_hvcurveto_peephole(self): - test_charstr = "1 2 3 4 5 6 1 0 3 4 5 6 1 2 3 4 5 6 rrcurveto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_vhcurveto_peephole(self): - test_charstr = "1 2 3 4 5 6 0 2 3 4 5 6 1 2 3 4 5 6 rrcurveto" - xpct_charstr = test_charstr - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rcurveline_6_2(self): - test_charstr = "21 -76 21 -72 24 -73 rrcurveto 31 -100 rlineto" - xpct_charstr = "21 -76 21 -72 24 -73 31 -100 rcurveline" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rcurveline_6_6_2(self): - test_charstr = ( - "-73 80 -80 121 -49 96 rrcurveto 60 65 55 41 54 17 rrcurveto -8 78 rlineto" - ) - xpct_charstr = "-73 80 -80 121 -49 96 60 65 55 41 54 17 -8 78 rcurveline" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rcurveline_6_6_6_2(self): - test_charstr = "1 64 10 51 29 39 rrcurveto 15 21 15 20 15 18 rrcurveto 47 -89 63 -98 52 -59 rrcurveto 91 8 rlineto" - xpct_charstr = ( - "1 64 10 51 29 39 15 21 15 20 15 18 47 -89 63 -98 52 -59 91 8 rcurveline" - ) - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rlinecurve_2_6(self): - test_charstr = "21 -76 rlineto 21 -72 24 -73 31 -100 rrcurveto" - xpct_charstr = "21 -76 21 -72 24 -73 31 -100 rlinecurve" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rlinecurve_2_2_6(self): - test_charstr = "-73 80 rlineto -80 121 rlineto -49 96 60 65 55 41 rrcurveto" - xpct_charstr = "-73 80 -80 121 -49 96 60 65 55 41 rlinecurve" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) - - def test_rlinecurve_2_2_2_6(self): - test_charstr = ( - "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 15 20 15 18 rrcurveto" - ) - xpct_charstr = "1 64 10 51 29 39 15 21 15 20 15 18 rlinecurve" - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) +def charstr_stack_use(charstr, getNumRegions=None): + program = stringToProgram(charstr) + + vsindex = None + maxStack = 0 + stack = [] + for token in program: + if token == vsindex: + vsindex = stack[-1] + stack = [] + elif token == "blend": + numBlends = stack[-1] + numRegions = getNumRegions(vsindex) + numOperandsToPop = 1 + numBlends * numRegions + stack[-numOperandsToPop:] = [] + elif type(token) is str: + stack = [] + else: + stack.append(token) + maxStack = max(maxStack, len(stack)) + + return maxStack + + +class CFFGeneralizeProgramTest: + @pytest.mark.parametrize( + "charstr", + [ + # no arguments/operands + ("rmoveto"), # test_rmoveto_none + ("hmoveto"), # test_hmoveto_none + ("vmoveto"), # test_vmoveto_none + ("rlineto"), # test_rlineto_none + ("hlineto"), # test_hlineto_none + ("vlineto"), # test_vlineto_none + ("rrcurveto"), # test_rrcurveto_none + ("hhcurveto"), # test_hhcurveto_none + ("vvcurveto"), # test_vvcurveto_none + ("hvcurveto"), # test_hvcurveto_none + ("vhcurveto"), # test_vhcurveto_none + ("rcurveline"), # test_rcurveline_none + ("rlinecurve"), # test_rlinecurve_none + ], + ) + def test_raises(self, charstr): + try: + charstr_generalize(charstr) + except ValueError: + return + raise AssertionError("Expected to raise ValueError, but didn't.", charstr) + + @pytest.mark.parametrize( + "charstr, expected", + [ + # rmoveto + ("0 0 rmoveto", None), # test_rmoveto_zero + ("100 0 0 rmoveto", None), # test_rmoveto_zero_width + (".55 -.8 rmoveto", "0.55 -0.8 rmoveto"), # test_rmoveto + ("100.5 50 -5.8 rmoveto", None), # test_rmoveto_width + # hmoveto + ("0 hmoveto", "0 0 rmoveto"), # test_hmoveto_zero + ("100 0 hmoveto", "100 0 0 rmoveto"), # test_hmoveto_zero_width + (".67 hmoveto", "0.67 0 rmoveto"), # test_hmoveto + ("100 -70 hmoveto", "100 -70 0 rmoveto"), # test_hmoveto_width + # vmoveto + ("0 vmoveto", "0 0 rmoveto"), # test_vmoveto_zero + ("100 0 vmoveto", "100 0 0 rmoveto"), # test_vmoveto_zero_width + ("-.24 vmoveto", "0 -0.24 rmoveto"), # test_vmoveto + ("100 44 vmoveto", "100 0 44 rmoveto"), # test_vmoveto_width + # rlineto + ("0 0 rlineto", None), # test_rlineto_zero + ( # test_rlineto_zero_mult + "0 0 0 0 0 0 rlineto", + "0 0 rlineto " * 3, + ), + (".55 -.8 rlineto", "0.55 -0.8 rlineto"), # test_rlineto + ( # test_rlineto_mult + ".55 -.8 .55 -.8 .55 -.8 rlineto", + "0.55 -0.8 rlineto " * 3, + ), + # hlineto + ("0 hlineto", "0 0 rlineto"), # test_hlineto_zero + ( # test_hlineto_zero_mult + "0 0 0 0 hlineto", + "0 0 rlineto " * 4, + ), + (".67 hlineto", "0.67 0 rlineto"), # test_hlineto + ( # test_hlineto_mult + ".67 -6.0 .67 hlineto", + "0.67 0 rlineto 0 -6.0 rlineto 0.67 0 rlineto", + ), + # vlineto + ("0 vlineto", "0 0 rlineto"), # test_vlineto_zero + ("0 0 0 vlineto", "0 0 rlineto " * 3), # test_vlineto_zero_mult + ("-.24 vlineto", "0 -0.24 rlineto"), # test_vlineto + ( # test_vlineto_mult + "-.24 +50 30 -4 vlineto", + "0 -0.24 rlineto 50 0 rlineto 0 30 rlineto -4 0 rlineto", + ), + # rrcurveto + ("-1 56 -2 57 -1 57 rrcurveto", None), # test_rrcurveto + ( # test_rrcurveto_mult + "-30 8 -36 15 -37 22 44 54 31 61 22 68 rrcurveto", + "-30 8 -36 15 -37 22 rrcurveto 44 54 31 61 22 68 rrcurveto", + ), + ("1 2 3 4 5 0 rrcurveto", None), # test_rrcurveto_d3947b8 + ( # test_rrcurveto_v0_0h_h0 + "0 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "0 10 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto", + ), + ( # test_rrcurveto_h0_0h_h0 + "10 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "10 0 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto", + ), + ( # test_rrcurveto_00_0h_h0 + "0 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "0 0 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto", + ), + ( # test_rrcurveto_r0_0h_h0 + "10 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "10 10 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto", + ), + ( # test_rrcurveto_v0_0v_v0 + "0 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "0 10 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto", + ), + ( # test_rrcurveto_h0_0v_v0 + "10 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "10 0 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto", + ), + ( # test_rrcurveto_00_0v_v0 + "0 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "0 0 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto", + ), + ( # test_rrcurveto_r0_0v_v0 + "10 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "10 10 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto", + ), + # hhcurveto + ("10 30 0 10 hhcurveto", "10 0 30 0 10 0 rrcurveto"), # test_hhcurveto_4 + ( # test_hhcurveto_5 + "40 -38 -60 41 -91 hhcurveto", + "-38 40 -60 41 -91 0 rrcurveto", + ), + ( # test_hhcurveto_mult_4_4 + "43 23 25 18 29 56 42 -84 hhcurveto", + "43 0 23 25 18 0 rrcurveto 29 0 56 42 -84 0 rrcurveto", + ), + ( # test_hhcurveto_mult_5_4 + "43 23 25 18 29 56 42 -84 79 hhcurveto", + "23 43 25 18 29 0 rrcurveto 56 0 42 -84 79 0 rrcurveto", + ), + ( # test_hhcurveto_mult_4_4_4 + "1 2 3 4 5 6 7 8 9 10 11 12 hhcurveto", + "1 0 2 3 4 0 rrcurveto 5 0 6 7 8 0 rrcurveto 9 0 10 11 12 0 rrcurveto", + ), + ( # test_hhcurveto_mult_5_4_4 + "1 2 3 4 5 6 7 8 9 10 11 12 13 hhcurveto", + "2 1 3 4 5 0 rrcurveto 6 0 7 8 9 0 rrcurveto 10 0 11 12 13 0 rrcurveto", + ), + # vvcurveto + ("61 6 52 68 vvcurveto", "0 61 6 52 0 68 rrcurveto"), # test_vvcurveto_4 + ( # test_vvcurveto_5 + "61 38 35 56 72 vvcurveto", + "61 38 35 56 0 72 rrcurveto", + ), + ( # test_vvcurveto_mult_4_4 + "-84 -88 -30 -90 -13 19 23 -11 vvcurveto", + "0 -84 -88 -30 0 -90 rrcurveto 0 -13 19 23 0 -11 rrcurveto", + ), + ( # test_vvcurveto_mult_5_4 + "43 12 17 32 65 68 -6 52 61 vvcurveto", + "43 12 17 32 0 65 rrcurveto 0 68 -6 52 0 61 rrcurveto", + ), + ( # test_vvcurveto_mult_4_4_4 + "1 2 3 4 5 6 7 8 9 10 11 12 vvcurveto", + "0 1 2 3 0 4 rrcurveto 0 5 6 7 0 8 rrcurveto 0 9 10 11 0 12 rrcurveto", + ), + ( # test_vvcurveto_mult_5_4_4 + "1 2 3 4 5 6 7 8 9 10 11 12 13 vvcurveto", + "1 2 3 4 0 5 rrcurveto 0 6 7 8 0 9 rrcurveto 0 10 11 12 0 13 rrcurveto", + ), + # hvcurveto + ("1 2 3 4 hvcurveto", "1 0 2 3 0 4 rrcurveto"), # test_hvcurveto_4 + ( # test_hvcurveto_5 + "57 44 22 40 34 hvcurveto", + "57 0 44 22 34 40 rrcurveto", + ), + ( # test_hvcurveto_4_4 + "65 33 -19 -45 -45 -29 -25 -71 hvcurveto", + "65 0 33 -19 0 -45 rrcurveto 0 -45 -29 -25 -71 0 rrcurveto", + ), + ( # test_hvcurveto_4_5 + "97 69 41 86 58 -36 34 -64 11 hvcurveto", + "97 0 69 41 0 86 rrcurveto 0 58 -36 34 -64 11 rrcurveto", + ), + ( # test_hvcurveto_4_4_4 + "1 2 3 4 5 6 7 8 9 10 11 12 hvcurveto", + "1 0 2 3 0 4 rrcurveto 0 5 6 7 8 0 rrcurveto 9 0 10 11 0 12 rrcurveto", + ), + ( # test_hvcurveto_4_4_5 + "-124 -79 104 165 163 82 102 124 56 43 -25 -37 35 hvcurveto", + "-124 0 -79 104 0 165 rrcurveto 0 163 82 102 124 0 rrcurveto 56 0 43 -25 35 -37 rrcurveto", + ), + ( # test_hvcurveto_4_4_4_4 + "32 25 22 32 31 -25 22 -32 -32 -25 -22 -31 -32 25 -22 32 hvcurveto", + "32 0 25 22 0 32 rrcurveto 0 31 -25 22 -32 0 rrcurveto -32 0 -25 -22 0 -31 rrcurveto 0 -32 25 -22 32 0 rrcurveto", + ), + ( # test_hvcurveto_4_4_4_4_5 + "-170 -128 111 195 234 172 151 178 182 95 -118 -161 -130 -71 -77 -63 -55 -19 38 79 20 hvcurveto", + "-170 0 -128 111 0 195 rrcurveto 0 234 172 151 178 0 rrcurveto 182 0 95 -118 0 -161 rrcurveto 0 -130 -71 -77 -63 0 rrcurveto -55 0 -19 38 20 79 rrcurveto", + ), + # vhcurveto + ( # test_vhcurveto_4 + "-57 43 -30 53 vhcurveto", + "0 -57 43 -30 53 0 rrcurveto", + ), + ( # test_vhcurveto_5 + "41 -27 19 -46 11 vhcurveto", + "0 41 -27 19 -46 11 rrcurveto", + ), + ( # test_vhcurveto_4_4 + "1 2 3 4 5 6 7 8 vhcurveto", + "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto", + ), + ( # test_vhcurveto_4_5 + "-64 -23 -25 -45 -30 -24 14 33 -19 vhcurveto", + "0 -64 -23 -25 -45 0 rrcurveto -30 0 -24 14 -19 33 rrcurveto", + ), + ( # test_vhcurveto_4_4_4 + "1 2 3 4 5 6 7 8 9 10 11 12 vhcurveto", + "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto 0 9 10 11 12 0 rrcurveto", + ), + ( # test_vhcurveto_4_4_5 + "108 59 81 98 99 59 -81 -108 -100 -46 -66 -63 -47 vhcurveto", + "0 108 59 81 98 0 rrcurveto 99 0 59 -81 0 -108 rrcurveto 0 -100 -46 -66 -63 -47 rrcurveto", + ), + ( # test_vhcurveto_4_4_4_5 + "60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto", + "0 60 -26 37 -43 0 rrcurveto -33 0 -28 -22 0 -36 rrcurveto 0 -37 27 -20 32 0 rrcurveto 3 0 4 0 3 1 rrcurveto", + ), + # rcurveline + ( # test_rcurveline_6_2 + "21 -76 21 -72 24 -73 31 -100 rcurveline", + "21 -76 21 -72 24 -73 rrcurveto 31 -100 rlineto", + ), + ( # test_rcurveline_6_6_2 + "-73 80 -80 121 -49 96 60 65 55 41 54 17 -8 78 rcurveline", + "-73 80 -80 121 -49 96 rrcurveto 60 65 55 41 54 17 rrcurveto -8 78 rlineto", + ), + ( # test_rcurveline_6_6_6_2 + "1 64 10 51 29 39 15 21 15 20 15 18 47 -89 63 -98 52 -59 91 8 rcurveline", + "1 64 10 51 29 39 rrcurveto 15 21 15 20 15 18 rrcurveto 47 -89 63 -98 52 -59 rrcurveto 91 8 rlineto", + ), + ( # test_rcurveline_6_6_6_6_2 + "1 64 10 51 29 39 15 21 15 20 15 18 46 -88 63 -97 52 -59 -38 -57 -49 -62 -52 -54 96 -8 rcurveline", + "1 64 10 51 29 39 rrcurveto 15 21 15 20 15 18 rrcurveto 46 -88 63 -97 52 -59 rrcurveto -38 -57 -49 -62 -52 -54 rrcurveto 96 -8 rlineto", + ), + # rlinecurve + ( # test_rlinecurve_2_6 + "21 -76 21 -72 24 -73 31 -100 rlinecurve", + "21 -76 rlineto 21 -72 24 -73 31 -100 rrcurveto", + ), + ( # test_rlinecurve_2_2_6 + "-73 80 -80 121 -49 96 60 65 55 41 rlinecurve", + "-73 80 rlineto -80 121 rlineto -49 96 60 65 55 41 rrcurveto", + ), + ( # test_rlinecurve_2_2_2_6 + "1 64 10 51 29 39 15 21 15 20 15 18 rlinecurve", + "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 15 20 15 18 rrcurveto", + ), + ( # test_rlinecurve_2_2_2_2_6 + "1 64 10 51 29 39 15 21 15 20 15 18 46 -88 rlinecurve", + "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 rlineto 15 20 15 18 46 -88 rrcurveto", + ), + # hstem/vstem + ( # test_hstem_vstem + "95 0 58 542 60 hstem 89 65 344 67 vstem 89 45 rmoveto", + None, + ), + # hstemhm/vstemhm + ( # test_hstemhm_vstemhm + "-16 577 60 24 60 hstemhm 98 55 236 55 vstemhm 343 577 rmoveto", + None, + ), + # hintmask/cntrmask + ( # test_hintmask_cntrmask + "52 80 153 61 4 83 -71.5 71.5 hintmask 11011100 94 119 216 119 216 119 cntrmask 1110000 154 -12 rmoveto", + None, + ), + # endchar + ("-255 319 rmoveto 266 57 rlineto endchar", None), # test_endchar + # xtra + ("-255 319 rmoveto 266 57 rlineto xtra 90 34", None), # test_xtra + ], + ) + def test_generalize(self, charstr, expected): + if expected is None: + expected = charstr + expected = expected.strip() + generalized = charstr_generalize(charstr) + assert generalized == expected, (generalized, expected) + + +class CFFSpecializeProgramTest: + @pytest.mark.parametrize( + "charstr", + [ + # no arguments/operands + ("rmoveto"), # test_rmoveto_none + ("hmoveto"), # test_hmoveto_none + ("vmoveto"), # test_vmoveto_none + ("rlineto"), # test_rlineto_none + ("hlineto"), # test_hlineto_none + ("vlineto"), # test_vlineto_none + ("rrcurveto"), # test_rrcurveto_none + ("hhcurveto"), # test_hhcurveto_none + ("vvcurveto"), # test_vvcurveto_none + ("hvcurveto"), # test_hvcurveto_none + ("vhcurveto"), # test_vhcurveto_none + ("rcurveline"), # test_rcurveline_none + ("rlinecurve"), # test_rlinecurve_none + ], + ) + def test_raises(self, charstr): + try: + charstr_specialize(charstr) + except ValueError: + return + raise AssertionError("Expected to raise ValueError, but didn't.", charstr) + + @pytest.mark.parametrize( + "charstr, expected", + [ + # rmoveto + ("0 0 rmoveto", "0 hmoveto"), # test_rmoveto_zero + ("0 0 rmoveto " * 3, "0 hmoveto"), # test_rmoveto_zero_mult + ("100 0 0 rmoveto", "100 0 hmoveto"), # test_rmoveto_zero_width + (".55 -.8 rmoveto", "0.55 -0.8 rmoveto"), # test_rmoveto + ("55 -8 rmoveto " * 3, "165 -24 rmoveto"), # test_rmoveto_mult + ("100.5 50 -5.8 rmoveto", None), # test_rmoveto_width + # rlineto + ("0 0 rlineto", ""), # test_rlineto_zero + ("0 0 rlineto " * 3, ""), # test_rlineto_zero_mult + (".55 -.8 rlineto", "0.55 -0.8 rlineto"), # test_rlineto + ( # test_rlineto_mult + ".55 -.8 rlineto " * 3, + "0.55 -0.8 0.55 -0.8 0.55 -0.8 rlineto", + ), + (".67 0 rlineto", "0.67 hlineto"), # test_hlineto + ("62 0 rlineto " * 3, "186 hlineto"), # test_hlineto_zero_mult + ( # test_hlineto_mult + ".67 0 rlineto 0 -6.0 rlineto .67 0 rlineto", + "0.67 -6.0 0.67 hlineto", + ), + ("0 -.24 rlineto", "-0.24 vlineto"), # test_vlineto + ("0 -24 rlineto " * 3, "-72 vlineto"), # test_vlineto_zero_mult + ( # test_vlineto_mult + "0 -.24 rlineto +50 0 rlineto 0 30 rlineto -4 0 rlineto", + "-0.24 50 30 -4 vlineto", + ), + ("1 2 0 0 3 4 rlineto", "1 2 3 4 rlineto"), # test_0lineto_peephole + ("1 2 5 0 3 4 rlineto", None), # test_hlineto_peephole + ("1 2 0 5 3 4 rlineto", None), # test_vlineto_peephole + # rrcurveto + ("-1 56 -2 57 -1 57 rrcurveto", None), # test_rrcurveto + ( # test_rrcurveto_mult + "-30 8 -36 15 -37 22 rrcurveto 44 54 31 61 22 68 rrcurveto", + "-30 8 -36 15 -37 22 44 54 31 61 22 68 rrcurveto", + ), + ("1 2 3 4 5 0 rrcurveto", "2 1 3 4 5 hhcurveto"), # test_rrcurveto_d3947b8 + ("10 0 30 0 10 0 rrcurveto", "10 30 0 10 hhcurveto"), # test_hhcurveto_4 + ( # test_hhcurveto_5 + "-38 40 -60 41 -91 0 rrcurveto", + "40 -38 -60 41 -91 hhcurveto", + ), + ( # test_hhcurveto_mult_4_4 + "43 0 23 25 18 0 rrcurveto 29 0 56 42 -84 0 rrcurveto", + "43 23 25 18 29 56 42 -84 hhcurveto", + ), + ( # test_hhcurveto_mult_5_4 + "23 43 25 18 29 0 rrcurveto 56 0 42 -84 79 0 rrcurveto", + "43 23 25 18 29 56 42 -84 79 hhcurveto", + ), + ( # test_hhcurveto_mult_4_4_4 + "1 0 2 3 4 0 rrcurveto 5 0 6 7 8 0 rrcurveto 9 0 10 11 12 0 rrcurveto", + "1 2 3 4 5 6 7 8 9 10 11 12 hhcurveto", + ), + ( # test_hhcurveto_mult_5_4_4 + "2 1 3 4 5 0 rrcurveto 6 0 7 8 9 0 rrcurveto 10 0 11 12 13 0 rrcurveto", + "1 2 3 4 5 6 7 8 9 10 11 12 13 hhcurveto", + ), + ("0 61 6 52 0 68 rrcurveto", "61 6 52 68 vvcurveto"), # test_vvcurveto_4 + ( # test_vvcurveto_5 + "61 38 35 56 0 72 rrcurveto", + "61 38 35 56 72 vvcurveto", + ), + ( # test_vvcurveto_mult_4_4 + "0 -84 -88 -30 0 -90 rrcurveto 0 -13 19 23 0 -11 rrcurveto", + "-84 -88 -30 -90 -13 19 23 -11 vvcurveto", + ), + ( # test_vvcurveto_mult_5_4 + "43 12 17 32 0 65 rrcurveto 0 68 -6 52 0 61 rrcurveto", + "43 12 17 32 65 68 -6 52 61 vvcurveto", + ), + ( # test_vvcurveto_mult_4_4_4 + "0 1 2 3 0 4 rrcurveto 0 5 6 7 0 8 rrcurveto 0 9 10 11 0 12 rrcurveto", + "1 2 3 4 5 6 7 8 9 10 11 12 vvcurveto", + ), + ( # test_vvcurveto_mult_5_4_4 + "1 2 3 4 0 5 rrcurveto 0 6 7 8 0 9 rrcurveto 0 10 11 12 0 13 rrcurveto", + "1 2 3 4 5 6 7 8 9 10 11 12 13 vvcurveto", + ), + ("1 0 2 3 0 4 rrcurveto", "1 2 3 4 hvcurveto"), # test_hvcurveto_4 + ( # test_hvcurveto_5 + "57 0 44 22 34 40 rrcurveto", + "57 44 22 40 34 hvcurveto", + ), + ( # test_hvcurveto_4_4 + "65 0 33 -19 0 -45 rrcurveto 0 -45 -29 -25 -71 0 rrcurveto", + "65 33 -19 -45 -45 -29 -25 -71 hvcurveto", + ), + ( # test_hvcurveto_4_5 + "97 0 69 41 0 86 rrcurveto 0 58 -36 34 -64 11 rrcurveto", + "97 69 41 86 58 -36 34 -64 11 hvcurveto", + ), + ( # test_hvcurveto_4_4_4 + "1 0 2 3 0 4 rrcurveto 0 5 6 7 8 0 rrcurveto 9 0 10 11 0 12 rrcurveto", + "1 2 3 4 5 6 7 8 9 10 11 12 hvcurveto", + ), + ( # test_hvcurveto_4_4_5 + "-124 0 -79 104 0 165 rrcurveto 0 163 82 102 124 0 rrcurveto 56 0 43 -25 35 -37 rrcurveto", + "-124 -79 104 165 163 82 102 124 56 43 -25 -37 35 hvcurveto", + ), + ( # test_hvcurveto_4_4_4_4 + "32 0 25 22 0 32 rrcurveto 0 31 -25 22 -32 0 rrcurveto -32 0 -25 -22 0 -31 rrcurveto 0 -32 25 -22 32 0 rrcurveto", + "32 25 22 32 31 -25 22 -32 -32 -25 -22 -31 -32 25 -22 32 hvcurveto", + ), + ( # test_hvcurveto_4_4_4_4_5 + "-170 0 -128 111 0 195 rrcurveto 0 234 172 151 178 0 rrcurveto 182 0 95 -118 0 -161 rrcurveto 0 -130 -71 -77 -63 0 rrcurveto -55 0 -19 38 20 79 rrcurveto", + "-170 -128 111 195 234 172 151 178 182 95 -118 -161 -130 -71 -77 -63 -55 -19 38 79 20 hvcurveto", + ), + ( # test_vhcurveto_4 + "0 -57 43 -30 53 0 rrcurveto", + "-57 43 -30 53 vhcurveto", + ), + ( # test_vhcurveto_5 + "0 41 -27 19 -46 11 rrcurveto", + "41 -27 19 -46 11 vhcurveto", + ), + ( # test_vhcurveto_4_4 + "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto", + "1 2 3 4 5 6 7 8 vhcurveto", + ), + ( # test_vhcurveto_4_5 + "0 -64 -23 -25 -45 0 rrcurveto -30 0 -24 14 -19 33 rrcurveto", + "-64 -23 -25 -45 -30 -24 14 33 -19 vhcurveto", + ), + ( # test_vhcurveto_4_4_4 + "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto 0 9 10 11 12 0 rrcurveto", + "1 2 3 4 5 6 7 8 9 10 11 12 vhcurveto", + ), + ( # test_vhcurveto_4_4_5 + "0 108 59 81 98 0 rrcurveto 99 0 59 -81 0 -108 rrcurveto 0 -100 -46 -66 -63 -47 rrcurveto", + "108 59 81 98 99 59 -81 -108 -100 -46 -66 -63 -47 vhcurveto", + ), + ( # test_vhcurveto_4_4_4_5 + "0 60 -26 37 -43 0 rrcurveto -33 0 -28 -22 0 -36 rrcurveto 0 -37 27 -20 32 0 rrcurveto 3 0 4 0 3 1 rrcurveto", + "60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto", + ), + ( # test_rrcurveto_v0_0h_h0 + "0 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "10 1 2 0 0 1 2 1 1 3 4 0 vhcurveto", + ), + ( # test_rrcurveto_h0_0h_h0 + "10 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "10 1 2 0 hhcurveto 0 1 2 1 1 3 4 0 hvcurveto", + ), + ( # test_rrcurveto_00_0h_h0 + "0 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "1 2 rlineto 0 1 2 1 1 3 4 0 hvcurveto", + ), + ( # test_rrcurveto_r0_0h_h0 + "10 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto", + "10 10 1 2 0 0 1 2 1 1 3 4 0 vvcurveto", + ), + ( # test_rrcurveto_v0_0v_v0 + "0 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "10 1 2 0 vhcurveto 0 1 2 1 1 3 4 0 hhcurveto", + ), + ( # test_rrcurveto_h0_0v_v0 + "10 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "10 1 2 0 0 1 2 1 1 3 4 0 hhcurveto", + ), + ( # test_rrcurveto_00_0v_v0 + "0 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "1 2 rlineto 0 1 2 1 1 3 4 0 hhcurveto", + ), + ( # test_rrcurveto_r0_0v_v0 + "10 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto", + "10 10 1 2 0 0 1 2 1 1 3 4 0 hhcurveto", + ), + ( # test_hhcurveto_peephole + "1 2 3 4 5 6 1 2 3 4 5 0 1 2 3 4 5 6 rrcurveto", + None, + ), + ( # test_vvcurveto_peephole + "1 2 3 4 5 6 1 2 3 4 0 6 1 2 3 4 5 6 rrcurveto", + None, + ), + ( # test_hvcurveto_peephole + "1 2 3 4 5 6 1 0 3 4 5 6 1 2 3 4 5 6 rrcurveto", + None, + ), + ( # test_vhcurveto_peephole + "1 2 3 4 5 6 0 2 3 4 5 6 1 2 3 4 5 6 rrcurveto", + None, + ), + ( # test_rcurveline_6_2 + "21 -76 21 -72 24 -73 rrcurveto 31 -100 rlineto", + "21 -76 21 -72 24 -73 31 -100 rcurveline", + ), + ( # test_rcurveline_6_6_2 + "-73 80 -80 121 -49 96 rrcurveto 60 65 55 41 54 17 rrcurveto -8 78 rlineto", + "-73 80 -80 121 -49 96 60 65 55 41 54 17 -8 78 rcurveline", + ), + ( # test_rcurveline_6_6_6_2 + "1 64 10 51 29 39 rrcurveto 15 21 15 20 15 18 rrcurveto 47 -89 63 -98 52 -59 rrcurveto 91 8 rlineto", + "1 64 10 51 29 39 15 21 15 20 15 18 47 -89 63 -98 52 -59 91 8 rcurveline", + ), + ( # test_rlinecurve_2_6 + "21 -76 rlineto 21 -72 24 -73 31 -100 rrcurveto", + "21 -76 21 -72 24 -73 31 -100 rlinecurve", + ), + ( # test_rlinecurve_2_2_6 + "-73 80 rlineto -80 121 rlineto -49 96 60 65 55 41 rrcurveto", + "-73 80 -80 121 -49 96 60 65 55 41 rlinecurve", + ), + ( # test_rlinecurve_2_2_2_6 + "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 15 20 15 18 rrcurveto", + "1 64 10 51 29 39 15 21 15 20 15 18 rlinecurve", + ), + ], + ) + def test_specialize(self, charstr, expected): + if expected is None: + expected = charstr + expected = expected.strip() + specialized = charstr_specialize(charstr) + assert specialized == expected, (specialized, expected) # maxstack CFF=48, specializer uses up to 47 def test_maxstack(self): operands = "1 2 3 4 5 6 " operator = "rrcurveto " - test_charstr = (operands + operator) * 9 - xpct_charstr = (operands * 2 + operator + operands * 7 + operator).rstrip() - self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr) + charstr = (operands + operator) * 9 + expected = (operands * 2 + operator + operands * 7 + operator).rstrip() + specialized = charstr_specialize(charstr) + assert specialized == expected, (specialized, expected) + + # maxstack CFF2=513, specializer uses up to 512 + def test_maxstack_blends(self): + numRegions = 15 + numOps = 2000 + getNumRegions = lambda iv: numRegions + blend_one = " ".join([str(i) for i in range(1 + numRegions)] + ["1", "blend"]) + operands = " ".join([blend_one] * 6) + operator = "rrcurveto" + charstr = " ".join([operands, operator] * numOps) + expected = charstr + specialized = charstr_specialize( + charstr, getNumRegions=getNumRegions, maxstack=maxStack + ) + stack_use = charstr_stack_use(specialized, getNumRegions=getNumRegions) + assert maxStack - numRegions < stack_use < maxStack class CFF2VFTestSpecialize(DataFilesHandler): @@ -994,12 +615,12 @@ class CFF2VFTestSpecialize(DataFilesHandler): cmds_g = generalizeCommands(cmds) cmds = specializeCommands(cmds_g, generalizeFirst=False) program = commandsToProgram(cmds) - self.assertEqual(program, cs.program) + assert program == cs.program, (program, cs.program) program = specializeProgram(program, getNumRegions=cs.getNumRegions) - self.assertEqual(program, cs.program) + assert program == cs.program, (program, cs.program) program_g = generalizeProgram(program, getNumRegions=cs.getNumRegions) program = commandsToProgram(cmds_g) - self.assertEqual(program, program_g) + assert program == program_g, (program, program_g) def test_blend_programToCommands(self): ttx_path = self.getpath("TestCFF2Widths.ttx") @@ -1013,10 +634,10 @@ class CFF2VFTestSpecialize(DataFilesHandler): cs.decompile() cmds = programToCommands(cs.program, getNumRegions=cs.getNumRegions) program = commandsToProgram(cmds) - self.assertEqual(program, cs.program) + assert program == cs.program, (program, cs.program) if __name__ == "__main__": import sys - sys.exit(unittest.main()) + sys.exit(pytest.main(sys.argv))