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