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