def test_warn_no_version(self): """Test that a warning is printed when app version is missing.""" data = self.generate_minimal_data() del data['.appVersion'] builder.warn = _add_warning to_ufos(data) self.assertTrue(_check_warnings())
def test_warn_no_version(self): """Test that a warning is printed when app version is missing.""" data = self.generate_minimal_data() del data['.appVersion'] with CapturingLogHandler(builder.logger, "WARNING") as captor: to_ufos(data) self.assertEqual(len([r for r in captor.records if "outdated version" in r.msg]), 1)
def load_to_ufos(filename, include_instances=False, debug=False): """Load an unpacked .glyphs object to UFO objects.""" with open(filename, 'rb') as ifile: data = load(ifile) print('>>> Loading to UFOs') return to_ufos(data, include_instances=include_instances, debug=debug)
def _run_guideline_test(self, data_in, expected): data = self.generate_minimal_data() data['glyphs'].append({ 'glyphname': 'a', 'layers': [{'layerId': data['fontMaster'][0]['id'], 'width': 0, 'guideLines': data_in}]}) ufo = to_ufos(data)[0] self.assertEqual(ufo['a'].guidelines, expected)
def load_to_ufos(file_or_path, include_instances=False, family_name=None, debug=False): """Load an unpacked .glyphs object to UFO objects.""" if hasattr(file_or_path, 'read'): data = load(file_or_path) else: with open(file_or_path, 'r', encoding='utf-8') as ifile: data = load(ifile) print('>>> Loading to UFOs') return to_ufos(data, include_instances=include_instances, family_name=family_name, debug=debug)
def test_set_blue_values(self): """Test that blue values are set correctly from alignment zones.""" data_in = [(500, 15), (400, -15), (0, -15), (-200, 15), (-300, -15)] expected_blue_values = [-200, -185, -15, 0, 500, 515] expected_other_blues = [-315, -300, 385, 400] data = self.generate_minimal_data() data['fontMaster'][0]['alignmentZones'] = data_in ufo = to_ufos(data)[0] self.assertEqual(ufo.info.postscriptBlueValues, expected_blue_values) self.assertEqual(ufo.info.postscriptOtherBlues, expected_other_blues)
def test_minimal_data(self): """Test the minimal data that must be provided to generate UFOs, and in some cases that additional redundant data is not set. """ data = self.generate_minimal_data() family_name = data['familyName'] ufos = to_ufos(data) self.assertEqual(len(ufos), 1) ufo = ufos[0] self.assertEqual(len(ufo), 0) self.assertEqual(ufo.info.familyName, family_name) self.assertEqual(ufo.info.styleName, 'Regular') self.assertEqual(ufo.info.versionMajor, 1) self.assertEqual(ufo.info.versionMinor, 0) self.assertIsNone(ufo.info.openTypeNameVersion)
def test_propagate_anchors(self): """Test anchor propagation for some relatively complicated cases.""" data = self.generate_minimal_data() 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: anchors = [{'name': n, 'position': (x, y)} for n, x, y in anchor_data] components = [{'name': n, 'transform': (1, 0, 0, 1, x, y)} for n, x, y in component_data] data['glyphs'].append({ 'glyphname': name, 'layers': [{'layerId': data['fontMaster'][0]['id'], 'width': 0, 'anchors': anchors, 'components': components}]}) ufos = to_ufos(data) ufo = ufos[0] glyph = ufo['dadDotbelow'] self.assertEqual(len(glyph.anchors), 2) 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_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. """ data = self.generate_minimal_data() # generate classes 'A': ['A', 'a'] and 'V': ['V', 'v'] for glyph_name in ('A', 'a', 'V', 'v'): data['glyphs'].append({ 'glyphname': glyph_name, 'layers': [], 'rightKerningGroup': glyph_name.upper(), 'leftKerningGroup': glyph_name.upper()}) # classes are referenced in Glyphs kerning using old MMK names data['kerning'] = { data['fontMaster'][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(data) 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 test_ligature_carets(self): """Test that ligature carets get converted into features.""" data = self.generate_minimal_data() glyphs = ( ('a_c.alt', [('caret_foo', 300, -50)]), ('f_f_i', [('caret_1', 250, -50), ('caret_2', 550, 150)]), ) for name, anchor_data in glyphs: anchors = [{'name': n, 'position': (x, y)} for n, x, y in anchor_data] data['glyphs'].append({ 'glyphname': name, 'layers': [{'layerId': data['fontMaster'][0]['id'], 'width': 0, 'anchors': anchors, 'components': []}]}) ufos = to_ufos(data) ufo = ufos[0] self.assertEqual(ufo.features.text.splitlines(), [ 'table GDEF {', '# automatic', 'LigatureCaretByPos a_c.alt 300;', 'LigatureCaretByPos f_f_i 250 550;', '} GDEF;', ])
def test_lib_custom(self): font = generate_minimal_font() font.masters[0].customName = 'FooBar' ufo = to_ufos(font)[0] self.assertEqual(ufo.lib[GLYPHS_PREFIX + 'customName'], 'FooBar')
def test_coerce_to_bool(self): font = generate_minimal_font() font.customParameters['Disable Last Change'] = 'Truthy' ufo = to_ufos(font)[0] self.assertEqual(True, ufo.lib[GLYPHS_PREFIX + 'disablesLastChange'])
def test_lib_width(self): data = self.generate_minimal_data() data['fontMaster'][0]['width'] = 'Condensed' ufo = to_ufos(data)[0] self.assertEqual(ufo.lib[GLYPHS_PREFIX + 'width'], 'Condensed')
def test_GDEF_ligature_with_attaching_anchor(self): data = self.generate_minimal_data() self.add_glyph(data, 'fi') self.add_anchor(data, 'fi', 'top', 400, 1000) self.assertIn('[fi], # Liga', to_ufos(data)[0].features.text)
def test_postscript_name_from_glyph_name(self): data = self.generate_minimal_data() self.add_glyph(data, 'C-fraktur') ufo = to_ufos(data)[0] postscriptNames = ufo.lib.get('public.postscriptNames') self.assertEqual(postscriptNames, {'C-fraktur': 'uni212D'})
def test_lib_custom(self): data = self.generate_minimal_data() data['fontMaster'][0]['custom'] = 'FooBar' ufo = to_ufos(data)[0] self.assertEqual(ufo.lib[GLYPHS_PREFIX + 'custom'], 'FooBar')
def test_widthClass_from_width(self): data = self.generate_minimal_data() data['fontMaster'][0]['width'] = 'Extra Condensed' ufo = to_ufos(data)[0] self.assertEqual(ufo.info.openTypeOS2WidthClass, 2)
def test_widthClass_default(self): data = self.generate_minimal_data() ufo = to_ufos(data)[0] self.assertEqual(ufo.info.openTypeOS2WidthClass, 5)
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_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_missing_date(self): data = self.generate_minimal_data() del data['date'] ufo = to_ufos(data)[0] self.assertIsNone(ufo.info.openTypeHeadCreated)
def test_GDEF_mark(self): data = self.generate_minimal_data() self.add_glyph(data, 'eeMatra-gurmukhi') self.assertIn('[eeMatra-gurmukhi], # Mark', to_ufos(data)[0].features.text)
def test_GDEF_ligature_with_nonattaching_anchor(self): data = self.generate_minimal_data() self.add_glyph(data, 'fi') self.add_anchor(data, 'fi', '_top', 400, 1000) self.assertEqual('', to_ufos(data)[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'})
def test_lib_weight(self): data = self.generate_minimal_data() data['fontMaster'][0]['weight'] = 'Bold' ufo = to_ufos(data)[0] self.assertEqual(ufo.lib[GLYPHS_PREFIX + 'weight'], 'Bold')
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_lib_weight(self): font = generate_minimal_font() font.masters[0].weight = 'Bold' ufo = to_ufos(font)[0] self.assertEqual(ufo.lib[GLYPHS_PREFIX + 'weight'], 'Bold')
def test_weightClass_from_weight(self): data = self.generate_minimal_data() data['fontMaster'][0]['weight'] = 'Bold' ufo = to_ufos(data)[0] self.assertEqual(ufo.info.openTypeOS2WeightClass, 700)
def test_lib_no_width(self): font = generate_minimal_font() ufo = to_ufos(font)[0] self.assertEqual(ufo.lib[GLYPHS_PREFIX + 'width'], 'Regular')
def assertUFORoundtrip(self, font): expected = write_to_lines(font) roundtrip = to_glyphs(to_ufos(font)) actual = write_to_lines(roundtrip) self.assertLinesEqual(expected, actual, "The font has been modified by the roundtrip")
def test_lib_width(self): font = generate_minimal_font() font.masters[0].width = 'Condensed' ufo = to_ufos(font)[0] self.assertEqual(ufo.lib[GLYPHS_PREFIX + 'width'], 'Condensed')
def test_lib_no_custom(self): data = self.generate_minimal_data() ufo = to_ufos(data)[0] self.assertFalse(GLYPHS_PREFIX + 'custom' in ufo.lib)
def test_lib_no_custom(self): font = generate_minimal_font() ufo = to_ufos(font)[0] self.assertFalse(GLYPHS_PREFIX + 'customName' in ufo.lib)
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_base_with_attaching_anchor(self): data = self.generate_minimal_data() self.add_glyph(data, 'A.alt') self.add_anchor(data, 'A.alt', 'top', 400, 1000) self.assertIn('[A.alt], # Base', to_ufos(data)[0].features.text)
def test_missing_date(self): font = generate_minimal_font() font.date = None ufo = to_ufos(font)[0] self.assertIsNone(ufo.info.openTypeHeadCreated)
def to_ufos(self, *args, **kwargs): kwargs["ufo_module"] = self.ufo_module return to_ufos(*args, **kwargs)