def split_glyph_list(self, glyph): glyphs = [] if len(glyph) > 1: # glyph names need to be converted to unicode # we need to take into account, that there can be more than one first/second letter in the very same hkern element # in this case they will be commas separated and each first letter needs to be combined with each next letter # e.g. <hkern g1="A,Agrave,Aacute,Acircumflex,Atilde,Adieresis,Amacron,Abreve,Aogonek" g2="T,Tcaron" k="5" /> glyph_names = glyph.split(",") for glyph_name in glyph_names: # each glyph can have additional special markers, e.g. o.cmp # toUnicode will not respect those and convert them to a simple letter # this behaviour will generate a wrong spacing for this letter. # Let's make sure to also transfer the separators and extensions to our json file separators = [".", "_"] used_separator = False for separator in separators: glyph_with_separator = glyph_name.split(separator) if len(glyph_with_separator) == 2: glyphs.append("%s%s%s" % (toUnicode(glyph_with_separator[0]), separator, glyph_with_separator[1])) used_separator = True continue # there is no extra separator if not used_separator: glyphs.append(toUnicode(glyph_name)) else: glyphs.append(glyph) return glyphs
def test_spec_examples(self): # https://github.com/adobe-type-tools/agl-specification#3-examples self.assertEqual(agl.toUnicode("Lcommaaccent"), "Ļ") self.assertEqual(agl.toUnicode("uni20AC0308"), "\u20AC\u0308") self.assertEqual(agl.toUnicode("u1040C"), "\U0001040C") self.assertEqual(agl.toUnicode("uniD801DC0C"), "") self.assertEqual(agl.toUnicode("uni20ac"), "") self.assertEqual( agl.toUnicode("Lcommaaccent_uni20AC0308_u1040C.alternate"), "\u013B\u20AC\u0308\U0001040C") self.assertEqual(agl.toUnicode("Lcommaaccent_uni013B_u013B"), "ĻĻĻ") self.assertEqual(agl.toUnicode("foo"), "") self.assertEqual(agl.toUnicode(".notdef"), "")
def get_glyph(glyph_name, data=glyphdata_generated): """Return a named tuple (Glyph) containing information derived from a glyph name akin to GSGlyphInfo. The information is derived from an included copy of GlyphsData.xml, going purely by the glyph name. """ # First, get the base name of the glyph. .notdef and .null are exceptions. # Periods denote glyph variants as per the AGLFN convention, which should # be in the same category as their base glyph. if glyph_name in (".notdef", ".null"): base_name = glyph_name else: base_name = glyph_name.split(".", 1)[0] # Next, look up the glyph name in Glyph's name database to get a Unicode # pseudoname, or "production name" as found in a font's post table # (e.g. "A-cy" -> "uni0410") so that e.g. PDF readers can map from names # to Unicode values. FontTool's agl module can turn this into the actual # character. production_name = _lookup_production_name(glyph_name) # Some Glyphs files use production names instead of Glyph's "nice names". # We catch this here, so that we can return the same properties as if # the Glyphs file had been following the Glyphs naming conventions. # https://github.com/googlei18n/glyphsLib/issues/232 if production_name is None: rev_prodname = data.PRODUCTION_NAMES_REVERSED.get(base_name) if rev_prodname is not None: production_name = base_name base_name = rev_prodname # Finally, if we couldn't find a known production name one way or another, # conclude that the glyph name doesn't carry any Unicode semantics. Use the # bare name in that case. if production_name is None: production_name = glyph_name # Next, derive the actual characters from the production name, e.g. # "uni0414" -> "Д". Two caveats: # 1. For some glyphs, Glyphs does not have a mapped character even when one # could be derived. # 2. For some others, Glyphs has a different idea than the agl module. unicode_characters = None if base_name not in data.MISSING_UNICODE_STRINGS: # 1. unicode_characters = data.IRREGULAR_UNICODE_STRINGS.get( base_name) # 2. if unicode_characters is None: unicode_characters = agl.toUnicode(production_name) or None # Lastly, generate the category in the sense of Glyph's # GSGlyphInfo.category and .subCategory. category, sub_category = _get_category(base_name, unicode_characters, data) return Glyph(glyph_name, production_name, unicode_characters, category, sub_category)
def test_dingbats(self): self.assertEqual(agl.toUnicode("a20", isZapfDingbats=True), "✔") self.assertEqual(agl.toUnicode("a20.alt", isZapfDingbats=True), "✔") self.assertEqual(agl.toUnicode("a206", isZapfDingbats=True), "❰") self.assertEqual(agl.toUnicode("a20", isZapfDingbats=False), "") self.assertEqual(agl.toUnicode("a0", isZapfDingbats=True), "") self.assertEqual(agl.toUnicode("a207", isZapfDingbats=True), "") self.assertEqual(agl.toUnicode("abcdef", isZapfDingbats=True), "")
def test_uniABCD(self): self.assertEqual(agl.toUnicode("uni0041"), "A") self.assertEqual(agl.toUnicode("uni0041_uni0042_uni0043"), "ABC") self.assertEqual(agl.toUnicode("uni004100420043"), "ABC") self.assertEqual(agl.toUnicode("uni"), "") self.assertEqual(agl.toUnicode("uni41"), "") self.assertEqual(agl.toUnicode("uni004101"), "") self.assertEqual(agl.toUnicode("uniDC00"), "")
def get_glyph(name, data=glyphdata_generated): prodname = data.PRODUCTION_NAMES.get(name, name) unistr = data.IRREGULAR_UNICODE_STRINGS.get(name) if unistr is None: unistr = agl.toUnicode(prodname) if unistr != "" and name not in data.MISSING_UNICODE_STRINGS: unistr_result = unistr else: unistr_result = None category, subCategory = _get_category(name, unistr, data) return Glyph(name, prodname, unistr_result, category, subCategory)
def test_spec_examples(self): # https://github.com/adobe-type-tools/agl-specification#3-examples # # TODO: Currently, we only handle AGLFN instead of legacy AGL names. # Therefore, the test cases below use Iogonek instead of Lcommaaccent. # Change Iogonek to Lcommaaccent as soon as the implementation has # been fixed to also support legacy AGL names. # https://github.com/fonttools/fonttools/issues/775 self.assertEqual(agl.toUnicode("Iogonek"), "Į") self.assertEqual(agl.toUnicode("uni20AC0308"), "\u20AC\u0308") self.assertEqual(agl.toUnicode("u1040C"), "\U0001040C") self.assertEqual(agl.toUnicode("uniD801DC0C"), "") self.assertEqual(agl.toUnicode("uni20ac"), "") self.assertEqual(agl.toUnicode("Iogonek_uni20AC0308_u1040C.alternate"), "\u012E\u20AC\u0308\U0001040C") self.assertEqual(agl.toUnicode("Iogonek_uni012E_u012E"), "ĮĮĮ") self.assertEqual(agl.toUnicode("foo"), "") self.assertEqual(agl.toUnicode(".notdef"), "")
def test_spec_examples(self): # https://github.com/adobe-type-tools/agl-specification#3-examples # # TODO: Currently, we only handle AGLFN instead of legacy AGL names. # Therefore, the test cases below use Iogonek instead of Lcommaaccent. # Change Iogonek to Lcommaaccent as soon as the implementation has # been fixed to also support legacy AGL names. # https://github.com/fonttools/fonttools/issues/775 self.assertEqual(agl.toUnicode("Iogonek"), "Į") self.assertEqual(agl.toUnicode("uni20AC0308"), "\u20AC\u0308") self.assertEqual(agl.toUnicode("u1040C"), "\U0001040C") self.assertEqual(agl.toUnicode("uniD801DC0C"), "") self.assertEqual(agl.toUnicode("uni20ac"), "") self.assertEqual( agl.toUnicode("Iogonek_uni20AC0308_u1040C.alternate"), "\u012E\u20AC\u0308\U0001040C") self.assertEqual(agl.toUnicode("Iogonek_uni012E_u012E"), "ĮĮĮ") self.assertEqual(agl.toUnicode("foo"), "") self.assertEqual(agl.toUnicode(".notdef"), "")
def get_glyph(name, data=glyphdata_generated): prodname = data.PRODUCTION_NAMES.get(name) # Some Glyphs files use production names (instead of Glyphs names). # We catch this here, so that we can return the same properties as if # the Glyphs file had been following the Glyphs naming conventions. # https://github.com/googlei18n/glyphsLib/issues/232 if prodname is None: rev_prodname = data.PRODUCTION_NAMES_REVERSED.get(name) if rev_prodname is not None: prodname = name name = rev_prodname if prodname is None: prodname = name unistr = data.IRREGULAR_UNICODE_STRINGS.get(name) if unistr is None: unistr = agl.toUnicode(prodname) if unistr != "" and name not in data.MISSING_UNICODE_STRINGS: unistr_result = unistr else: unistr_result = None category, subCategory = _get_category(name, unistr, data) return Glyph(name, prodname, unistr_result, category, subCategory)
def _read_encoding_with_differences(self) -> None: # check whether we've been here before if len(self._unicode_lookup_to_character_identifier) > 0: return # figure out how many characters we'll need to calculate assert "FirstChar" in self assert isinstance(self["FirstChar"], pDecimal) assert "LastChar" in self assert isinstance(self["LastChar"], pDecimal) first_char: int = int(self["FirstChar"]) last_char: int = int(self["LastChar"]) self._character_identifier_to_unicode_lookup = {} # apply differences i: int = 0 j: int = 0 while i < len(self["Encoding"]["Differences"]): assert isinstance(self["Encoding"]["Differences"][i], pDecimal) character_code: int = self["Encoding"]["Differences"][i] j = i + 1 while j < len(self["Encoding"]["Differences"]) and not isinstance( self["Encoding"]["Differences"][j], pDecimal ): glyph_name: str = str(self["Encoding"]["Differences"][j]) self._character_identifier_to_unicode_lookup[ int(character_code) ] = toUnicode(glyph_name) character_code += 1 j += 1 i = j # build reverse map self._unicode_lookup_to_character_identifier = { v: k for k, v in self._character_identifier_to_unicode_lookup.items() }
def test_aglfn(self): self.assertEqual(agl.toUnicode("longs_t"), "ſt") self.assertEqual(agl.toUnicode("f_f_i.alt123"), "ffi")
def test_uABCD(self): self.assertEqual(agl.toUnicode("u0041"), "A") self.assertEqual(agl.toUnicode("u00041"), "A") self.assertEqual(agl.toUnicode("u000041"), "A") self.assertEqual(agl.toUnicode("u0000041"), "") self.assertEqual(agl.toUnicode("u0041_uni0041_A.alt"), "AAA")
def test_union(self): # Interesting test case because "uni" is a prefix of "union". self.assertEqual(agl.toUnicode("union"), "∪") # U+222A U+FE00 is a Standardized Variant for UNION WITH SERIFS. self.assertEqual(agl.toUnicode("union_uniFE00"), "\u222A\uFE00")