def printRange(rangeName, toFile=None): out = [ "{0:<50s}{1:<30}{2:<30}{3}{4:<5}{5}".format("Generated Name", "AGD", "Glyphs", "uni ", " ", "uni name"), "" ] for u in range(*_rangeNameToRange(rangeName)): g = GlyphName(uniNumber=u) name = g.getName() if name is None: continue AGDName = unicode2name_AGD.get(g.uniNumber) if AGDName is None: AGDName = "-" elif AGDName == name: AGDName = u"�" GLYPHSName = unicode2name_GLYPHS.get(g.uniNumber) if GLYPHSName is None: GLYPHSName = "-" elif GLYPHSName == name: GLYPHSName = "" txt = name.ljust(50) txt += AGDName.ljust(30) txt += GLYPHSName.ljust(30) txt += "%04X " % g.uniNumber txt += g.uniLetter.ljust(5) txt += g.uniName out.append(txt) out = "\n".join(out) if toFile: toFile.write(out) else: print(out) testDoubles(rangeName, toFile) testGLIFFileName(rangeName, toFile)
def printRange(rangeName, toFile=None): out = [] for u in range(*_rangeNameToRange(rangeName)): g = GlyphName(uniNumber=u) name = g.getName() if name is None: continue AGDName = unicode2name_AGD.get(g.uniNumber) if AGDName is None: AGDName = "-" elif AGDName == name: AGDName = u"👍" txt = name.ljust(50) txt += AGDName.ljust(30) txt += "%04X " % g.uniNumber txt += g.uniLetter.ljust(5) txt += g.uniName out.append(txt) out = "\n".join(out) out = out.encode("utf-8") if toFile: toFile.write(out) else: print(out) testDoubles(rangeName, toFile) testGLIFFileName(rangeName, toFile)
def generateFlat(path, onlySupported=True, scriptSeparator=None, scriptAsPrefix=None, status=0, includeUnicodeCategory=False): data = [ "# Glyph Name Formatted Unicode List - GNFUL", "# GlyphNameFormatter version %s" % _versionNumber, "# Unicode version: %s" % unicodeVersion, "# Source code: %s" % _githubLink, "# Generated on %s" % time.strftime("%Y %m %d %H:%M:%S"), ] if includeUnicodeCategory: data.append("# <glyphName> <hex unicode> <unicodeCategory>") else: data.append("# <glyphName> <hex unicode>") if scriptSeparator is not None: data.append("# Separator \"%s\"" % scriptSeparator) if scriptAsPrefix is not None: data.append("# Prefixed \"%s\"" % scriptAsPrefix) data.append("#") for rangeName in getAllRangeNames(): if onlySupported: moduleName = rangeNameToModuleName(rangeName) try: module = importlib.import_module( 'glyphNameFormatter.rangeProcessors.%s' % moduleName) except: continue data.append("# %s" % rangeName) start, end = getRangeByName(rangeName) for u in range(start, end + 1): g = GlyphName(uniNumber=u, scriptSeparator=scriptSeparator, scriptAsPrefix=scriptAsPrefix) g.compress() # should auto compress if status is not None: if g.status < status: # if the glyph has a status that is less than what we're looking for # then do not include it in the list. continue name = g.getName(extension=True) if name is None: continue if includeUnicodeCategory: data.append("%s %04X %s" % (name, u, unicodeCategories.get(u, "-"))) else: data.append("%s %04X" % (name, u)) f = open(path, "w") f.write("\n".join(data)) f.close()
def generateFlat(path, onlySupported=True, scriptSeparator=None, scriptAsPrefix=None, status=0, includeUnicodeCategory=False): data = [ "# Glyph Name Formatted Unicode List - GNFUL", "# GlyphNameFormatter version %s" % _versionNumber, "# Unicode version: %s" % unicodeVersion, "# Source code: %s" % _githubLink, "# Generated on %s" % time.strftime("%Y %m %d %H:%M:%S"), ] if includeUnicodeCategory: data.append("# <glyphName> <hex unicode> <unicodeCategory>") else: data.append("# <glyphName> <hex unicode>") if scriptSeparator is not None: data.append("# Separator \"%s\"" % scriptSeparator) if scriptAsPrefix is not None: data.append("# Prefixed \"%s\"" % scriptAsPrefix) data.append("#") for rangeName in getAllRangeNames(): if onlySupported: moduleName = rangeNameToModuleName(rangeName) try: module = importlib.import_module('glyphNameFormatter.rangeProcessors.%s' % moduleName) except: continue data.append("# %s" % rangeName) start, end = getRangeByName(rangeName) for u in range(start, end+1): g = GlyphName(uniNumber=u, scriptSeparator=scriptSeparator, scriptAsPrefix=scriptAsPrefix) g.compress() # should auto compress if status is not None: if g.status < status: # if the glyph has a status that is less than what we're looking for # then do not include it in the list. continue name = g.getName(extension=True) if name is None: continue if includeUnicodeCategory: data.append("%s %04X %s" % (name, u, unicodeCategories.get(u, "-"))) else: data.append("%s %04X" % (name, u)) f = open(path, "w") f.write("\n".join(data)) f.close()
def testGLIFFileName(rangeName, toFile=None): """ test on glif file name """ # support both UFO2 as UFO3 try: # UFO3 ufoLib from fontTools.ufoLib.filenames import userNameToFileName def nameToFileName(name): return userNameToFileName(name) except: # UFO2 robofab from robofab.tools.glyphNameSchemes import glyphNameToShortFileName def nameToFileName(name): return glyphNameToShortFileName(name, None) existing = set() doubles = set() r = _rangeNameToRange(rangeName) for u in range(*r): g = GlyphName(uniNumber=u) name = g.getName() if name is None: # ignore continue glifFileName = nameToFileName(name) if glifFileName in existing: doubles.add(glifFileName) else: existing.add(glifFileName) if doubles: rangeText = "%04X - %04X" % (r[0], r[1]) txt = "\n\ndouble glif file names for range %s:\n\t%s" % (rangeText, "\n\t".join(sorted(doubles))) if toFile: toFile.write(txt) else: print(txt)
def testGLIFFileName(rangeName, toFile=None): """ test on glif file name """ # support both UFO2 as UFO3 try: # UFO3 ufoLib from ufoLib.filenames import userNameToFileName def nameToFileName(name): return userNameToFileName(unicode(name)) except: # UFO2 robofab from robofab.tools.glyphNameSchemes import glyphNameToShortFileName def nameToFileName(name): return glyphNameToShortFileName(name, None) existing = set() doubles = set() r = _rangeNameToRange(rangeName) for u in range(*r): g = GlyphName(uniNumber=u) name = g.getName() if name is None: # ignore continue glifFileName = nameToFileName(name) if glifFileName in existing: doubles.add(glifFileName) else: existing.add(glifFileName) if doubles: rangeText = "%04X - %04X" % (r[0], r[1]) txt = "\n\ndouble glif file names for range %s:\n\t%s" % (rangeText, "\n\t".join(sorted(doubles))) if toFile: toFile.write(txt) else: print(txt)
def generateFlat(path, onlySupported=True): data = [ "# format", "# <glyphName> <hex unicode>" ] for rangeName in getAllRangeNames(): if onlySupported: moduleName = rangeNameToModuleName(rangeName) try: module = importlib.import_module('glyphNameFormatter.rangeProcessors.%s' % moduleName) except: continue data.append("# %s" % rangeName) for u in range(*getRangeByName(rangeName)): g = GlyphName(uniNumber=u) name = g.getName(extension=True) if name is None: continue data.append("%s %04X" % (name, u)) f = open(path, "w") f.write("\n".join(data)) f.close()
def printRange(rangeName, toFile=None): out = [ "{0:<50s}{1:<30}{2:<30}{3}{4:<5}{5}".format("Generated Name", "AGD", "Glyphs", "uni ", " ", "uni name"), "" ] for u in range(*_rangeNameToRange(rangeName)): g = GlyphName(uniNumber=u) name = g.getName() if name is None: continue AGDName = unicode2name_AGD.get(g.uniNumber) if AGDName is None: AGDName = "-" elif AGDName == name: AGDName = u"�" GLYPHSName = unicode2name_GLYPHS.get(g.uniNumber) if GLYPHSName is None: GLYPHSName = "-" elif GLYPHSName == name: GLYPHSName = "" txt = name.ljust(50) txt += AGDName.ljust(30) txt += GLYPHSName.ljust(30) txt += "%04X " % g.uniNumber txt += g.uniLetter.ljust(5) txt += g.uniName out.append(txt) out = "\n".join(out) if PY2: out = out.encode("utf-8") if toFile: toFile.write(out) else: print(out) testDoubles(rangeName, toFile) testGLIFFileName(rangeName, toFile)
def testDoubles(rangeName, toFile=None): """ test if there are doubles """ names = set() doubles = set() r = _rangeNameToRange(rangeName) for u in range(*r): g = GlyphName(uniNumber=u) name = g.getName() if name is None: # ignore continue if name in names: doubles.add(name) else: names.add(name) if doubles: rangeText = "%04X - %04X" % (r[0], r[1]) txt = "\n\ndouble names for range %s:\n\t%s" % (rangeText, "\n\t".join(sorted(doubles))) if toFile: toFile.write(txt) else: print(txt)
from glyphNameFormatter import GlyphName from glyphNameFormatter.unicodeRangeNames import * greekSymbols = [] pi = [] theta = [] for name in getAllRangeNames(): if name in [ 'Ancient Greek Musical Notation', 'Mathematical Alphanumeric Symbols' ]: continue a, b = getRangeByName(name) for uniNumber in range(a, b): g = GlyphName(uniNumber) if g.uniName is None: continue if "GREEK" in g.uniName and g.isMath: greekSymbols.append(g) if "GREEK" in g.uniName and ("LETTER PI" in g.uniName or "PI SYMBOL" in g.uniName): pi.append(g) if "GREEK" in g.uniName and ("LETTER THETA" in g.uniName or "THETA SYMBOL" in g.uniName): theta.append(g) print("\n\ngreek and math") for g in greekSymbols: print(g, g.uniRangeName, g.isMath)
def testCoverage(): uncountables = ['Hangul Syllables', 'CJK Unified Ideographs', 'Private'] uncounted = [] text = [] text.append("\n\n# Coverage") wantRanges = {} glyphCount = {} for thisRange in getAllRangeNames(): a, b = getRangeByName(thisRange) countThis = True for uc in uncountables: if thisRange.find(uc) != -1: uncounted.append(" * %s" % thisRange) print(thisRange, "uncountable") countThis = False moduleName = rangeNameToModuleName(thisRange) if thisRange not in glyphCount: glyphCount[thisRange] = { 'nameable': 0, 'uniNames': 0, 'total': b - a, 'rangeProcessor': None } try: module = importlib.import_module( 'glyphNameFormatter.rangeProcessors.%s' % moduleName) glyphCount[thisRange]['rangeProcessor'] = True except ImportError: pass for uniNumber in range(a, b): g = GlyphName(uniNumber) if g.uniName is not None: glyphCount[thisRange]['uniNames'] += 1 if countThis: glyphCount[thisRange]['nameable'] += 1 totalGlyphs = 0 # the total of all glyph counts in all ranges totalCovered = 0 # the total of all glyphs that this package has rangeprocessors for totalPoints = 0 # the total of all ranges totalNameable = 0 # the total of all glyphs that can be named for key, items in glyphCount.items(): #print(key, items) totalGlyphs += items['uniNames'] totalPoints += items['total'] if items['rangeProcessor'] is not None: totalCovered += items['uniNames'] totalNameable += items['nameable'] text = [] text.append("") text.append("## Version %s" % unicodeVersion) text.append("\n\n\n") text.append("### Note:\n") text.append("This coverage page is has some issues.\n") text.append( " * Most of the Unicode data is downloaded from Unicode.org. Only the bidirectional data still depends on the Python unicodedata module.." ) text.append( " * Narrow build Python might also leave some names inaccessible.") text.append( " * Not all ranges need to count. Private Use ranges are ignored, perhaps others need to as well." ) text.append("\n\n\n") # if uncounted: # text.append("The following ranges are skipped:") # for line in uncounted: # text.append(line) # text.append("\n\n\n") # text.append("| Stats | :) |") # text.append("| ------------------------------------------ | --------: |") # text.append('| Total code points in the available ranges | `%d` |'%totalPoints) # text.append('| Total glyphs in the available ranges | `%d` |'%totalGlyphs) # text.append('| Total glyphs that can be named | `%d` |'%totalNameable) # text.append('| Total names covered in GlyphNameFormatter | `%d` |'%totalCovered) # text.append('| Progress | `%3.3f%%` |'%(100.0*totalCovered/totalGlyphs)) text.append("\n\n\n") text.append("| Range name | # | has processor | Start | End |") text.append("| ----- | ----- |----- | ----- | ----- |") for thisRange in getAllRangeNames(): if not thisRange in glyphCount: continue a, b = getRangeByName(thisRange) items = glyphCount[thisRange] if items['rangeProcessor'] != None: has = "**Yes**" n = "**%s**" % items['uniNames'] else: has = "No" n = items['uniNames'] text.append("| %s | %s | %s | `%04X` | `%04X` |" % (thisRange, n, has, a, b)) text.append("\n\n") path = "../../../coverage.md" f = open(path, 'w') f.write("\n".join(text)) f.close()
if name is None: # ignore continue glifFileName = nameToFileName(name) if glifFileName in existing: doubles.add(glifFileName) else: existing.add(glifFileName) if doubles: rangeText = "%04X - %04X" % (r[0], r[1]) txt = "\n\ndouble glif file names for range %s:\n\t%s" % (rangeText, "\n\t".join(sorted(doubles))) if toFile: toFile.write(txt) else: print(txt) if __name__ == "__main__": from glyphNameFormatter.unicodeRangeNames import getAllRangeNames # time test import time t = time.time() for rangeName in getAllRangeNames(): r = _rangeNameToRange(rangeName) for u in range(*r): g = GlyphName(uniNumber=u) name = g.getName() print(time.time() - t)
print("ERROR: unknown ligature structure") print("\n", self.uniName) print("\t", len(ligatureParts), ligatureParts[0]) print("\t", ligatureType) return # assembly self.uniNameProcessed = "" ligaName = [] for p in ligatureParts: ligaName.append("".join(p).lower()) self.uniNameProcessed = "_".join(ligaName) if __name__ == "__main__": from glyphNameFormatter import GlyphName assert GlyphName(uniNumber=0xFDFA).getName() == "SallallahouAlayheWasallam" assert GlyphName( uniNumber=0xFDC4).getName() == "ain.init_jeem.medi_meem.medi" assert GlyphName( uniNumber=0xFC5D).getName() == "alefmaksura.init_superscriptalef.fina" assert GlyphName(uniNumber=0xFC40).getName() == "lam.init_hah.fina" assert GlyphName(uniNumber=0xFBFC).getName() == "yehfarsi.isol" print("\ndoNotProcessAsLigatureRanges", doNotProcessAsLigatureRanges) odd = 0xfe76 for a, b in doNotProcessAsLigatureRanges: print('\nrange:', hex(a), hex(odd), hex(b)) print(a <= odd <= b, ) for u in range(a, b + 1): try: g = GlyphName(uniNumber=u)
# Make a new font nf = NewFont("NES") # convert the hex value to decimal start = int(HEX, 16) amount = len(glyphOrder) * 2 # x2 because of the empty sprites inbetween for i in range(amount): if i % 2 != 0: continue # skip those empty inbetweens # we draw pixels upwards on a rows and than decrement the row. y = pixelSize * 7 name = GlyphName(ord(glyphOrder[floor(i / 2)])).getName() if name == "at": continue # ng = new glyph ng = nf.newGlyph(name) ng.autoUnicodes() # add unicode ng.width = pixelSize * 8 for b in fnt[start + (i * 8):start + ((i + 1) * 8)]: # fetch a byte c = ("{0:b}".format(b).zfill(8)) # int to binary for x, bit in enumerate(c): # loop the bits if bit == "1": # <-- make it "0" to make a cameo font path = BezierPath() path.rect(x * pixelSize, y, pixelSize, pixelSize) # draw the path in the glyph
def process(self): self.edit("GREEK PROSGEGRAMMENI", "iotaadscript") self.processAs("Greek and Coptic") self.compress() if __name__ == "__main__": from glyphNameFormatter.exporters import printRange printRange("Greek Extended") # https://github.com/LettError/glyphNameFormatter/issues/38 from glyphNameFormatter import GlyphName g = GlyphName(0x1FBE) assert g.getName() == "iotaadscript"
self.replace('FINAL FORM', "fina") self.replace('ISOLATED FORM', "isol") self.replace('WITH SUPERSCRIPT', "") self.replace('WITH', "") self.replace("LIGATURE", "") self.replace("ARABIC", "") self.replace("SYMBOL", "") self.replace("LETTER", "") self.lower() self.camelCase() return True return False if __name__ == "__main__": from glyphNameFormatter import GlyphName print("\ndoNotProcessAsLigatureRanges", doNotProcessAsLigatureRanges) odd = 0xfe76 for a, b in doNotProcessAsLigatureRanges: for u in range(a,b+1): try: g = GlyphName(uniNumber=u) n = g.getName() print(hex(u), n, g.uniName) except: import traceback traceback.print_exc()
with open(namFilePath, "r", encoding="utf-8") as namFile: lines = namFile.read() for line in lines.split("\n"): if len(line): if line.startswith(" "): unistr = None character = None description = None name = line.replace(" ", "") elif line.startswith("0x"): lineSplit = line.split(" ") unistr = lineSplit[0] uni = int(unistr, 16) character = lineSplit[1] description = " ".join(lineSplit[2:]) gn = GlyphName(uni) name = gn.getName() # Format the entry if not name in allNames: if not name or not name.endswith(".sc"): allGlyphInfo.append([ name, unistr, character, description, namCategory, optional ]) allNames.append(name) # My custom sorting order for GF-latin-core sortOrder = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z zero one two three four five six seven eight nine period comma colon semicolon periodcentered ellipsis exclam exclamdown question questiondown quotesingle quotedbl quoteleft quoteright quotesinglbase quotedblleft quotedblright quotedblbase guilsinglleft guilsinglright guillemetleft guillemetright parenleft parenright bracketleft bracketright braceleft braceright slash bar brokenbar backslash fraction divisionslash bullet hyphen hyphensoft endash emdash underscore plus minus multiply divide plusminus equal less greater logicalnot mu.math asterisk asciicircum asciitilde percent degree onesuperior twosuperior threesuperior four.superior onequarter onehalf threequarters ordmasculine ordfeminine copyright registered at numbersign dollar cent sterling yen Euro currency ampersand section paragraph dieresis grave macron acute cedilla circumflex ring tilde dieresis.cap grave.cap macron.cap acute.cap cedilla.cap circumflex.cap ring.cap tilde.cap Agrave Aacute Acircumflex Atilde Adieresis Aring AE Ccedilla Egrave Eacute Ecircumflex Edieresis Igrave Iacute Icircumflex Idieresis Eth Ntilde Ograve Oacute Ocircumflex Otilde Odieresis Oslash OE Ugrave Uacute Ucircumflex Udieresis Yacute Ydieresis Thorn germandbls agrave aacute acircumflex atilde adieresis aring ae ccedilla egrave eacute ecircumflex edieresis igrave iacute icircumflex idieresis dotlessi eth ntilde ograve oacute ocircumflex otilde odieresis oslash oe ugrave uacute ucircumflex udieresis yacute thorn ydieresis space nbspace NULL CR" sortOrder = sortOrder.split(" ") # Apply index values temporarly, for sorting