def test_glyph_lib_componentsAlignment_and_componentsLocked(self): font = generate_minimal_font() add_glyph(font, "a") add_glyph(font, "b") composite_glyph = add_glyph(font, "c") add_component(font, "c", "a", (1, 0, 0, 1, 0, 0)) add_component(font, "c", "b", (1, 0, 0, 1, 0, 100)) comp1 = composite_glyph.layers[0].components[0] comp2 = composite_glyph.layers[0].components[1] self.assertEqual(comp1.alignment, 0) self.assertEqual(comp1.locked, False) ufo = to_ufos(font)[0] # all components have deault values, no lib key is written self.assertNotIn(GLYPHS_PREFIX + "componentsAlignment", ufo["c"].lib) self.assertNotIn(GLYPHS_PREFIX + "componentsLocked", ufo["c"].lib) comp2.alignment = -1 comp1.locked = True ufo = to_ufos(font)[0] # if any component has a non-default alignment/locked values, write # list of values for all of them self.assertIn(GLYPHS_PREFIX + "componentsAlignment", ufo["c"].lib) self.assertEqual(ufo["c"].lib[GLYPHS_PREFIX + "componentsAlignment"], [0, -1]) self.assertIn(GLYPHS_PREFIX + "componentsLocked", ufo["c"].lib) self.assertEqual(ufo["c"].lib[GLYPHS_PREFIX + "componentsLocked"], [True, False])
def test_GDEF(self): font = generate_minimal_font() for glyph in ('space', 'A', 'A.alt', 'wigglylinebelowcomb', 'wigglylinebelowcomb.alt', 'fi', 'fi.alt', 't_e_s_t', 't_e_s_t.alt'): add_glyph(font, glyph) add_anchor(font, 'A', 'bottom', 300, -10) add_anchor(font, 'wigglylinebelowcomb', '_bottom', 100, 40) add_anchor(font, 'fi', 'caret_1', 150, 0) add_anchor(font, 't_e_s_t.alt', 'caret_1', 200, 0) add_anchor(font, 't_e_s_t.alt', 'caret_2', 400, 0) add_anchor(font, 't_e_s_t.alt', 'caret_3', 600, 0) ufo = to_ufos(font)[0] self.assertEqual(ufo.features.text.splitlines(), [ 'table GDEF {', ' # automatic', ' GlyphClassDef', ' [A], # Base', ' [fi t_e_s_t.alt], # Liga', ' [wigglylinebelowcomb wigglylinebelowcomb.alt], # Mark', ' ;', ' LigatureCaretByPos fi 150;', ' LigatureCaretByPos t_e_s_t.alt 200 400 600;', '} GDEF;', ])
def test_category(self): font = generate_minimal_font() add_glyph(font, 'foo')['category'] = 'Mark' add_glyph(font, 'bar') ufo = to_ufos(font)[0] category_key = GLYPHLIB_PREFIX + 'category' self.assertEqual(ufo['foo'].lib.get(category_key), 'Mark') self.assertFalse(category_key in ufo['bar'].lib)
def test_subCategory(self): font = generate_minimal_font() add_glyph(font, 'foo')['subCategory'] = 'Nonspacing' add_glyph(font, 'bar') ufo = to_ufos(font)[0] subCategory_key = GLYPHLIB_PREFIX + 'subCategory' self.assertEqual(ufo['foo'].lib.get(subCategory_key), 'Nonspacing') self.assertFalse(subCategory_key in ufo['bar'].lib)
def test_GDEF_fractional_caret_position(self): # Some Glyphs sources happen to contain fractional caret positions. # In the Adobe feature file syntax (and binary OpenType GDEF tables), # caret positions must be integers. font = generate_minimal_font() add_glyph(font, 'fi') add_anchor(font, 'fi', 'caret_1', 499.9876, 0) self.assertIn('LigatureCaretByPos fi 500;', to_ufos(font)[0].features.text)
def test_GDEF_custom_category_subCategory(self): font = generate_minimal_font() add_glyph(font, 'foo')['subCategory'] = 'Ligature' add_anchor(font, 'foo', 'top', 400, 1000) bar = add_glyph(font, 'bar') bar['category'], bar['subCategory'] = 'Mark', 'Nonspacing' baz = add_glyph(font, 'baz') baz['category'], baz['subCategory'] = 'Mark', 'Spacing Combining' features = to_ufos(font)[0].features.text self.assertIn('[foo], # Liga', features) self.assertIn('[bar baz], # Mark', features)
def test_set_glyphOrder_no_custom_param(self): font = generate_minimal_font() add_glyph(font, 'C') add_glyph(font, 'B') add_glyph(font, 'A') add_glyph(font, 'Z') glyphOrder = to_ufos(font)[0].lib[PUBLIC_PREFIX + 'glyphOrder'] self.assertEqual(glyphOrder, ['C', 'B', 'A', 'Z'])
def test_fail_during_anchor_propagation(self): """Fix https://github.com/googlei18n/glyphsLib/issues/317""" font = generate_minimal_font() glyphs = ( # This glyph has components that don't exist in the font ('yodyod', [('yod', 0, 0), ('yod', 100, 0)], []), ) for name, component_data, anchor_data in glyphs: add_glyph(font, name) for n, x, y, in anchor_data: add_anchor(font, name, n, x, y) for n, x, y in component_data: add_component(font, name, n, (1, 0, 0, 1, x, y)) # We just want the call to `to_ufos` to not crash assert to_ufos(font)
def test_set_glyphOrder_with_custom_param(self): font = generate_minimal_font() font.customParameters['glyphOrder'] = ['A', 'B', 'C'] add_glyph(font, 'C') add_glyph(font, 'B') add_glyph(font, 'A') # glyphs outside glyphOrder are appended at the end add_glyph(font, 'Z') glyphOrder = to_ufos(font)[0].lib[PUBLIC_PREFIX + 'glyphOrder'] self.assertEqual(glyphOrder, ['A', 'B', 'C', 'Z'])
def test_glyph_lib_metricsKeys(self): font = generate_minimal_font() glyph = add_glyph(font, "x") glyph.leftMetricsKey = "y" glyph.rightMetricsKey = "z" assert glyph.widthMetricsKey is None ufo = to_ufos(font)[0] self.assertEqual(ufo["x"].lib[GLYPHLIB_PREFIX + "leftMetricsKey"], "y") self.assertEqual(ufo["x"].lib[GLYPHLIB_PREFIX + "rightMetricsKey"], "z") self.assertNotIn(GLYPHLIB_PREFIX + "widthMetricsKey", ufo["x"].lib)
def test_glyph_lib_Export(self): font = generate_minimal_font() glyph = add_glyph(font, "a") self.assertEqual(glyph.export, True) ufo = to_ufos(font)[0] self.assertNotIn(GLYPHLIB_PREFIX + "Export", ufo["a"].lib) glyph.export = False ufo = to_ufos(font)[0] self.assertEqual(ufo["a"].lib[GLYPHLIB_PREFIX + "Export"], False)
def test_mark_nonspacing_zero_width(self): font = generate_minimal_font() add_glyph(font, 'dieresiscomb').layers[0].width = 100 foo = add_glyph(font, 'foo') foo.category = 'Mark' foo.subCategory = 'Nonspacing' foo.layers[0].width = 200 bar = add_glyph(font, 'bar') bar.category = 'Mark' bar.subCategory = 'Nonspacing' bar.layers[0].width = 0 ufo = to_ufos(font)[0] originalWidth_key = GLYPHLIB_PREFIX + 'originalWidth' self.assertEqual(ufo['dieresiscomb'].width, 0) self.assertEqual(ufo['dieresiscomb'].lib.get(originalWidth_key), 100) self.assertEqual(ufo['foo'].width, 0) self.assertEqual(ufo['foo'].lib.get(originalWidth_key), 200) self.assertEqual(ufo['bar'].width, 0) self.assertFalse(originalWidth_key in ufo['bar'].lib)
def test_propagate_anchors(self): """Test anchor propagation for some relatively complicated cases.""" font = generate_minimal_font() glyphs = ( ('sad', [], [('bottom', 50, -50), ('top', 50, 150)]), ('dotabove', [], [('top', 0, 150), ('_top', 0, 100)]), ('dotbelow', [], [('bottom', 0, -50), ('_bottom', 0, 0)]), ('dad', [('sad', 0, 0), ('dotabove', 50, 50)], []), ('dadDotbelow', [('dad', 0, 0), ('dotbelow', 50, -50)], []), ('yod', [], [('bottom', 50, -50)]), ('yodyod', [('yod', 0, 0), ('yod', 100, 0)], []), ) for name, component_data, anchor_data in glyphs: glyph = add_glyph(font, name) for n, x, y, in anchor_data: add_anchor(font, name, n, x, y) for n, x, y in component_data: add_component(font, name, n, (1, 0, 0, 1, x, y)) ufos = to_ufos(font) ufo = ufos[0] glyph = ufo['dadDotbelow'] self.assertEqual(len(glyph.anchors), 2) # check propagated anchors are appended in a deterministic order self.assertEqual( [anchor.name for anchor in glyph.anchors], ['bottom', 'top'] ) for anchor in glyph.anchors: self.assertEqual(anchor.x, 50) if anchor.name == 'bottom': self.assertEqual(anchor.y, -100) else: self.assertEqual(anchor.name, 'top') self.assertEqual(anchor.y, 200) glyph = ufo['yodyod'] self.assertEqual(len(glyph.anchors), 2) for anchor in glyph.anchors: self.assertEqual(anchor.y, -50) if anchor.name == 'bottom_1': self.assertEqual(anchor.x, 50) else: self.assertEqual(anchor.name, 'bottom_2') self.assertEqual(anchor.x, 150)
def test_postscript_name_from_glyph_name(self): font = generate_minimal_font() # in GlyphData (and AGLFN) without a 'production' name add_glyph(font, 'A') # not in GlyphData, no production name add_glyph(font, 'foobar') # in GlyphData with a 'production' name add_glyph(font, 'C-fraktur') ufo = to_ufos(font)[0] postscriptNames = ufo.lib.get('public.postscriptNames') self.assertEqual(postscriptNames, {'C-fraktur': 'uni212D'})
def test_load_kerning(self): """Test that kerning conflicts are resolved correctly. Correct resolution is defined as such: the last time a pair is found in a kerning rule, that rule is used for the pair. """ font = generate_minimal_font() # generate classes 'A': ['A', 'a'] and 'V': ['V', 'v'] for glyph_name in ('A', 'a', 'V', 'v'): glyph = add_glyph(font, glyph_name) glyph.rightKerningGroup = glyph_name.upper() glyph.leftKerningGroup = glyph_name.upper() # classes are referenced in Glyphs kerning using old MMK names font.kerning = { font.masters[0].id: collections.OrderedDict(( ('@MMK_L_A', collections.OrderedDict(( ('@MMK_R_V', -250), ('v', -100), ))), ('a', collections.OrderedDict((('@MMK_R_V', 100), ))), )) } ufos = to_ufos(font) ufo = ufos[0] # these rules should be obvious self.assertEqual(ufo.kerning['public.kern1.A', 'public.kern2.V'], -250) self.assertEqual(ufo.kerning['a', 'public.kern2.V'], 100) # this rule results from breaking up (kern1.A, v, -100) # due to conflict with (a, kern2.V, 100) self.assertEqual(ufo.kerning['A', 'v'], -100)
def setUp(self): self.font = generate_minimal_font() add_glyph(self.font, "a") self.logger = logging.getLogger( "glyphsLib.builder.builders.UFOBuilder")
def test_GDEF_mark(self): font = generate_minimal_font() add_glyph(font, 'eeMatra-gurmukhi') self.assertIn('[eeMatra-gurmukhi], # Mark', to_ufos(font)[0].features.text)
def test_GDEF_ligature_with_nonattaching_anchor(self): font = generate_minimal_font() add_glyph(font, 'fi') add_anchor(font, 'fi', '_top', 400, 1000) self.assertEqual('', to_ufos(font)[0].features.text)
def test_GDEF_ligature_with_attaching_anchor(self): font = generate_minimal_font() add_glyph(font, 'fi') add_anchor(font, 'fi', 'top', 400, 1000) self.assertIn('[fi], # Liga', to_ufos(font)[0].features.text)
def test_GDEF_base_with_attaching_anchor(self): font = generate_minimal_font() add_glyph(font, 'A.alt') add_anchor(font, 'A.alt', 'top', 400, 1000) self.assertIn('[A.alt], # Base', to_ufos(font)[0].features.text)
def test_postscript_name_from_data(self): font = generate_minimal_font() add_glyph(font, 'foo')['production'] = 'f_o_o.alt1' ufo = to_ufos(font)[0] postscriptNames = ufo.lib.get('public.postscriptNames') self.assertEqual(postscriptNames, {'foo': 'f_o_o.alt1'})