xref: /aosp_15_r20/external/fonttools/Tests/cffLib/specializer_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1from fontTools.cffLib.specializer import (
2    programToString,
3    stringToProgram,
4    generalizeProgram,
5    specializeProgram,
6    programToCommands,
7    commandsToProgram,
8    generalizeCommands,
9    specializeCommands,
10)
11from fontTools.ttLib import TTFont
12import os
13import unittest
14from fontTools.misc.testTools import parseXML, DataFilesHandler
15
16# TODO
17# https://github.com/fonttools/fonttools/pull/959#commitcomment-22059841
18# Maybe we should make these data driven. Each entry will have an input string,
19# and a generalized and specialized. For the latter two, if they are None, they
20# are considered equal to the input. Then we can do roundtripping tests as well...
21# There are a few other places (aosp tests for example) where we generate tests
22# from data.
23
24
25def get_generalized_charstr(charstr, **kwargs):
26    return programToString(generalizeProgram(stringToProgram(charstr), **kwargs))
27
28
29def get_specialized_charstr(charstr, **kwargs):
30    return programToString(specializeProgram(stringToProgram(charstr), **kwargs))
31
32
33class CFFGeneralizeProgramTest(unittest.TestCase):
34    def __init__(self, methodName):
35        unittest.TestCase.__init__(self, methodName)
36        # Python 3 renamed assertRaisesRegexp to assertRaisesRegex,
37        # and fires deprecation warnings if a program uses the old name.
38        if not hasattr(self, "assertRaisesRegex"):
39            self.assertRaisesRegex = self.assertRaisesRegexp
40
41    # no arguments/operands
42    def test_rmoveto_none(self):
43        test_charstr = "rmoveto"
44        with self.assertRaisesRegex(ValueError, r"\[\]"):
45            get_generalized_charstr(test_charstr)
46
47    def test_hmoveto_none(self):
48        test_charstr = "hmoveto"
49        with self.assertRaisesRegex(ValueError, r"\[\]"):
50            get_generalized_charstr(test_charstr)
51
52    def test_vmoveto_none(self):
53        test_charstr = "vmoveto"
54        with self.assertRaisesRegex(ValueError, r"\[\]"):
55            get_generalized_charstr(test_charstr)
56
57    def test_rlineto_none(self):
58        test_charstr = "rlineto"
59        with self.assertRaisesRegex(ValueError, r"\[\]"):
60            get_generalized_charstr(test_charstr)
61
62    def test_hlineto_none(self):
63        test_charstr = "hlineto"
64        with self.assertRaisesRegex(ValueError, r"\[\]"):
65            get_generalized_charstr(test_charstr)
66
67    def test_vlineto_none(self):
68        test_charstr = "vlineto"
69        with self.assertRaisesRegex(ValueError, r"\[\]"):
70            get_generalized_charstr(test_charstr)
71
72    def test_rrcurveto_none(self):
73        test_charstr = "rrcurveto"
74        with self.assertRaisesRegex(ValueError, r"\[\]"):
75            get_generalized_charstr(test_charstr)
76
77    def test_hhcurveto_none(self):
78        test_charstr = "hhcurveto"
79        with self.assertRaisesRegex(ValueError, r"\[\]"):
80            get_generalized_charstr(test_charstr)
81
82    def test_vvcurveto_none(self):
83        test_charstr = "vvcurveto"
84        with self.assertRaisesRegex(ValueError, r"\[\]"):
85            get_generalized_charstr(test_charstr)
86
87    def test_hvcurveto_none(self):
88        test_charstr = "hvcurveto"
89        with self.assertRaisesRegex(ValueError, r"\[\]"):
90            get_generalized_charstr(test_charstr)
91
92    def test_vhcurveto_none(self):
93        test_charstr = "vhcurveto"
94        with self.assertRaisesRegex(ValueError, r"\[\]"):
95            get_generalized_charstr(test_charstr)
96
97    def test_rcurveline_none(self):
98        test_charstr = "rcurveline"
99        with self.assertRaisesRegex(ValueError, r"\[\]"):
100            get_generalized_charstr(test_charstr)
101
102    def test_rlinecurve_none(self):
103        test_charstr = "rlinecurve"
104        with self.assertRaisesRegex(ValueError, r"\[\]"):
105            get_generalized_charstr(test_charstr)
106
107    # rmoveto
108    def test_rmoveto_zero(self):
109        test_charstr = "0 0 rmoveto"
110        xpct_charstr = test_charstr
111        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
112
113    def test_rmoveto_zero_width(self):
114        test_charstr = "100 0 0 rmoveto"
115        xpct_charstr = test_charstr
116        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
117
118    def test_rmoveto(self):
119        test_charstr = ".55 -.8 rmoveto"
120        xpct_charstr = "0.55 -0.8 rmoveto"
121        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
122
123    def test_rmoveto_width(self):
124        test_charstr = "100.5 50 -5.8 rmoveto"
125        xpct_charstr = test_charstr
126        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
127
128    # hmoveto
129    def test_hmoveto_zero(self):
130        test_charstr = "0 hmoveto"
131        xpct_charstr = "0 0 rmoveto"
132        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
133
134    def test_hmoveto_zero_width(self):
135        test_charstr = "100 0 hmoveto"
136        xpct_charstr = "100 0 0 rmoveto"
137        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
138
139    def test_hmoveto(self):
140        test_charstr = ".67 hmoveto"
141        xpct_charstr = "0.67 0 rmoveto"
142        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
143
144    def test_hmoveto_width(self):
145        test_charstr = "100 -70 hmoveto"
146        xpct_charstr = "100 -70 0 rmoveto"
147        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
148
149    # vmoveto
150    def test_vmoveto_zero(self):
151        test_charstr = "0 vmoveto"
152        xpct_charstr = "0 0 rmoveto"
153        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
154
155    def test_vmoveto_zero_width(self):
156        test_charstr = "100 0 vmoveto"
157        xpct_charstr = "100 0 0 rmoveto"
158        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
159
160    def test_vmoveto(self):
161        test_charstr = "-.24 vmoveto"
162        xpct_charstr = "0 -0.24 rmoveto"
163        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
164
165    def test_vmoveto_width(self):
166        test_charstr = "100 44 vmoveto"
167        xpct_charstr = "100 0 44 rmoveto"
168        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
169
170    # rlineto
171    def test_rlineto_zero(self):
172        test_charstr = "0 0 rlineto"
173        xpct_charstr = test_charstr
174        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
175
176    def test_rlineto_zero_mult(self):
177        test_charstr = "0 0 0 0 0 0 rlineto"
178        xpct_charstr = ("0 0 rlineto " * 3).rstrip()
179        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
180
181    def test_rlineto(self):
182        test_charstr = ".55 -.8 rlineto"
183        xpct_charstr = "0.55 -0.8 rlineto"
184        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
185
186    def test_rlineto_mult(self):
187        test_charstr = ".55 -.8 .55 -.8 .55 -.8 rlineto"
188        xpct_charstr = ("0.55 -0.8 rlineto " * 3).rstrip()
189        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
190
191    # hlineto
192    def test_hlineto_zero(self):
193        test_charstr = "0 hlineto"
194        xpct_charstr = "0 0 rlineto"
195        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
196
197    def test_hlineto_zero_mult(self):
198        test_charstr = "0 0 0 0 hlineto"
199        xpct_charstr = ("0 0 rlineto " * 4).rstrip()
200        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
201
202    def test_hlineto(self):
203        test_charstr = ".67 hlineto"
204        xpct_charstr = "0.67 0 rlineto"
205        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
206
207    def test_hlineto_mult(self):
208        test_charstr = ".67 -6.0 .67 hlineto"
209        xpct_charstr = "0.67 0 rlineto 0 -6.0 rlineto 0.67 0 rlineto"
210        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
211
212    # vlineto
213    def test_vlineto_zero(self):
214        test_charstr = "0 vlineto"
215        xpct_charstr = "0 0 rlineto"
216        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
217
218    def test_vlineto_zero_mult(self):
219        test_charstr = "0 0 0 vlineto"
220        xpct_charstr = ("0 0 rlineto " * 3).rstrip()
221        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
222
223    def test_vlineto(self):
224        test_charstr = "-.24 vlineto"
225        xpct_charstr = "0 -0.24 rlineto"
226        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
227
228    def test_vlineto_mult(self):
229        test_charstr = "-.24 +50 30 -4 vlineto"
230        xpct_charstr = "0 -0.24 rlineto 50 0 rlineto 0 30 rlineto -4 0 rlineto"
231        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
232
233    # rrcurveto
234    def test_rrcurveto(self):
235        test_charstr = "-1 56 -2 57 -1 57 rrcurveto"
236        xpct_charstr = test_charstr
237        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
238
239    def test_rrcurveto_mult(self):
240        test_charstr = "-30 8 -36 15 -37 22 44 54 31 61 22 68 rrcurveto"
241        xpct_charstr = "-30 8 -36 15 -37 22 rrcurveto 44 54 31 61 22 68 rrcurveto"
242        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
243
244    def test_rrcurveto_d3947b8(self):
245        test_charstr = "1 2 3 4 5 0 rrcurveto"
246        xpct_charstr = test_charstr
247        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
248
249    def test_rrcurveto_v0_0h_h0(self):
250        test_charstr = "0 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
251        xpct_charstr = (
252            "0 10 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto"
253        )
254        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
255
256    def test_rrcurveto_h0_0h_h0(self):
257        test_charstr = "10 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
258        xpct_charstr = (
259            "10 0 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto"
260        )
261        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
262
263    def test_rrcurveto_00_0h_h0(self):
264        test_charstr = "0 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
265        xpct_charstr = (
266            "0 0 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto"
267        )
268        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
269
270    def test_rrcurveto_r0_0h_h0(self):
271        test_charstr = "10 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
272        xpct_charstr = (
273            "10 10 1 2 0 0 rrcurveto 0 0 1 2 0 1 rrcurveto 0 1 3 4 0 0 rrcurveto"
274        )
275        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
276
277    def test_rrcurveto_v0_0v_v0(self):
278        test_charstr = "0 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
279        xpct_charstr = (
280            "0 10 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto"
281        )
282        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
283
284    def test_rrcurveto_h0_0v_v0(self):
285        test_charstr = "10 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
286        xpct_charstr = (
287            "10 0 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto"
288        )
289        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
290
291    def test_rrcurveto_00_0v_v0(self):
292        test_charstr = "0 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
293        xpct_charstr = (
294            "0 0 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto"
295        )
296        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
297
298    def test_rrcurveto_r0_0v_v0(self):
299        test_charstr = "10 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
300        xpct_charstr = (
301            "10 10 1 2 0 0 rrcurveto 0 0 1 2 1 0 rrcurveto 1 0 3 4 0 0 rrcurveto"
302        )
303        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
304
305    # hhcurveto
306    def test_hhcurveto_4(self):
307        test_charstr = "10 30 0 10 hhcurveto"
308        xpct_charstr = "10 0 30 0 10 0 rrcurveto"
309        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
310
311    def test_hhcurveto_5(self):
312        test_charstr = "40 -38 -60 41 -91 hhcurveto"
313        xpct_charstr = "-38 40 -60 41 -91 0 rrcurveto"
314        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
315
316    def test_hhcurveto_mult_4_4(self):
317        test_charstr = "43 23 25 18 29 56 42 -84 hhcurveto"
318        xpct_charstr = "43 0 23 25 18 0 rrcurveto 29 0 56 42 -84 0 rrcurveto"
319        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
320
321    def test_hhcurveto_mult_5_4(self):
322        test_charstr = "43 23 25 18 29 56 42 -84 79 hhcurveto"
323        xpct_charstr = "23 43 25 18 29 0 rrcurveto 56 0 42 -84 79 0 rrcurveto"
324        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
325
326    def test_hhcurveto_mult_4_4_4(self):
327        test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hhcurveto"
328        xpct_charstr = (
329            "1 0 2 3 4 0 rrcurveto 5 0 6 7 8 0 rrcurveto 9 0 10 11 12 0 rrcurveto"
330        )
331        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
332
333    def test_hhcurveto_mult_5_4_4(self):
334        test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 hhcurveto"
335        xpct_charstr = (
336            "2 1 3 4 5 0 rrcurveto 6 0 7 8 9 0 rrcurveto 10 0 11 12 13 0 rrcurveto"
337        )
338        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
339
340    # vvcurveto
341    def test_vvcurveto_4(self):
342        test_charstr = "61 6 52 68 vvcurveto"
343        xpct_charstr = "0 61 6 52 0 68 rrcurveto"
344        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
345
346    def test_vvcurveto_5(self):
347        test_charstr = "61 38 35 56 72 vvcurveto"
348        xpct_charstr = "61 38 35 56 0 72 rrcurveto"
349        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
350
351    def test_vvcurveto_mult_4_4(self):
352        test_charstr = "-84 -88 -30 -90 -13 19 23 -11 vvcurveto"
353        xpct_charstr = "0 -84 -88 -30 0 -90 rrcurveto 0 -13 19 23 0 -11 rrcurveto"
354        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
355
356    def test_vvcurveto_mult_5_4(self):
357        test_charstr = "43 12 17 32 65 68 -6 52 61 vvcurveto"
358        xpct_charstr = "43 12 17 32 0 65 rrcurveto 0 68 -6 52 0 61 rrcurveto"
359        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
360
361    def test_vvcurveto_mult_4_4_4(self):
362        test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vvcurveto"
363        xpct_charstr = (
364            "0 1 2 3 0 4 rrcurveto 0 5 6 7 0 8 rrcurveto 0 9 10 11 0 12 rrcurveto"
365        )
366        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
367
368    def test_vvcurveto_mult_5_4_4(self):
369        test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 vvcurveto"
370        xpct_charstr = (
371            "1 2 3 4 0 5 rrcurveto 0 6 7 8 0 9 rrcurveto 0 10 11 12 0 13 rrcurveto"
372        )
373        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
374
375    # hvcurveto
376    def test_hvcurveto_4(self):
377        test_charstr = "1 2 3 4 hvcurveto"
378        xpct_charstr = "1 0 2 3 0 4 rrcurveto"
379        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
380
381    def test_hvcurveto_5(self):
382        test_charstr = "57 44 22 40 34 hvcurveto"
383        xpct_charstr = "57 0 44 22 34 40 rrcurveto"
384        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
385
386    def test_hvcurveto_4_4(self):
387        test_charstr = "65 33 -19 -45 -45 -29 -25 -71 hvcurveto"
388        xpct_charstr = "65 0 33 -19 0 -45 rrcurveto 0 -45 -29 -25 -71 0 rrcurveto"
389        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
390
391    def test_hvcurveto_4_5(self):
392        test_charstr = "97 69 41 86 58 -36 34 -64 11 hvcurveto"
393        xpct_charstr = "97 0 69 41 0 86 rrcurveto 0 58 -36 34 -64 11 rrcurveto"
394        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
395
396    def test_hvcurveto_4_4_4(self):
397        test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hvcurveto"
398        xpct_charstr = (
399            "1 0 2 3 0 4 rrcurveto 0 5 6 7 8 0 rrcurveto 9 0 10 11 0 12 rrcurveto"
400        )
401        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
402
403    def test_hvcurveto_4_4_5(self):
404        test_charstr = "-124 -79 104 165 163 82 102 124 56 43 -25 -37 35 hvcurveto"
405        xpct_charstr = "-124 0 -79 104 0 165 rrcurveto 0 163 82 102 124 0 rrcurveto 56 0 43 -25 35 -37 rrcurveto"
406        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
407
408    def test_hvcurveto_4_4_4_4(self):
409        test_charstr = (
410            "32 25 22 32 31 -25 22 -32 -32 -25 -22 -31 -32 25 -22 32 hvcurveto"
411        )
412        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"
413        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
414
415    def test_hvcurveto_4_4_4_4_5(self):
416        test_charstr = "-170 -128 111 195 234 172 151 178 182 95 -118 -161 -130 -71 -77 -63 -55 -19 38 79 20 hvcurveto"
417        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"
418        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
419
420    # vhcurveto
421    def test_vhcurveto_4(self):
422        test_charstr = "-57 43 -30 53 vhcurveto"
423        xpct_charstr = "0 -57 43 -30 53 0 rrcurveto"
424        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
425
426    def test_vhcurveto_5(self):
427        test_charstr = "41 -27 19 -46 11 vhcurveto"
428        xpct_charstr = "0 41 -27 19 -46 11 rrcurveto"
429        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
430
431    def test_vhcurveto_4_4(self):
432        test_charstr = "1 2 3 4 5 6 7 8 vhcurveto"
433        xpct_charstr = "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto"
434        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
435
436    def test_vhcurveto_4_5(self):
437        test_charstr = "-64 -23 -25 -45 -30 -24 14 33 -19 vhcurveto"
438        xpct_charstr = "0 -64 -23 -25 -45 0 rrcurveto -30 0 -24 14 -19 33 rrcurveto"
439        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
440
441    def test_vhcurveto_4_4_4(self):
442        test_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vhcurveto"
443        xpct_charstr = (
444            "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto 0 9 10 11 12 0 rrcurveto"
445        )
446        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
447
448    def test_vhcurveto_4_4_5(self):
449        test_charstr = "108 59 81 98 99 59 -81 -108 -100 -46 -66 -63 -47 vhcurveto"
450        xpct_charstr = "0 108 59 81 98 0 rrcurveto 99 0 59 -81 0 -108 rrcurveto 0 -100 -46 -66 -63 -47 rrcurveto"
451        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
452
453    def test_vhcurveto_4_4_4_5(self):
454        test_charstr = "60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto"
455        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"
456        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
457
458    # rcurveline
459    def test_rcurveline_6_2(self):
460        test_charstr = "21 -76 21 -72 24 -73 31 -100 rcurveline"
461        xpct_charstr = "21 -76 21 -72 24 -73 rrcurveto 31 -100 rlineto"
462        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
463
464    def test_rcurveline_6_6_2(self):
465        test_charstr = "-73 80 -80 121 -49 96 60 65 55 41 54 17 -8 78 rcurveline"
466        xpct_charstr = (
467            "-73 80 -80 121 -49 96 rrcurveto 60 65 55 41 54 17 rrcurveto -8 78 rlineto"
468        )
469        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
470
471    def test_rcurveline_6_6_6_2(self):
472        test_charstr = (
473            "1 64 10 51 29 39 15 21 15 20 15 18 47 -89 63 -98 52 -59 91 8 rcurveline"
474        )
475        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"
476        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
477
478    def test_rcurveline_6_6_6_6_2(self):
479        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"
480        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"
481        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
482
483    # rlinecurve
484    def test_rlinecurve_2_6(self):
485        test_charstr = "21 -76 21 -72 24 -73 31 -100 rlinecurve"
486        xpct_charstr = "21 -76 rlineto 21 -72 24 -73 31 -100 rrcurveto"
487        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
488
489    def test_rlinecurve_2_2_6(self):
490        test_charstr = "-73 80 -80 121 -49 96 60 65 55 41 rlinecurve"
491        xpct_charstr = "-73 80 rlineto -80 121 rlineto -49 96 60 65 55 41 rrcurveto"
492        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
493
494    def test_rlinecurve_2_2_2_6(self):
495        test_charstr = "1 64 10 51 29 39 15 21 15 20 15 18 rlinecurve"
496        xpct_charstr = (
497            "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 15 20 15 18 rrcurveto"
498        )
499        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
500
501    def test_rlinecurve_2_2_2_2_6(self):
502        test_charstr = "1 64 10 51 29 39 15 21 15 20 15 18 46 -88 rlinecurve"
503        xpct_charstr = "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 rlineto 15 20 15 18 46 -88 rrcurveto"
504        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
505
506    # hstem/vstem
507    def test_hstem_vstem(self):
508        test_charstr = "95 0 58 542 60 hstem 89 65 344 67 vstem 89 45 rmoveto"
509        xpct_charstr = test_charstr
510        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
511
512    # hstemhm/vstemhm
513    def test_hstemhm_vstemhm(self):
514        test_charstr = "-16 577 60 24 60 hstemhm 98 55 236 55 vstemhm 343 577 rmoveto"
515        xpct_charstr = test_charstr
516        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
517
518    # hintmask/cntrmask
519    def test_hintmask_cntrmask(self):
520        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"
521        xpct_charstr = test_charstr
522        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
523
524    # endchar
525    def test_endchar(self):
526        test_charstr = "-255 319 rmoveto 266 57 rlineto endchar"
527        xpct_charstr = test_charstr
528        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
529
530    # xtra
531    def test_xtra(self):
532        test_charstr = "-255 319 rmoveto 266 57 rlineto xtra 90 34"
533        xpct_charstr = test_charstr
534        self.assertEqual(get_generalized_charstr(test_charstr), xpct_charstr)
535
536
537class CFFSpecializeProgramTest(unittest.TestCase):
538    def __init__(self, methodName):
539        unittest.TestCase.__init__(self, methodName)
540        # Python 3 renamed assertRaisesRegexp to assertRaisesRegex,
541        # and fires deprecation warnings if a program uses the old name.
542        if not hasattr(self, "assertRaisesRegex"):
543            self.assertRaisesRegex = self.assertRaisesRegexp
544
545    # no arguments/operands
546    def test_rmoveto_none(self):
547        test_charstr = "rmoveto"
548        with self.assertRaisesRegex(ValueError, r"\[\]"):
549            get_specialized_charstr(test_charstr)
550
551    def test_hmoveto_none(self):
552        test_charstr = "hmoveto"
553        with self.assertRaisesRegex(ValueError, r"\[\]"):
554            get_specialized_charstr(test_charstr)
555
556    def test_vmoveto_none(self):
557        test_charstr = "vmoveto"
558        with self.assertRaisesRegex(ValueError, r"\[\]"):
559            get_specialized_charstr(test_charstr)
560
561    def test_rlineto_none(self):
562        test_charstr = "rlineto"
563        with self.assertRaisesRegex(ValueError, r"\[\]"):
564            get_specialized_charstr(test_charstr)
565
566    def test_hlineto_none(self):
567        test_charstr = "hlineto"
568        with self.assertRaisesRegex(ValueError, r"\[\]"):
569            get_specialized_charstr(test_charstr)
570
571    def test_vlineto_none(self):
572        test_charstr = "vlineto"
573        with self.assertRaisesRegex(ValueError, r"\[\]"):
574            get_specialized_charstr(test_charstr)
575
576    def test_rrcurveto_none(self):
577        test_charstr = "rrcurveto"
578        with self.assertRaisesRegex(ValueError, r"\[\]"):
579            get_specialized_charstr(test_charstr)
580
581    def test_hhcurveto_none(self):
582        test_charstr = "hhcurveto"
583        with self.assertRaisesRegex(ValueError, r"\[\]"):
584            get_specialized_charstr(test_charstr)
585
586    def test_vvcurveto_none(self):
587        test_charstr = "vvcurveto"
588        with self.assertRaisesRegex(ValueError, r"\[\]"):
589            get_specialized_charstr(test_charstr)
590
591    def test_hvcurveto_none(self):
592        test_charstr = "hvcurveto"
593        with self.assertRaisesRegex(ValueError, r"\[\]"):
594            get_specialized_charstr(test_charstr)
595
596    def test_vhcurveto_none(self):
597        test_charstr = "vhcurveto"
598        with self.assertRaisesRegex(ValueError, r"\[\]"):
599            get_specialized_charstr(test_charstr)
600
601    def test_rcurveline_none(self):
602        test_charstr = "rcurveline"
603        with self.assertRaisesRegex(ValueError, r"\[\]"):
604            get_specialized_charstr(test_charstr)
605
606    def test_rlinecurve_none(self):
607        test_charstr = "rlinecurve"
608        with self.assertRaisesRegex(ValueError, r"\[\]"):
609            get_specialized_charstr(test_charstr)
610
611    # rmoveto
612    def test_rmoveto_zero(self):
613        test_charstr = "0 0 rmoveto"
614        xpct_charstr = "0 hmoveto"
615        self.assertEqual(
616            get_specialized_charstr(test_charstr, generalizeFirst=False), xpct_charstr
617        )
618
619    def test_rmoveto_zero_mult(self):
620        test_charstr = "0 0 rmoveto " * 3
621        xpct_charstr = "0 hmoveto"
622        self.assertEqual(
623            get_specialized_charstr(test_charstr, generalizeFirst=False), xpct_charstr
624        )
625
626    def test_rmoveto_zero_width(self):
627        test_charstr = "100 0 0 rmoveto"
628        xpct_charstr = "100 0 hmoveto"
629        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
630
631    def test_rmoveto(self):
632        test_charstr = ".55 -.8 rmoveto"
633        xpct_charstr = "0.55 -0.8 rmoveto"
634        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
635
636    def test_rmoveto_mult(self):
637        test_charstr = "55 -8 rmoveto " * 3
638        xpct_charstr = "165 -24 rmoveto"
639        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
640
641    def test_rmoveto_width(self):
642        test_charstr = "100.5 50 -5.8 rmoveto"
643        xpct_charstr = test_charstr
644        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
645
646    # rlineto
647    def test_rlineto_zero(self):
648        test_charstr = "0 0 rlineto"
649        xpct_charstr = ""
650        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
651
652    def test_rlineto_zero_mult(self):
653        test_charstr = "0 0 rlineto " * 3
654        xpct_charstr = ""
655        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
656
657    def test_rlineto(self):
658        test_charstr = ".55 -.8 rlineto"
659        xpct_charstr = "0.55 -0.8 rlineto"
660        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
661
662    def test_rlineto_mult(self):
663        test_charstr = ".55 -.8 rlineto " * 3
664        xpct_charstr = "0.55 -0.8 0.55 -0.8 0.55 -0.8 rlineto"
665        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
666
667    def test_hlineto(self):
668        test_charstr = ".67 0 rlineto"
669        xpct_charstr = "0.67 hlineto"
670        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
671
672    def test_hlineto_zero_mult(self):
673        test_charstr = "62 0 rlineto " * 3
674        xpct_charstr = "186 hlineto"
675        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
676
677    def test_hlineto_mult(self):
678        test_charstr = ".67 0 rlineto 0 -6.0 rlineto .67 0 rlineto"
679        xpct_charstr = "0.67 -6.0 0.67 hlineto"
680        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
681
682    def test_vlineto(self):
683        test_charstr = "0 -.24 rlineto"
684        xpct_charstr = "-0.24 vlineto"
685        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
686
687    def test_vlineto_zero_mult(self):
688        test_charstr = "0 -24 rlineto " * 3
689        xpct_charstr = "-72 vlineto"
690        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
691
692    def test_vlineto_mult(self):
693        test_charstr = "0 -.24 rlineto +50 0 rlineto 0 30 rlineto -4 0 rlineto"
694        xpct_charstr = "-0.24 50 30 -4 vlineto"
695        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
696
697    def test_0lineto_peephole(self):
698        test_charstr = "1 2 0 0 3 4 rlineto"
699        xpct_charstr = "1 2 3 4 rlineto"
700        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
701
702    def test_hlineto_peephole(self):
703        test_charstr = "1 2 5 0 3 4 rlineto"
704        xpct_charstr = test_charstr
705        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
706
707    def test_vlineto_peephole(self):
708        test_charstr = "1 2 0 5 3 4 rlineto"
709        xpct_charstr = test_charstr
710        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
711
712    # rrcurveto
713    def test_rrcurveto(self):
714        test_charstr = "-1 56 -2 57 -1 57 rrcurveto"
715        xpct_charstr = test_charstr
716        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
717
718    def test_rrcurveto_mult(self):
719        test_charstr = "-30 8 -36 15 -37 22 rrcurveto 44 54 31 61 22 68 rrcurveto"
720        xpct_charstr = "-30 8 -36 15 -37 22 44 54 31 61 22 68 rrcurveto"
721        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
722
723    def test_rrcurveto_d3947b8(self):
724        test_charstr = "1 2 3 4 5 0 rrcurveto"
725        xpct_charstr = "2 1 3 4 5 hhcurveto"
726        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
727
728    def test_hhcurveto_4(self):
729        test_charstr = "10 0 30 0 10 0 rrcurveto"
730        xpct_charstr = "10 30 0 10 hhcurveto"
731        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
732
733    def test_hhcurveto_5(self):
734        test_charstr = "-38 40 -60 41 -91 0 rrcurveto"
735        xpct_charstr = "40 -38 -60 41 -91 hhcurveto"
736        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
737
738    def test_hhcurveto_mult_4_4(self):
739        test_charstr = "43 0 23 25 18 0 rrcurveto 29 0 56 42 -84 0 rrcurveto"
740        xpct_charstr = "43 23 25 18 29 56 42 -84 hhcurveto"
741        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
742
743    def test_hhcurveto_mult_5_4(self):
744        test_charstr = "23 43 25 18 29 0 rrcurveto 56 0 42 -84 79 0 rrcurveto"
745        xpct_charstr = "43 23 25 18 29 56 42 -84 79 hhcurveto"
746        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
747
748    def test_hhcurveto_mult_4_4_4(self):
749        test_charstr = (
750            "1 0 2 3 4 0 rrcurveto 5 0 6 7 8 0 rrcurveto 9 0 10 11 12 0 rrcurveto"
751        )
752        xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hhcurveto"
753        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
754
755    def test_hhcurveto_mult_5_4_4(self):
756        test_charstr = (
757            "2 1 3 4 5 0 rrcurveto 6 0 7 8 9 0 rrcurveto 10 0 11 12 13 0 rrcurveto"
758        )
759        xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 hhcurveto"
760        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
761
762    def test_vvcurveto_4(self):
763        test_charstr = "0 61 6 52 0 68 rrcurveto"
764        xpct_charstr = "61 6 52 68 vvcurveto"
765        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
766
767    def test_vvcurveto_5(self):
768        test_charstr = "61 38 35 56 0 72 rrcurveto"
769        xpct_charstr = "61 38 35 56 72 vvcurveto"
770        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
771
772    def test_vvcurveto_mult_4_4(self):
773        test_charstr = "0 -84 -88 -30 0 -90 rrcurveto 0 -13 19 23 0 -11 rrcurveto"
774        xpct_charstr = "-84 -88 -30 -90 -13 19 23 -11 vvcurveto"
775        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
776
777    def test_vvcurveto_mult_5_4(self):
778        test_charstr = "43 12 17 32 0 65 rrcurveto 0 68 -6 52 0 61 rrcurveto"
779        xpct_charstr = "43 12 17 32 65 68 -6 52 61 vvcurveto"
780        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
781
782    def test_vvcurveto_mult_4_4_4(self):
783        test_charstr = (
784            "0 1 2 3 0 4 rrcurveto 0 5 6 7 0 8 rrcurveto 0 9 10 11 0 12 rrcurveto"
785        )
786        xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vvcurveto"
787        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
788
789    def test_vvcurveto_mult_5_4_4(self):
790        test_charstr = (
791            "1 2 3 4 0 5 rrcurveto 0 6 7 8 0 9 rrcurveto 0 10 11 12 0 13 rrcurveto"
792        )
793        xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 13 vvcurveto"
794        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
795
796    def test_hvcurveto_4(self):
797        test_charstr = "1 0 2 3 0 4 rrcurveto"
798        xpct_charstr = "1 2 3 4 hvcurveto"
799        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
800
801    def test_hvcurveto_5(self):
802        test_charstr = "57 0 44 22 34 40 rrcurveto"
803        xpct_charstr = "57 44 22 40 34 hvcurveto"
804        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
805
806    def test_hvcurveto_4_4(self):
807        test_charstr = "65 0 33 -19 0 -45 rrcurveto 0 -45 -29 -25 -71 0 rrcurveto"
808        xpct_charstr = "65 33 -19 -45 -45 -29 -25 -71 hvcurveto"
809        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
810
811    def test_hvcurveto_4_5(self):
812        test_charstr = "97 0 69 41 0 86 rrcurveto 0 58 -36 34 -64 11 rrcurveto"
813        xpct_charstr = "97 69 41 86 58 -36 34 -64 11 hvcurveto"
814        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
815
816    def test_hvcurveto_4_4_4(self):
817        test_charstr = (
818            "1 0 2 3 0 4 rrcurveto 0 5 6 7 8 0 rrcurveto 9 0 10 11 0 12 rrcurveto"
819        )
820        xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 hvcurveto"
821        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
822
823    def test_hvcurveto_4_4_5(self):
824        test_charstr = "-124 0 -79 104 0 165 rrcurveto 0 163 82 102 124 0 rrcurveto 56 0 43 -25 35 -37 rrcurveto"
825        xpct_charstr = "-124 -79 104 165 163 82 102 124 56 43 -25 -37 35 hvcurveto"
826        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
827
828    def test_hvcurveto_4_4_4_4(self):
829        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"
830        xpct_charstr = (
831            "32 25 22 32 31 -25 22 -32 -32 -25 -22 -31 -32 25 -22 32 hvcurveto"
832        )
833        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
834
835    def test_hvcurveto_4_4_4_4_5(self):
836        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"
837        xpct_charstr = "-170 -128 111 195 234 172 151 178 182 95 -118 -161 -130 -71 -77 -63 -55 -19 38 79 20 hvcurveto"
838        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
839
840    def test_vhcurveto_4(self):
841        test_charstr = "0 -57 43 -30 53 0 rrcurveto"
842        xpct_charstr = "-57 43 -30 53 vhcurveto"
843        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
844
845    def test_vhcurveto_5(self):
846        test_charstr = "0 41 -27 19 -46 11 rrcurveto"
847        xpct_charstr = "41 -27 19 -46 11 vhcurveto"
848        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
849
850    def test_vhcurveto_4_4(self):
851        test_charstr = "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto"
852        xpct_charstr = "1 2 3 4 5 6 7 8 vhcurveto"
853        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
854
855    def test_vhcurveto_4_5(self):
856        test_charstr = "0 -64 -23 -25 -45 0 rrcurveto -30 0 -24 14 -19 33 rrcurveto"
857        xpct_charstr = "-64 -23 -25 -45 -30 -24 14 33 -19 vhcurveto"
858        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
859
860    def test_vhcurveto_4_4_4(self):
861        test_charstr = (
862            "0 1 2 3 4 0 rrcurveto 5 0 6 7 0 8 rrcurveto 0 9 10 11 12 0 rrcurveto"
863        )
864        xpct_charstr = "1 2 3 4 5 6 7 8 9 10 11 12 vhcurveto"
865        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
866
867    def test_vhcurveto_4_4_5(self):
868        test_charstr = "0 108 59 81 98 0 rrcurveto 99 0 59 -81 0 -108 rrcurveto 0 -100 -46 -66 -63 -47 rrcurveto"
869        xpct_charstr = "108 59 81 98 99 59 -81 -108 -100 -46 -66 -63 -47 vhcurveto"
870        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
871
872    def test_vhcurveto_4_4_4_5(self):
873        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"
874        xpct_charstr = "60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto"
875        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
876
877    def test_rrcurveto_v0_0h_h0(self):
878        test_charstr = "0 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
879        xpct_charstr = "10 1 2 0 0 1 2 1 1 3 4 0 vhcurveto"
880        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
881
882    def test_rrcurveto_h0_0h_h0(self):
883        test_charstr = "10 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
884        xpct_charstr = "10 1 2 0 hhcurveto 0 1 2 1 1 3 4 0 hvcurveto"
885        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
886
887    def test_rrcurveto_00_0h_h0(self):
888        test_charstr = "0 0 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
889        xpct_charstr = "1 2 rlineto 0 1 2 1 1 3 4 0 hvcurveto"
890        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
891
892    def test_rrcurveto_r0_0h_h0(self):
893        test_charstr = "10 10 1 2 0 0 0 0 1 2 0 1 0 1 3 4 0 0 rrcurveto"
894        xpct_charstr = "10 10 1 2 0 0 1 2 1 1 3 4 0 vvcurveto"
895        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
896
897    def test_rrcurveto_v0_0v_v0(self):
898        test_charstr = "0 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
899        xpct_charstr = "10 1 2 0 vhcurveto 0 1 2 1 1 3 4 0 hhcurveto"
900        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
901
902    def test_rrcurveto_h0_0v_v0(self):
903        test_charstr = "10 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
904        xpct_charstr = "10 1 2 0 0 1 2 1 1 3 4 0 hhcurveto"
905        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
906
907    def test_rrcurveto_00_0v_v0(self):
908        test_charstr = "0 0 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
909        xpct_charstr = "1 2 rlineto 0 1 2 1 1 3 4 0 hhcurveto"
910        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
911
912    def test_rrcurveto_r0_0v_v0(self):
913        test_charstr = "10 10 1 2 0 0 0 0 1 2 1 0 1 0 3 4 0 0 rrcurveto"
914        xpct_charstr = "10 10 1 2 0 0 1 2 1 1 3 4 0 hhcurveto"
915        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
916
917    def test_hhcurveto_peephole(self):
918        test_charstr = "1 2 3 4 5 6 1 2 3 4 5 0 1 2 3 4 5 6 rrcurveto"
919        xpct_charstr = test_charstr
920        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
921
922    def test_vvcurveto_peephole(self):
923        test_charstr = "1 2 3 4 5 6 1 2 3 4 0 6 1 2 3 4 5 6 rrcurveto"
924        xpct_charstr = test_charstr
925        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
926
927    def test_hvcurveto_peephole(self):
928        test_charstr = "1 2 3 4 5 6 1 0 3 4 5 6 1 2 3 4 5 6 rrcurveto"
929        xpct_charstr = test_charstr
930        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
931
932    def test_vhcurveto_peephole(self):
933        test_charstr = "1 2 3 4 5 6 0 2 3 4 5 6 1 2 3 4 5 6 rrcurveto"
934        xpct_charstr = test_charstr
935        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
936
937    def test_rcurveline_6_2(self):
938        test_charstr = "21 -76 21 -72 24 -73 rrcurveto 31 -100 rlineto"
939        xpct_charstr = "21 -76 21 -72 24 -73 31 -100 rcurveline"
940        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
941
942    def test_rcurveline_6_6_2(self):
943        test_charstr = (
944            "-73 80 -80 121 -49 96 rrcurveto 60 65 55 41 54 17 rrcurveto -8 78 rlineto"
945        )
946        xpct_charstr = "-73 80 -80 121 -49 96 60 65 55 41 54 17 -8 78 rcurveline"
947        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
948
949    def test_rcurveline_6_6_6_2(self):
950        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"
951        xpct_charstr = (
952            "1 64 10 51 29 39 15 21 15 20 15 18 47 -89 63 -98 52 -59 91 8 rcurveline"
953        )
954        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
955
956    def test_rlinecurve_2_6(self):
957        test_charstr = "21 -76 rlineto 21 -72 24 -73 31 -100 rrcurveto"
958        xpct_charstr = "21 -76 21 -72 24 -73 31 -100 rlinecurve"
959        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
960
961    def test_rlinecurve_2_2_6(self):
962        test_charstr = "-73 80 rlineto -80 121 rlineto -49 96 60 65 55 41 rrcurveto"
963        xpct_charstr = "-73 80 -80 121 -49 96 60 65 55 41 rlinecurve"
964        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
965
966    def test_rlinecurve_2_2_2_6(self):
967        test_charstr = (
968            "1 64 rlineto 10 51 rlineto 29 39 rlineto 15 21 15 20 15 18 rrcurveto"
969        )
970        xpct_charstr = "1 64 10 51 29 39 15 21 15 20 15 18 rlinecurve"
971        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
972
973    # maxstack CFF=48, specializer uses up to 47
974    def test_maxstack(self):
975        operands = "1 2 3 4 5 6 "
976        operator = "rrcurveto "
977        test_charstr = (operands + operator) * 9
978        xpct_charstr = (operands * 2 + operator + operands * 7 + operator).rstrip()
979        self.assertEqual(get_specialized_charstr(test_charstr), xpct_charstr)
980
981
982class CFF2VFTestSpecialize(DataFilesHandler):
983    def test_blend_round_trip(self):
984        ttx_path = self.getpath("TestSparseCFF2VF.ttx")
985        ttf_font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
986        ttf_font.importXML(ttx_path)
987        fontGlyphList = ttf_font.getGlyphOrder()
988        topDict = ttf_font["CFF2"].cff.topDictIndex[0]
989        charstrings = topDict.CharStrings
990        for glyphName in fontGlyphList:
991            cs = charstrings[glyphName]
992            cs.decompile()
993            cmds = programToCommands(cs.program, getNumRegions=cs.getNumRegions)
994            cmds_g = generalizeCommands(cmds)
995            cmds = specializeCommands(cmds_g, generalizeFirst=False)
996            program = commandsToProgram(cmds)
997            self.assertEqual(program, cs.program)
998            program = specializeProgram(program, getNumRegions=cs.getNumRegions)
999            self.assertEqual(program, cs.program)
1000            program_g = generalizeProgram(program, getNumRegions=cs.getNumRegions)
1001            program = commandsToProgram(cmds_g)
1002            self.assertEqual(program, program_g)
1003
1004    def test_blend_programToCommands(self):
1005        ttx_path = self.getpath("TestCFF2Widths.ttx")
1006        ttf_font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
1007        ttf_font.importXML(ttx_path)
1008        fontGlyphList = ttf_font.getGlyphOrder()
1009        topDict = ttf_font["CFF2"].cff.topDictIndex[0]
1010        charstrings = topDict.CharStrings
1011        for glyphName in fontGlyphList:
1012            cs = charstrings[glyphName]
1013            cs.decompile()
1014            cmds = programToCommands(cs.program, getNumRegions=cs.getNumRegions)
1015            program = commandsToProgram(cmds)
1016            self.assertEqual(program, cs.program)
1017
1018
1019if __name__ == "__main__":
1020    import sys
1021
1022    sys.exit(unittest.main())
1023