1# -*- coding: utf-8 -*-
2from __future__ import absolute_import, unicode_literals
3import unittest
4from ufoLib.glifLib import GlifLibError, readGlyphFromString, writeGlyphToString
5from ufoLib.test.testSupport import Glyph, stripText
6from itertools import islice
7
8try:
9	basestring
10except NameError:
11	basestring = str
12# ----------
13# Test Cases
14# ----------
15
16class TestGLIF1(unittest.TestCase):
17
18	def assertEqual(self, first, second, msg=None):
19		if isinstance(first, basestring):
20			first = stripText(first)
21		if isinstance(second, basestring):
22			second = stripText(second)
23		return super(TestGLIF1, self).assertEqual(first, second, msg=msg)
24
25	def pyToGLIF(self, py):
26		py = stripText(py)
27		glyph = Glyph()
28		exec(py, {"glyph" : glyph, "pointPen" : glyph})
29		glif = writeGlyphToString(glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, formatVersion=1, validate=True)
30		# discard the first line containing the xml declaration
31		return "\n".join(islice(glif.splitlines(), 1, None))
32
33	def glifToPy(self, glif):
34		glif = stripText(glif)
35		glif = "<?xml version=\"1.0\"?>\n" + glif
36		glyph = Glyph()
37		readGlyphFromString(glif, glyphObject=glyph, pointPen=glyph, validate=True)
38		return glyph.py()
39
40	def testTopElement(self):
41		# not glyph
42		glif = """
43		<notglyph name="a" format="1">
44			<outline>
45			</outline>
46		</notglyph>
47		"""
48		self.assertRaises(GlifLibError, self.glifToPy, glif)
49
50	def testName_legal(self):
51		# legal
52		glif = """
53		<glyph name="a" format="1">
54			<outline>
55			</outline>
56		</glyph>
57		"""
58		py = """
59		glyph.name = "a"
60		"""
61		resultGlif = self.pyToGLIF(py)
62		resultPy = self.glifToPy(glif)
63		self.assertEqual(glif, resultGlif)
64		self.assertEqual(py, resultPy)
65
66	def testName_empty(self):
67		# empty
68		glif = """
69		<glyph name="" format="1">
70			<outline>
71			</outline>
72		</glyph>
73		"""
74		py = """
75		glyph.name = ""
76		"""
77		self.assertRaises(GlifLibError, self.pyToGLIF, py)
78		self.assertRaises(GlifLibError, self.glifToPy, glif)
79
80	def testName_not_a_string(self):
81		# not a string
82		py = """
83		glyph.name = 1
84		"""
85		self.assertRaises(GlifLibError, self.pyToGLIF, py)
86
87	def testFormat_legal(self):
88		# legal
89		glif = """
90		<glyph name="a" format="1">
91			<outline>
92			</outline>
93		</glyph>
94		"""
95		py = """
96		glyph.name = "a"
97		"""
98		resultGlif = self.pyToGLIF(py)
99		resultPy = self.glifToPy(glif)
100		self.assertEqual(glif, resultGlif)
101		self.assertEqual(py, resultPy)
102
103	def testFormat_wrong_number(self):
104		# wrong number
105		glif = """
106		<glyph name="a" format="-1">
107			<outline>
108			</outline>
109		</glyph>
110		"""
111		self.assertRaises(GlifLibError, self.glifToPy, glif)
112
113	def testFormat_not_an_int(self):
114		# not an int
115		glif = """
116		<glyph name="a" format="A">
117			<outline>
118			</outline>
119		</glyph>
120		"""
121		self.assertRaises(GlifLibError, self.glifToPy, glif)
122
123	def testBogusGlyphStructure_unknown_element(self):
124		# unknown element
125		glif = """
126		<glyph name="a" format="1">
127			<unknown />
128		</glyph>
129		"""
130		self.assertRaises(GlifLibError, self.glifToPy, glif)
131
132	def testBogusGlyphStructure_content(self):
133		# content
134		glif = """
135		<glyph name="a" format="1">
136			Hello World.
137		</glyph>
138		"""
139		self.assertRaises(GlifLibError, self.glifToPy, glif)
140
141	def testAdvance_legal_width_and_height(self):
142		# legal: width and height
143		glif = """
144		<glyph name="a" format="1">
145			<advance height="200" width="100"/>
146			<outline>
147			</outline>
148		</glyph>
149		"""
150		py = """
151		glyph.name = "a"
152		glyph.width = 100
153		glyph.height = 200
154		"""
155		resultGlif = self.pyToGLIF(py)
156		resultPy = self.glifToPy(glif)
157		self.assertEqual(glif, resultGlif)
158		self.assertEqual(py, resultPy)
159
160	def testAdvance_legal_width_and_height_floats(self):
161		# legal: width and height floats
162		glif = """
163		<glyph name="a" format="1">
164			<advance height="200.1" width="100.1"/>
165			<outline>
166			</outline>
167		</glyph>
168		"""
169		py = """
170		glyph.name = "a"
171		glyph.width = 100.1
172		glyph.height = 200.1
173		"""
174		resultGlif = self.pyToGLIF(py)
175		resultPy = self.glifToPy(glif)
176		self.assertEqual(glif, resultGlif)
177		self.assertEqual(py, resultPy)
178
179	def testAdvance_legal_width(self):
180		# legal: width
181		glif = """
182		<glyph name="a" format="1">
183			<advance width="100"/>
184			<outline>
185			</outline>
186		</glyph>
187		"""
188		py = """
189		glyph.name = "a"
190		glyph.width = 100
191		"""
192		resultGlif = self.pyToGLIF(py)
193		resultPy = self.glifToPy(glif)
194		self.assertEqual(glif, resultGlif)
195		self.assertEqual(py, resultPy)
196
197	def testAdvance_legal_height(self):
198		# legal: height
199		glif = """
200		<glyph name="a" format="1">
201			<advance height="200"/>
202			<outline>
203			</outline>
204		</glyph>
205		"""
206		py = """
207		glyph.name = "a"
208		glyph.height = 200
209		"""
210		resultGlif = self.pyToGLIF(py)
211		resultPy = self.glifToPy(glif)
212		self.assertEqual(glif, resultGlif)
213		self.assertEqual(py, resultPy)
214
215	def testAdvance_illegal_width(self):
216		# illegal: not a number
217		glif = """
218		<glyph name="a" format="1">
219			<advance width="a"/>
220			<outline>
221			</outline>
222		</glyph>
223		"""
224		py = """
225		glyph.name = "a"
226		glyph.width = "a"
227		"""
228		self.assertRaises(GlifLibError, self.pyToGLIF, py)
229		self.assertRaises(GlifLibError, self.glifToPy, glif)
230
231	def testAdvance_illegal_height(self):
232		glif = """
233		<glyph name="a" format="1">
234			<advance height="a"/>
235			<outline>
236			</outline>
237		</glyph>
238		"""
239		py = """
240		glyph.name = "a"
241		glyph.height = "a"
242		"""
243		self.assertRaises(GlifLibError, self.pyToGLIF, py)
244		self.assertRaises(GlifLibError, self.glifToPy, glif)
245
246	def testUnicodes_legal(self):
247		# legal
248		glif = """
249		<glyph name="a" format="1">
250			<unicode hex="0061"/>
251			<outline>
252			</outline>
253		</glyph>
254		"""
255		py = """
256		glyph.name = "a"
257		glyph.unicodes = [97]
258		"""
259		resultGlif = self.pyToGLIF(py)
260		resultPy = self.glifToPy(glif)
261		self.assertEqual(glif, resultGlif)
262		self.assertEqual(py, resultPy)
263
264	def testUnicodes_legal_multiple(self):
265		glif = """
266		<glyph name="a" format="1">
267			<unicode hex="0062"/>
268			<unicode hex="0063"/>
269			<unicode hex="0061"/>
270			<outline>
271			</outline>
272		</glyph>
273		"""
274		py = """
275		glyph.name = "a"
276		glyph.unicodes = [98, 99, 97]
277		"""
278		resultGlif = self.pyToGLIF(py)
279		resultPy = self.glifToPy(glif)
280		self.assertEqual(glif, resultGlif)
281		self.assertEqual(py, resultPy)
282
283	def testUnicodes_illegal(self):
284		# illegal
285		glif = """
286		<glyph name="a" format="1">
287			<unicode hex="1.1"/>
288			<outline>
289			</outline>
290		</glyph>
291		"""
292		py = """
293		glyph.name = "zzzzzz"
294		glyph.unicodes = ["1.1"]
295		"""
296		self.assertRaises(GlifLibError, self.pyToGLIF, py)
297		self.assertRaises(GlifLibError, self.glifToPy, glif)
298
299	def testNote(self):
300		glif = """
301		<glyph name="a" format="1">
302			<note>
303				\U0001F4A9
304			</note>
305			<outline>
306			</outline>
307		</glyph>
308		"""
309		py = """
310		glyph.name = "a"
311		glyph.note = "��"
312		"""
313		resultGlif = self.pyToGLIF(py)
314		resultPy = self.glifToPy(glif)
315		self.assertEqual(glif, resultGlif)
316		self.assertEqual(py, resultPy)
317
318	def testLib_legal(self):
319		glif = """
320		<glyph name="a" format="1">
321			<outline>
322			</outline>
323			<lib>
324				<dict>
325					<key>dict</key>
326					<dict>
327						<key>hello</key>
328						<string>world</string>
329					</dict>
330					<key>float</key>
331					<real>2.5</real>
332					<key>int</key>
333					<integer>1</integer>
334					<key>list</key>
335					<array>
336						<string>a</string>
337						<string>b</string>
338						<integer>1</integer>
339						<real>2.5</real>
340					</array>
341					<key>string</key>
342					<string>a</string>
343				</dict>
344			</lib>
345		</glyph>
346		"""
347		py = """
348		glyph.name = "a"
349		glyph.lib = {"dict" : {"hello" : "world"}, "float" : 2.5, "int" : 1, "list" : ["a", "b", 1, 2.5], "string" : "a"}
350		"""
351		resultGlif = self.pyToGLIF(py)
352		resultPy = self.glifToPy(glif)
353		self.assertEqual(glif, resultGlif)
354		self.assertEqual(py, resultPy)
355
356	def testOutline_unknown_element(self):
357		# unknown element
358		glif = """
359		<glyph name="a" format="1">
360			<outline>
361				<unknown/>
362			</outline>
363		</glyph>
364		"""
365		self.assertRaises(GlifLibError, self.glifToPy, glif)
366
367	def testOutline_content(self):
368		# content
369		glif = """
370		<glyph name="a" format="1">
371			<outline>
372				hello
373			</outline>
374		</glyph>
375		"""
376		self.assertRaises(GlifLibError, self.glifToPy, glif)
377
378	def testComponent_legal(self):
379		# legal
380		glif = """
381		<glyph name="a" format="1">
382			<outline>
383				<component base="x" xScale="2" xyScale="3" yxScale="6" yScale="5" xOffset="1" yOffset="4"/>
384			</outline>
385		</glyph>
386		"""
387		py = """
388		glyph.name = "a"
389		pointPen.addComponent(*["x", (2, 3, 6, 5, 1, 4)])
390		"""
391		resultGlif = self.pyToGLIF(py)
392		resultPy = self.glifToPy(glif)
393		self.assertEqual(glif, resultGlif)
394		self.assertEqual(py, resultPy)
395
396	def testComponent_illegal_no_base(self):
397		# no base
398		glif = """
399		<glyph name="a" format="1">
400			<outline>
401				<component xScale="2" xyScale="3" yxScale="6" yScale="5" xOffset="1" yOffset="4"/>
402			</outline>
403		</glyph>
404		"""
405		self.assertRaises(GlifLibError, self.glifToPy, glif)
406
407	def testComponent_bogus_transformation(self):
408		# bogus values in transformation
409		glif = """
410		<glyph name="a" format="1">
411			<outline>
412				<component base="x" xScale="a" xyScale="3" yxScale="6" yScale="5" xOffset="1" yOffset="4"/>
413			</outline>
414		</glyph>
415		"""
416		py = """
417		glyph.name = "a"
418		pointPen.addComponent(*["x", ("a", 3, 6, 5, 1, 4)])
419		"""
420		self.assertRaises(GlifLibError, self.pyToGLIF, py)
421		self.assertRaises(GlifLibError, self.glifToPy, glif)
422		glif = """
423		<glyph name="a" format="1">
424			<outline>
425				<component base="x" xScale="a" xyScale="3" yxScale="6" yScale="5" xOffset="1" yOffset="4"/>
426			</outline>
427		</glyph>
428		"""
429		py = """
430		glyph.name = "a"
431		pointPen.addComponent(*["x", (2, "a", 6, 5, 1, 4)])
432		"""
433		self.assertRaises(GlifLibError, self.pyToGLIF, py)
434		self.assertRaises(GlifLibError, self.glifToPy, glif)
435		glif = """
436		<glyph name="a" format="1">
437			<outline>
438				<component base="x" xScale="2" xyScale="3" yxScale="a" yScale="5" xOffset="1" yOffset="4"/>
439			</outline>
440		</glyph>
441		"""
442		py = """
443		glyph.name = "a"
444		pointPen.addComponent(*["x", (2, 3, "a", 5, 1, 4)])
445		"""
446		self.assertRaises(GlifLibError, self.pyToGLIF, py)
447		self.assertRaises(GlifLibError, self.glifToPy, glif)
448		glif = """
449		<glyph name="a" format="1">
450			<outline>
451				<component base="x" xScale="2" xyScale="3" yxScale="6" yScale="a" xOffset="1" yOffset="4"/>
452			</outline>
453		</glyph>
454		"""
455		py = """
456		glyph.name = "a"
457		pointPen.addComponent(*["x", (2, 3, 6, "a", 1, 4)])
458		"""
459		self.assertRaises(GlifLibError, self.pyToGLIF, py)
460		self.assertRaises(GlifLibError, self.glifToPy, glif)
461		glif = """
462		<glyph name="a" format="1">
463			<outline>
464				<component base="x" xScale="2" xyScale="3" yxScale="6" yScale="5" xOffset="a" yOffset="4"/>
465			</outline>
466		</glyph>
467		"""
468		py = """
469		glyph.name = "a"
470		pointPen.addComponent(*["x", (2, 3, 6, 5, "a", 4)])
471		"""
472		self.assertRaises(GlifLibError, self.pyToGLIF, py)
473		self.assertRaises(GlifLibError, self.glifToPy, glif)
474		glif = """
475		<glyph name="a" format="1">
476			<outline>
477				<component base="x" xScale="2" xyScale="3" yxScale="6" yScale="5" xOffset="1" yOffset="a"/>
478			</outline>
479		</glyph>
480		"""
481		py = """
482		glyph.name = "a"
483		pointPen.addComponent(*["x", (2, 3, 6, 5, 1, "a")])
484		"""
485		self.assertRaises(GlifLibError, self.pyToGLIF, py)
486		self.assertRaises(GlifLibError, self.glifToPy, glif)
487
488	def testContour_legal_one_contour(self):
489		# legal: one contour
490		glif = """
491		<glyph name="a" format="1">
492			<outline>
493				<contour>
494				</contour>
495			</outline>
496		</glyph>
497		"""
498		py = """
499		glyph.name = "a"
500		pointPen.beginPath()
501		pointPen.endPath()
502		"""
503		resultGlif = self.pyToGLIF(py)
504		resultPy = self.glifToPy(glif)
505		self.assertEqual(glif, resultGlif)
506		self.assertEqual(py, resultPy)
507
508	def testContour_legal_two_contours(self):
509		# legal: two contours
510		glif = """
511		<glyph name="a" format="1">
512			<outline>
513				<contour>
514					<point x="1" y="2" type="move"/>
515					<point x="10" y="20" type="line"/>
516				</contour>
517				<contour>
518					<point x="1" y="2" type="move"/>
519					<point x="10" y="20" type="line"/>
520				</contour>
521			</outline>
522		</glyph>
523		"""
524		py = """
525		glyph.name = "a"
526		pointPen.beginPath()
527		pointPen.addPoint(*[(1, 2)], **{"segmentType" : "move", "smooth" : False})
528		pointPen.addPoint(*[(10, 20)], **{"segmentType" : "line", "smooth" : False})
529		pointPen.endPath()
530		pointPen.beginPath()
531		pointPen.addPoint(*[(1, 2)], **{"segmentType" : "move", "smooth" : False})
532		pointPen.addPoint(*[(10, 20)], **{"segmentType" : "line", "smooth" : False})
533		pointPen.endPath()
534		"""
535		resultGlif = self.pyToGLIF(py)
536		resultPy = self.glifToPy(glif)
537		self.assertEqual(glif, resultGlif)
538		self.assertEqual(py, resultPy)
539
540	def testContour_illegal_unkonwn_element(self):
541		# unknown element
542		glif = """
543		<glyph name="a" format="1">
544			<outline>
545				<contour>
546					<unknown/>
547				</contour>
548			</outline>
549		</glyph>
550		"""
551		self.assertRaises(GlifLibError, self.glifToPy, glif)
552
553	def testPointCoordinates_legal_int(self):
554		# legal: int
555		glif = """
556		<glyph name="a" format="1">
557			<outline>
558				<contour>
559					<point x="1" y="-2" type="move"/>
560					<point x="0" y="0" type="line" name="this is here so that the contour isn't seen as an anchor"/>
561				</contour>
562			</outline>
563		</glyph>
564		"""
565		py = """
566		glyph.name = "a"
567		pointPen.beginPath()
568		pointPen.addPoint(*[(1, -2)], **{"segmentType" : "move", "smooth" : False})
569		pointPen.addPoint(*[(0, 0)], **{"name" : "this is here so that the contour isn't seen as an anchor", "segmentType" : "line", "smooth" : False})
570		pointPen.endPath()
571		"""
572		resultGlif = self.pyToGLIF(py)
573		resultPy = self.glifToPy(glif)
574		self.assertEqual(glif, resultGlif)
575		self.assertEqual(py, resultPy)
576
577	def testPointCoordinates_legal_float(self):
578		# legal: float
579		glif = """
580		<glyph name="a" format="1">
581			<outline>
582				<contour>
583					<point x="1.1" y="-2.2" type="move"/>
584					<point x="0" y="0" type="line" name="this is here so that the contour isn't seen as an anchor"/>
585				</contour>
586			</outline>
587		</glyph>
588		"""
589		py = """
590		glyph.name = "a"
591		pointPen.beginPath()
592		pointPen.addPoint(*[(1.1, -2.2)], **{"segmentType" : "move", "smooth" : False})
593		pointPen.addPoint(*[(0, 0)], **{"name" : "this is here so that the contour isn't seen as an anchor", "segmentType" : "line", "smooth" : False})
594		pointPen.endPath()
595		"""
596		resultGlif = self.pyToGLIF(py)
597		resultPy = self.glifToPy(glif)
598		self.assertEqual(glif, resultGlif)
599		self.assertEqual(py, resultPy)
600
601	def testPointCoordinates_illegal_x(self):
602		# illegal: string
603		glif = """
604		<glyph name="a" format="1">
605			<outline>
606				<contour>
607					<point x="a" y="2" type="move"/>
608					<point x="0" y="0" type="line" name="this is here so that the contour isn't seen as an anchor"/>
609				</contour>
610			</outline>
611		</glyph>
612		"""
613		py = """
614		glyph.name = "a"
615		pointPen.beginPath()
616		pointPen.addPoint(*[("a", 2)], **{"segmentType" : "move", "smooth" : False})
617		pointPen.addPoint(*[(0, 0)], **{"name" : "this is here so that the contour isn't seen as an anchor", "segmentType" : "line", "smooth" : False})
618		pointPen.endPath()
619		"""
620		self.assertRaises(GlifLibError, self.pyToGLIF, py)
621		self.assertRaises(GlifLibError, self.glifToPy, glif)
622
623	def testPointCoordinates_illegal_y(self):
624		# legal: int
625		glif = """
626		<glyph name="a" format="1">
627			<outline>
628				<contour>
629					<point x="1" y="a" type="move"/>
630					<point x="0" y="0" type="line" name="this is here so that the contour isn't seen as an anchor"/>
631				</contour>
632			</outline>
633		</glyph>
634		"""
635		py = """
636		glyph.name = "a"
637		pointPen.beginPath()
638		pointPen.addPoint(*[(1, "a")], **{"segmentType" : "move", "smooth" : False})
639		pointPen.addPoint(*[(0, 0)], **{"name" : "this is here so that the contour isn't seen as an anchor", "segmentType" : "line", "smooth" : False})
640		pointPen.endPath()
641		"""
642		self.assertRaises(GlifLibError, self.pyToGLIF, py)
643		self.assertRaises(GlifLibError, self.glifToPy, glif)
644
645	def testPointTypeMove_legal(self):
646		# legal
647		glif = """
648		<glyph name="a" format="1">
649			<outline>
650				<contour>
651					<point x="1" y="-2" type="move"/>
652					<point x="3" y="-4" type="line"/>
653				</contour>
654			</outline>
655		</glyph>
656		"""
657		py = """
658		glyph.name = "a"
659		pointPen.beginPath()
660		pointPen.addPoint(*[(1, -2)], **{"segmentType" : "move", "smooth" : False})
661		pointPen.addPoint(*[(3, -4)], **{"segmentType" : "line", "smooth" : False})
662		pointPen.endPath()
663		"""
664		resultGlif = self.pyToGLIF(py)
665		resultPy = self.glifToPy(glif)
666		self.assertEqual(glif, resultGlif)
667		self.assertEqual(py, resultPy)
668
669	def testPointTypeMove_legal_smooth(self):
670		# legal: smooth=True
671		glif = """
672		<glyph name="a" format="1">
673			<outline>
674				<contour>
675					<point x="1" y="-2" type="move" smooth="yes"/>
676					<point x="3" y="-4" type="line"/>
677				</contour>
678			</outline>
679		</glyph>
680		"""
681		py = """
682		glyph.name = "a"
683		pointPen.beginPath()
684		pointPen.addPoint(*[(1, -2)], **{"segmentType" : "move", "smooth" : True})
685		pointPen.addPoint(*[(3, -4)], **{"segmentType" : "line", "smooth" : False})
686		pointPen.endPath()
687		"""
688		resultGlif = self.pyToGLIF(py)
689		resultPy = self.glifToPy(glif)
690		self.assertEqual(glif, resultGlif)
691		self.assertEqual(py, resultPy)
692
693	def testPointTypeMove_illegal_not_at_start(self):
694		# illegal: not at start
695		glif = """
696		<glyph name="a" format="1">
697			<outline>
698				<contour>
699					<point x="3" y="-4" type="line"/>
700					<point x="1" y="-2" type="move"/>
701				</contour>
702			</outline>
703		</glyph>
704		"""
705		py = """
706		glyph.name = "a"
707		pointPen.beginPath()
708		pointPen.addPoint(*[(3, -4)], **{"segmentType" : "line", "smooth" : False})
709		pointPen.addPoint(*[(1, -2)], **{"segmentType" : "move", "smooth" : False})
710		pointPen.endPath()
711		"""
712		self.assertRaises(GlifLibError, self.pyToGLIF, py)
713		self.assertRaises(GlifLibError, self.glifToPy, glif)
714
715	def testPointTypeLine_legal(self):
716		# legal
717		glif = """
718		<glyph name="a" format="1">
719			<outline>
720				<contour>
721					<point x="1" y="-2" type="move"/>
722					<point x="3" y="-4" type="line"/>
723				</contour>
724			</outline>
725		</glyph>
726		"""
727		py = """
728		glyph.name = "a"
729		pointPen.beginPath()
730		pointPen.addPoint(*[(1, -2)], **{"segmentType" : "move", "smooth" : False})
731		pointPen.addPoint(*[(3, -4)], **{"segmentType" : "line", "smooth" : False})
732		pointPen.endPath()
733		"""
734		resultGlif = self.pyToGLIF(py)
735		resultPy = self.glifToPy(glif)
736		self.assertEqual(glif, resultGlif)
737		self.assertEqual(py, resultPy)
738
739	def testPointTypeLine_legal_start_of_contour(self):
740		# legal: start of contour
741		glif = """
742		<glyph name="a" format="1">
743			<outline>
744				<contour>
745					<point x="1" y="-2" type="line"/>
746					<point x="3" y="-4" type="line"/>
747				</contour>
748			</outline>
749		</glyph>
750		"""
751		py = """
752		glyph.name = "a"
753		pointPen.beginPath()
754		pointPen.addPoint(*[(1, -2)], **{"segmentType" : "line", "smooth" : False})
755		pointPen.addPoint(*[(3, -4)], **{"segmentType" : "line", "smooth" : False})
756		pointPen.endPath()
757		"""
758		resultGlif = self.pyToGLIF(py)
759		resultPy = self.glifToPy(glif)
760		self.assertEqual(glif, resultGlif)
761		self.assertEqual(py, resultPy)
762
763	def testPointTypeLine_legal_smooth(self):
764		# legal: smooth=True
765		glif = """
766		<glyph name="a" format="1">
767			<outline>
768				<contour>
769					<point x="1" y="-2" type="move"/>
770					<point x="3" y="-4" type="line" smooth="yes"/>
771				</contour>
772			</outline>
773		</glyph>
774		"""
775		py = """
776		glyph.name = "a"
777		pointPen.beginPath()
778		pointPen.addPoint(*[(1, -2)], **{"segmentType" : "move", "smooth" : False})
779		pointPen.addPoint(*[(3, -4)], **{"segmentType" : "line", "smooth" : True})
780		pointPen.endPath()
781		"""
782		resultGlif = self.pyToGLIF(py)
783		resultPy = self.glifToPy(glif)
784		self.assertEqual(glif, resultGlif)
785		self.assertEqual(py, resultPy)
786
787	def testPointTypeCurve_legal(self):
788		# legal
789		glif = """
790		<glyph name="a" format="1">
791			<outline>
792				<contour>
793					<point x="0" y="0" type="move"/>
794					<point x="0" y="65"/>
795					<point x="65" y="200"/>
796					<point x="100" y="200" type="curve"/>
797				</contour>
798			</outline>
799		</glyph>
800		"""
801		py = """
802		glyph.name = "a"
803		pointPen.beginPath()
804		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
805		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
806		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
807		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : False})
808		pointPen.endPath()
809		"""
810		resultGlif = self.pyToGLIF(py)
811		resultPy = self.glifToPy(glif)
812		self.assertEqual(glif, resultGlif)
813		self.assertEqual(py, resultPy)
814
815	def testPointTypeCurve_legal_start_of_contour(self):
816		# legal: start of contour
817		glif = """
818		<glyph name="a" format="1">
819			<outline>
820				<contour>
821					<point x="100" y="200" type="curve"/>
822					<point x="0" y="65"/>
823					<point x="65" y="200"/>
824				</contour>
825			</outline>
826		</glyph>
827		"""
828		py = """
829		glyph.name = "a"
830		pointPen.beginPath()
831		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : False})
832		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
833		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
834		pointPen.endPath()
835		"""
836		resultGlif = self.pyToGLIF(py)
837		resultPy = self.glifToPy(glif)
838		self.assertEqual(glif, resultGlif)
839		self.assertEqual(py, resultPy)
840
841	def testPointTypeCurve_legal_smooth(self):
842		# legal: smooth=True
843		glif = """
844		<glyph name="a" format="1">
845			<outline>
846				<contour>
847					<point x="0" y="0" type="move"/>
848					<point x="0" y="65"/>
849					<point x="65" y="200"/>
850					<point x="100" y="200" type="curve" smooth="yes"/>
851				</contour>
852			</outline>
853		</glyph>
854		"""
855		py = """
856		glyph.name = "a"
857		pointPen.beginPath()
858		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
859		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
860		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
861		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : True})
862		pointPen.endPath()
863		"""
864		resultGlif = self.pyToGLIF(py)
865		resultPy = self.glifToPy(glif)
866		self.assertEqual(glif, resultGlif)
867		self.assertEqual(py, resultPy)
868
869	def testPointTypeCurve_legal_no_off_curves(self):
870		# legal: no off-curves
871		glif = """
872		<glyph name="a" format="1">
873			<outline>
874				<contour>
875					<point x="0" y="0" type="move"/>
876					<point x="100" y="200" type="curve"/>
877				</contour>
878			</outline>
879		</glyph>
880		"""
881		py = """
882		glyph.name = "a"
883		pointPen.beginPath()
884		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
885		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : False})
886		pointPen.endPath()
887		"""
888		resultGlif = self.pyToGLIF(py)
889		resultPy = self.glifToPy(glif)
890		self.assertEqual(glif, resultGlif)
891		self.assertEqual(py, resultPy)
892
893	def testPointTypeCurve_legal_1_off_curve(self):
894		# legal: 1 off-curve
895		glif = """
896		<glyph name="a" format="1">
897			<outline>
898				<contour>
899					<point x="0" y="0" type="move"/>
900					<point x="50" y="100"/>
901					<point x="100" y="200" type="curve"/>
902				</contour>
903			</outline>
904		</glyph>
905		"""
906		py = """
907		glyph.name = "a"
908		pointPen.beginPath()
909		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
910		pointPen.addPoint(*[(50, 100)], **{"smooth" : False})
911		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : False})
912		pointPen.endPath()
913		"""
914		resultGlif = self.pyToGLIF(py)
915		resultPy = self.glifToPy(glif)
916		self.assertEqual(glif, resultGlif)
917		self.assertEqual(py, resultPy)
918
919	def testPointTypeCurve_illegal_3_off_curves(self):
920		# illegal: 3 off-curves
921		glif = """
922		<glyph name="a" format="1">
923			<outline>
924				<contour>
925					<point x="0" y="0" type="move"/>
926					<point x="0" y="100"/>
927					<point x="35" y="125"/>
928					<point x="65" y="200"/>
929					<point x="100" y="200" type="curve"/>
930				</contour>
931			</outline>
932		</glyph>
933		"""
934		py = """
935		glyph.name = "a"
936		pointPen.beginPath()
937		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
938		pointPen.addPoint(*[(0, 100)], **{"smooth" : False})
939		pointPen.addPoint(*[(35, 125)], **{"smooth" : False})
940		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
941		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : False})
942		pointPen.endPath()
943		"""
944		self.assertRaises(GlifLibError, self.pyToGLIF, py)
945		self.assertRaises(GlifLibError, self.glifToPy, glif)
946
947	def testPointQCurve_legal(self):
948		# legal
949		glif = """
950		<glyph name="a" format="1">
951			<outline>
952				<contour>
953					<point x="0" y="0" type="move"/>
954					<point x="0" y="65"/>
955					<point x="65" y="200"/>
956					<point x="100" y="200" type="qcurve"/>
957				</contour>
958			</outline>
959		</glyph>
960		"""
961		py = """
962		glyph.name = "a"
963		pointPen.beginPath()
964		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
965		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
966		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
967		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "qcurve", "smooth" : False})
968		pointPen.endPath()
969		"""
970		resultGlif = self.pyToGLIF(py)
971		resultPy = self.glifToPy(glif)
972		self.assertEqual(glif, resultGlif)
973		self.assertEqual(py, resultPy)
974
975	def testPointQCurve_legal_start_of_contour(self):
976		# legal: start of contour
977		glif = """
978		<glyph name="a" format="1">
979			<outline>
980				<contour>
981					<point x="100" y="200" type="qcurve"/>
982					<point x="0" y="65"/>
983					<point x="65" y="200"/>
984				</contour>
985			</outline>
986		</glyph>
987		"""
988		py = """
989		glyph.name = "a"
990		pointPen.beginPath()
991		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "qcurve", "smooth" : False})
992		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
993		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
994		pointPen.endPath()
995		"""
996		resultGlif = self.pyToGLIF(py)
997		resultPy = self.glifToPy(glif)
998		self.assertEqual(glif, resultGlif)
999		self.assertEqual(py, resultPy)
1000
1001	def testPointQCurve_legal_smooth(self):
1002		# legal: smooth=True
1003		glif = """
1004		<glyph name="a" format="1">
1005			<outline>
1006				<contour>
1007					<point x="0" y="0" type="move"/>
1008					<point x="0" y="65"/>
1009					<point x="65" y="200"/>
1010					<point x="100" y="200" type="qcurve" smooth="yes"/>
1011				</contour>
1012			</outline>
1013		</glyph>
1014		"""
1015		py = """
1016		glyph.name = "a"
1017		pointPen.beginPath()
1018		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
1019		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
1020		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
1021		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "qcurve", "smooth" : True})
1022		pointPen.endPath()
1023		"""
1024		resultGlif = self.pyToGLIF(py)
1025		resultPy = self.glifToPy(glif)
1026		self.assertEqual(glif, resultGlif)
1027		self.assertEqual(py, resultPy)
1028
1029	def testPointQCurve_legal_no_off_curves(self):
1030		# legal: no off-curves
1031		glif = """
1032		<glyph name="a" format="1">
1033			<outline>
1034				<contour>
1035					<point x="0" y="0" type="move"/>
1036					<point x="100" y="200" type="qcurve"/>
1037				</contour>
1038			</outline>
1039		</glyph>
1040		"""
1041		py = """
1042		glyph.name = "a"
1043		pointPen.beginPath()
1044		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
1045		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "qcurve", "smooth" : False})
1046		pointPen.endPath()
1047		"""
1048		resultGlif = self.pyToGLIF(py)
1049		resultPy = self.glifToPy(glif)
1050		self.assertEqual(glif, resultGlif)
1051		self.assertEqual(py, resultPy)
1052
1053	def testPointQCurve_legal_one_off_curve(self):
1054		# legal: 1 off-curve
1055		glif = """
1056		<glyph name="a" format="1">
1057			<outline>
1058				<contour>
1059					<point x="0" y="0" type="move"/>
1060					<point x="50" y="100"/>
1061					<point x="100" y="200" type="qcurve"/>
1062				</contour>
1063			</outline>
1064		</glyph>
1065		"""
1066		py = """
1067		glyph.name = "a"
1068		pointPen.beginPath()
1069		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
1070		pointPen.addPoint(*[(50, 100)], **{"smooth" : False})
1071		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "qcurve", "smooth" : False})
1072		pointPen.endPath()
1073		"""
1074		resultGlif = self.pyToGLIF(py)
1075		resultPy = self.glifToPy(glif)
1076		self.assertEqual(glif, resultGlif)
1077		self.assertEqual(py, resultPy)
1078
1079	def testPointQCurve_legal_3_off_curves(self):
1080		# legal: 3 off-curves
1081		glif = """
1082		<glyph name="a" format="1">
1083			<outline>
1084				<contour>
1085					<point x="0" y="0" type="move"/>
1086					<point x="0" y="100"/>
1087					<point x="35" y="125"/>
1088					<point x="65" y="200"/>
1089					<point x="100" y="200" type="qcurve"/>
1090				</contour>
1091			</outline>
1092		</glyph>
1093		"""
1094		py = """
1095		glyph.name = "a"
1096		pointPen.beginPath()
1097		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
1098		pointPen.addPoint(*[(0, 100)], **{"smooth" : False})
1099		pointPen.addPoint(*[(35, 125)], **{"smooth" : False})
1100		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
1101		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "qcurve", "smooth" : False})
1102		pointPen.endPath()
1103		"""
1104		resultGlif = self.pyToGLIF(py)
1105		resultPy = self.glifToPy(glif)
1106		self.assertEqual(glif, resultGlif)
1107		self.assertEqual(py, resultPy)
1108
1109	def testSpecialCaseQCurve(self):
1110		# contour with no on curve
1111		glif = """
1112		<glyph name="a" format="1">
1113			<outline>
1114				<contour>
1115					<point x="0" y="0"/>
1116					<point x="0" y="100"/>
1117					<point x="100" y="100"/>
1118					<point x="100" y="0"/>
1119				</contour>
1120			</outline>
1121		</glyph>
1122		"""
1123		py = """
1124		glyph.name = "a"
1125		pointPen.beginPath()
1126		pointPen.addPoint(*[(0, 0)], **{"smooth" : False})
1127		pointPen.addPoint(*[(0, 100)], **{"smooth" : False})
1128		pointPen.addPoint(*[(100, 100)], **{"smooth" : False})
1129		pointPen.addPoint(*[(100, 0)], **{"smooth" : False})
1130		pointPen.endPath()
1131		"""
1132		resultGlif = self.pyToGLIF(py)
1133		resultPy = self.glifToPy(glif)
1134		self.assertEqual(glif, resultGlif)
1135		self.assertEqual(py, resultPy)
1136
1137	def testPointTypeOffCurve_legal(self):
1138		# legal
1139		glif = """
1140		<glyph name="a" format="1">
1141			<outline>
1142				<contour>
1143					<point x="0" y="0" type="move"/>
1144					<point x="0" y="65"/>
1145					<point x="65" y="200"/>
1146					<point x="100" y="200" type="curve"/>
1147				</contour>
1148			</outline>
1149		</glyph>
1150		"""
1151		py = """
1152		glyph.name = "a"
1153		pointPen.beginPath()
1154		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
1155		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
1156		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
1157		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : False})
1158		pointPen.endPath()
1159		"""
1160		resultGlif = self.pyToGLIF(py)
1161		resultPy = self.glifToPy(glif)
1162		self.assertEqual(glif, resultGlif)
1163		self.assertEqual(py, resultPy)
1164
1165	def testPointTypeOffCurve_legal_start_of_contour(self):
1166		# legal: start of contour
1167		glif = """
1168		<glyph name="a" format="1">
1169			<outline>
1170				<contour>
1171					<point x="0" y="65"/>
1172					<point x="65" y="200"/>
1173					<point x="100" y="200" type="curve"/>
1174				</contour>
1175			</outline>
1176		</glyph>
1177		"""
1178		py = """
1179		glyph.name = "a"
1180		pointPen.beginPath()
1181		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
1182		pointPen.addPoint(*[(65, 200)], **{"smooth" : False})
1183		pointPen.addPoint(*[(100, 200)], **{"segmentType" : "curve", "smooth" : False})
1184		pointPen.endPath()
1185		"""
1186		resultGlif = self.pyToGLIF(py)
1187		resultPy = self.glifToPy(glif)
1188		self.assertEqual(glif, resultGlif)
1189		self.assertEqual(py, resultPy)
1190
1191	def testPointTypeOffCurve_illegal_before_move(self):
1192		# before move
1193		glif = """
1194		<glyph name="a" format="1">
1195			<outline>
1196				<contour>
1197					<point x="0" y="65"/>
1198					<point x="0" y="0" type="move"/>
1199				</contour>
1200			</outline>
1201		</glyph>
1202		"""
1203		py = """
1204		glyph.name = "a"
1205		pointPen.beginPath()
1206		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
1207		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "move", "smooth" : False})
1208		pointPen.endPath()
1209		"""
1210		self.assertRaises(GlifLibError, self.pyToGLIF, py)
1211		self.assertRaises(GlifLibError, self.glifToPy, glif)
1212
1213	def testPointTypeOffCurve_illegal_before_line(self):
1214		# before line
1215		glif = """
1216		<glyph name="a" format="1">
1217			<outline>
1218				<contour>
1219					<point x="0" y="65"/>
1220					<point x="0" y="0" type="line"/>
1221				</contour>
1222			</outline>
1223		</glyph>
1224		"""
1225		py = """
1226		glyph.name = "a"
1227		pointPen.beginPath()
1228		pointPen.addPoint(*[(0, 65)], **{"smooth" : False})
1229		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "line", "smooth" : False})
1230		pointPen.endPath()
1231		"""
1232		self.assertRaises(GlifLibError, self.pyToGLIF, py)
1233		self.assertRaises(GlifLibError, self.glifToPy, glif)
1234
1235	def testPointTypeOffCurve_illegal_smooth(self):
1236		# smooth=True
1237		glif = """
1238		<glyph name="a" format="1">
1239			<outline>
1240				<contour>
1241					<point x="0" y="65" smooth="yes"/>
1242					<point x="0" y="0" type="curve"/>
1243				</contour>
1244			</outline>
1245		</glyph>
1246		"""
1247		py = """
1248		glyph.name = "a"
1249		pointPen.beginPath()
1250		pointPen.addPoint(*[(0, 65)], **{"smooth" : True})
1251		pointPen.addPoint(*[(0, 0)], **{"segmentType" : "curve", "smooth" : False})
1252		pointPen.endPath()
1253		"""
1254		self.assertRaises(GlifLibError, self.pyToGLIF, py)
1255		self.assertRaises(GlifLibError, self.glifToPy, glif)
1256
1257	def testSinglePoint_legal_without_name(self):
1258		# legal
1259		# glif format 1 single point without a name was not an anchor
1260		glif = """
1261		<glyph name="a" format="1">
1262			<outline>
1263				<contour>
1264					<point x="1" y="2" type="move"/>
1265				</contour>
1266			</outline>
1267		</glyph>
1268		"""
1269		py = """
1270		glyph.name = "a"
1271		pointPen.beginPath()
1272		pointPen.addPoint(*[(1, 2)], **{"segmentType" : "move", "smooth" : False})
1273		pointPen.endPath()
1274		"""
1275		resultGlif = self.pyToGLIF(py)
1276		resultPy = self.glifToPy(glif)
1277		self.assertEqual(glif, resultGlif)
1278		self.assertEqual(py, resultPy)
1279
1280	def testAnchor_legal_with_name(self):
1281		glif = """
1282		<glyph name="a" format="1">
1283			<outline>
1284				<contour>
1285					<point x="1" y="2" type="move" name="test"/>
1286				</contour>
1287			</outline>
1288		</glyph>
1289		"""
1290		py = """
1291		glyph.name = "a"
1292		glyph.anchors = [{"name" : "test", "x" : 1, "y" : 2}]
1293		"""
1294		resultGlif = self.pyToGLIF(py)
1295		resultPy = self.glifToPy(glif)
1296		self.assertEqual(glif, resultGlif)
1297		self.assertEqual(py, resultPy)
1298
1299	def testOpenContourLooseOffCurves_legal(self):
1300		# a piece of software was writing this kind of structure
1301		glif = """
1302		<glyph name="a" format="1">
1303			<outline>
1304				<contour>
1305					<point x="1" y="2" type="move"/>
1306					<point x="1" y="2"/>
1307					<point x="1" y="2"/>
1308					<point x="1" y="2" type="curve"/>
1309					<point x="1" y="2"/>
1310				</contour>
1311			</outline>
1312		</glyph>
1313		"""
1314		expectedPy = """
1315		glyph.name = "a"
1316		pointPen.beginPath()
1317		pointPen.addPoint(*[(1, 2)], **{"segmentType" : "move", "smooth" : False})
1318		pointPen.addPoint(*[(1, 2)], **{"smooth" : False})
1319		pointPen.addPoint(*[(1, 2)], **{"smooth" : False})
1320		pointPen.addPoint(*[(1, 2)], **{"segmentType" : "curve", "smooth" : False})
1321		pointPen.endPath()
1322		"""
1323		resultPy = self.glifToPy(glif)
1324		self.assertEqual(resultPy, expectedPy)
1325
1326	def testOpenContourLooseOffCurves_illegal(self):
1327		py = """
1328		glyph.name = "a"
1329		pointPen.beginPath()
1330		pointPen.addPoint(*[(1, 2)], **{"segmentType" : "move", "smooth" : False})
1331		pointPen.addPoint(*[(1, 2)], **{"smooth" : False})
1332		pointPen.addPoint(*[(1, 2)], **{"smooth" : False})
1333		pointPen.addPoint(*[(1, 2)], **{"segmentType" : "curve", "smooth" : False})
1334		pointPen.addPoint(*[(1, 2)], **{"smooth" : False})
1335		pointPen.endPath()
1336		"""
1337		self.assertRaises(GlifLibError, self.pyToGLIF, py)
1338
1339
1340if __name__ == "__main__":
1341	from ufoLib.test.testSupport import runTests
1342	runTests()
1343