def getGlyphInfos(self): result = [] # glyphIndexToNameMap = {} glyphToCharacterMap = self.getGlyphIndexToCharacterMap() if self.ftFont.has_glyph_names: for glyphIndex in self.getGlyphIndices(): glyphNameBuffer = ' ' * 256 error = freetype.FT_Get_Glyph_Name(self.ftFont._FT_Face, glyphIndex, glyphNameBuffer, len(glyphNameBuffer) - 1) if error: raise freetype.FT_Exception(error) glyphInfo = TFSMap() glyphInfo.glyphIndex = glyphIndex glyphInfo.glyphName = glyphNameBuffer.strip()[:-1] # print 'glyphName', glyphIndex, glyphName, len(glyphName) glyphInfo.characterCode = None if glyphIndex in glyphToCharacterMap: glyphInfo.characterCode = glyphToCharacterMap[glyphIndex] result.append(glyphInfo) else: for glyphIndex, characterCode in glyphToCharacterMap.items(): glyphInfo = TFSMap() glyphInfo.glyphIndex = glyphIndex glyphInfo.glyphName = getUnicodeCharacterName(characterCode) glyphInfo.characterCode = characterCode # glyphInfoMap[glyphIndex] = glyphInfo result.append(glyphInfo) return result
def do_kern_for_pairs(dir_path, fontfilename, weights_str, kernlistdir): x = 0 # _dir = dir_path + '/' # weights = weights_str.split(',') # get_kern_pair_file_to_tupple(fontfilename, weights, kernlistdir) # for w in weights: # print(_dir + fontfilename + "_" + w + ".ufo") # in_fnt = _dir + fontfilename + "_" + w + "_krn.ufo" out_fnt = _dir + fontfilename + "_" + w + "_krn_fix.ufo" # pseudo_argv = ('--ufo-src-path', in_fnt, '--ufo-dst-path', out_fnt, '--min-distance-ems', '0.04', '--max-distance-ems', '0.05', '--max-x-extrema-overlap-ems', '0.1', '--intrusion-tolerance-ems', '0.02', '--precision-ems', '0.005', '--glyph-pairs-to-kern') autokernArgs = TFSMap() AutokernSettings(autokernArgs).getCommandLineSettings(*(pseudo_argv + pairlist[w])) autokern = Autokern(autokernArgs) autokern.process() # x = x + 1 # print('Completed:' + w + ' ' + str(x) + '/' + str(len(weights)) + '\n' + ' Produced Kerned UFO:' + out_fnt) # print('Replace the kern.plist at your leasure')
def getCommandLineSettings(self, *replacementValues): parser = self.createParser() if replacementValues: args = parser.parse_args(replacementValues) else: args = parser.parse_args() # print 'args', args if self.target is None: self.target = TFSMap() ''' Copy attributes ''' if self.dumpCommandLineSettings(): print() for attr in sorted(dir(args)): if attr.startswith('_'): continue if self.dumpCommandLineSettings(): print('arg', attr, getattr(args, attr)) setattr(self.target, attr, getattr(args, attr)) if self.dumpCommandLineSettings(): print()
def do_kern_for_pairs(dir_path, fontfilename, weights_str): x = 0 # _dir = dir_path + '/' # weights = weights_str.split(',') # # for w in weights: # print(_dir + fontfilename + "_" + w + ".ufo") # in_fnt = _dir + fontfilename + "_" + w + ".ufo" out_fnt = _dir + fontfilename + "_" + w + "_krn.ufo" # pseudo_argv = ( '--ufo-src-path', in_fnt, '--ufo-dst-path', out_fnt, '--min-distance-ems', '0.08', '--max-distance-ems', '0.10', '--max-x-extrema-overlap-ems', '0.10', '--intrusion-tolerance-ems', '0.02', '--precision-ems', '0.005', #'--log-path', #'/media/root/Malysh1/winshm/advent_repo/Advent/scripts/kerning_scripts/kern_log/log', #'--log-basic-pairs', #'--write-kerning-pair-logs' ) print('pseudo_argv', ' '.join([str(arg) for arg in pseudo_argv])) autokernArgs = TFSMap() AutokernSettings(autokernArgs).getCommandLineSettings(*pseudo_argv) autokern = Autokern(autokernArgs) autokern.process() # x = x + 1 # print('Completed:' + w + ' ' + str(x) + '/' + str(len(weights)) + '\n' + ' Produced Kerned UFO:' + out_fnt) # print('Replace the kern.plist at your leasure')
# pseudo_argv = ('--ufo-src-path', os.path.join(pardir,'advent_pro','advent_pro_thn.ufo'), '--ufo-dst-path', os.path.join(pardir,'advent_pro','advent_pro_thn_flat_kern.ufo'), '--min-distance-ems', '0.05', '--max-distance-ems', '0.1', '--max-x-extrema-overlap-ems', '0.1', '--intrusion-tolerance-ems', '0.4', '--precision-ems', '0.02', #'--log-path', #os.path.join(pardir,'logs','log'), #'--log-basic-pairs', #'--write-kerning-pair-logs', ) print ('pseudo_argv', ' '.join([str(arg) for arg in pseudo_argv])) autokernArgs = TFSMap() AutokernSettings(autokernArgs).getCommandLineSettings(*pseudo_argv) autokern = Autokern(autokernArgs) autokern.process() print ('complete.')
def dumpMetricsMap(self, kerningPairMap, htmlFilename): print print 'fonts scanned:', len(self.processedPostscriptNames) print 'fonts processed:', len(self.nonEmptyPostscriptNames) print 'glyph pairs observed:', len(kerningPairMap) maxGlyphPairCount = reduce(max, kerningPairMap.values()) print 'Highest glyph pair frequency:', maxGlyphPairCount glyphs = [] for ( glyph0, glyph1, ), count in kerningPairMap.iteritems(): glyph = TFSMap() glyph.glyph0 = glyph0 glyph.glyph1 = glyph1 glyph.count = count glyphs.append(glyph) def glyphCountSort(glyph0, glyph1): # Negate; we want reverse order for count. result = -cmp(glyph0.count, glyph1.count) if result != 0: return result result = cmp(glyph0.glyph0, glyph1.glyph0) if result != 0: return result result = cmp(glyph0.glyph1, glyph1.glyph1) if result != 0: return result return 0 # return cmp(glyph0.codePoint, glyph1.codePoint) glyphs.sort(glyphCountSort) print 'Most common glyph:', glyphs[0] print 'Least common glyph:', glyphs[-1] locale.setlocale(locale.LC_ALL, 'en_US') pres = [] for glyph in glyphs[:5000]: # for glyph in glyphs[:1000]: # pre = {} pre = { # 'glyphHex': hex(glyph.codePoint), 'glyphHex0': '%04X' % glyph.glyph0, 'glyphHex1': '%04X' % glyph.glyph1, # 'glyphName0': getUnicodeLongName(glyph.glyph0, # ignoreUnknown=True, # skipValidation=True), # 'glyphName1': getUnicodeLongName(glyph.glyph1, # ignoreUnknown=True, # skipValidation=True), 'glyphName0': getUnicodeCharacterName(glyph.glyph0, ignoreUnknown=True), 'glyphName1': getUnicodeCharacterName(glyph.glyph1, ignoreUnknown=True), 'glyphCount': locale.format("%d", glyph.count, grouping=True), 'glyphPercent': '%0.2f%%' % (100.0 * glyph.count / float(len(self.nonEmptyPostscriptNames))), # 'glyphColor': '%06X' % glyphColor, } # pre['value'] = '%s %s: %d (%0.2f%%)' % ( hex(glyph.codePoint), # getUnicodeLongName(glyph.codePoint, # ignoreUnknown=True, # skipValidation=True), # glyph.count, # glyph.count / float(len(self.nonEmptyPostscriptNames)), # ) # print 'pre', pre pres.append(pre) self.writeMustacheLog( 'kia_pre_template.txt', htmlFilename, # 'most_common_kerning_pairs.html', mustacheVars={ 'pres': pres, # 'headerPres': headerPres, 'pageTitle': '1,000 Most Common Kerning Pairs', 'headerTitle': '1,000 Most Common Kerning Pairs', # 'headerTitle': 'Kerning Pairs Implementation Statistics', 'statsTitle': 'Statistics', 'stats': ( { 'key': 'Total Fonts', 'value': locale.format("%d", len(self.processedPostscriptNames), grouping=True), }, { 'key': 'Fonts With Valid Kerning Table', 'value': locale.format("%d", len(self.nonEmptyPostscriptNames), grouping=True), }, { 'key': 'Kerning Pairs Observed', 'value': locale.format("%d", len(kerningPairMap), grouping=True), }, ), } # replaceMap = {'<!-- SVG Graph Placeholder -->': tableSvg, # } )
def dumpMetrics(self): print print 'fonts scanned:', len(self.processedPostscriptNames) print 'fonts processed:', len(self.nonEmptyPostscriptNames) print 'glyph pairs observed:', len(self.kerningPairCountMap) maxGlyphPairCount = reduce(max, self.kerningPairCountMap.values()) print 'Highest glyph pair frequency:', maxGlyphPairCount # self.dumpMetricsMap(self.kerningPairCountMap, 'most_common_kerning_pairs.html') # self.dumpMetricsMap(self.kerningPairAbsEmsMap, 'most_common_kerning_pairs_ems.html') # kerningPairAverageMap = {} # for key in self.kerningPairCountMap: # kerningPairAverageMap[key] = self.kerningPairAbsEmsMap[key] / self.kerningPairCountMap[key] # self.dumpMetricsMap(kerningPairAverageMap, 'most_common_kerning_pairs_avg.html') countGlyphs = [] avgGlyphs = [] for key in self.kerningPairCountMap: glyph0, glyph1 = key glyph = TFSMap() glyph.glyph0 = glyph0 glyph.glyph1 = glyph1 glyph.absEmsTotal = self.kerningPairAbsEmsMap[key] glyph.count = self.kerningPairCountMap[key] glyph.frequencyPct = 100.0 * glyph.count / float( len(self.nonEmptyPostscriptNames)) glyph.absEmsRawAverage = self.kerningPairAbsEmsMap[key] / float( len(self.nonEmptyPostscriptNames)) glyph.absEmsWeightedAverage = self.kerningPairAbsEmsMap[ key] / float(self.kerningPairCountMap[key]) glyphHex0 = '%04X' % glyph.glyph0 glyphHex1 = '%04X' % glyph.glyph1 def getGlyphName(codePoint): result = getUnicodeCharacterName(codePoint, ignoreUnknown=True, skipValidation=True) if result is None: return 'Unknown' result = result.replace('<', '').replace('>', '') return result glyph.label = '0x%s &#x%s %s vs. 0x%s &#x%s %s' % ( glyphHex0, glyphHex0, getGlyphName(glyph.glyph0), glyphHex1, glyphHex1, getGlyphName(glyph.glyph1), ) # 'glyphCount': locale.format("%d", glyph.count, grouping=True), # 'glyphPercent': '%0.2f%%' % (100.0 * glyph.count / float(len(self.nonEmptyPostscriptNames))), if glyph.frequencyPct >= 10.0: countGlyph = TFSMap(glyph) countGlyph.sortValue = glyph.count countGlyph.displayValue = glyph.count countGlyph.displayValue = '%0.0f%%' % (glyph.frequencyPct, ) countGlyphs.append(countGlyph) if glyph.absEmsRawAverage > 0.03: avgGlyph = TFSMap(glyph) avgGlyph.sortValue = glyph.absEmsRawAverage avgGlyph.displayValue = '%0.2f em' % (glyph.absEmsRawAverage, ) # avgGlyph.displayValue = '%0.2f%%' % (100.0 * glyph.absEmsRawAverage, ) avgGlyphs.append(avgGlyph) self.dumpMetricsGroup(countGlyphs, 'Most Common Kerning Pairs', 'The most frequent kerning pairs.', 'most_common_kerning_pairs_avg.html') self.dumpMetricsGroup(avgGlyphs, 'Most Heavily Kerning Pairs', 'The most heavily kerning pairs.', 'most_heavily_kerning_pairs_avg.html')
def dumpMetrics(self): print print 'fonts scanned:', len(self.processedPostscriptNames) print 'fonts processed:', len(self.nonEmptyPostscriptNames) print 'glyphs observed:', len(self.glyphCountMap) maxGlyphCount = reduce(max, self.glyphCountMap.values()) print 'Highest glyph frequency:', maxGlyphCount glyphs = [] for codePoint, count in self.glyphCountMap.iteritems(): glyph = TFSMap() glyph.codePoint = codePoint glyph.count = count glyphs.append(glyph) def glyphCountSort(glyph0, glyph1): # Negate; we want reverse order for count. result = -cmp(glyph0.count, glyph1.count) if result != 0: return result return cmp(glyph0.codePoint, glyph1.codePoint) glyphs.sort(glyphCountSort) print 'Most common glyph:', glyphs[0] print 'Least common glyph:', glyphs[-1] locale.setlocale(locale.LC_ALL, 'en_US') pres = [] for glyph in glyphs[:1000]: # pre = {} pre = { # 'glyphHex': hex(glyph.codePoint), 'glyphHex': '%04X' % glyph.codePoint, 'glyphName': getUnicodeLongName(glyph.codePoint, ignoreUnknown=True, skipValidation=True), 'glyphCount': locale.format("%d", glyph.count, grouping=True), 'glyphPercent': '%0.2f%%' % (100.0 * glyph.count / float(len(self.nonEmptyPostscriptNames))), # 'glyphColor': '%06X' % glyphColor, } # pre['value'] = '%s %s: %d (%0.2f%%)' % ( hex(glyph.codePoint), # getUnicodeLongName(glyph.codePoint, # ignoreUnknown=True, # skipValidation=True), # glyph.count, # glyph.count / float(len(self.nonEmptyPostscriptNames)), # ) # print 'pre', pre pres.append(pre) glyphs.sort(lambda glyph0, glyph1:cmp(glyph0.codePoint, glyph1.codePoint)) headerPres = [] for glyph in glyphs[:10000]: minGlyphColor = 0xffafafff maxGlyphColor = 0xff0f0f5f phase = glyph.count / float(maxGlyphCount) from tfs.common.TFSSvg import blendArgbColors glyphColor = 0xffffff & blendArgbColors(minGlyphColor, maxGlyphColor, phase) pre = { # 'glyphHex': hex(glyph.codePoint), 'glyphHex': '%X' % glyph.codePoint, 'glyphName': getUnicodeLongName(glyph.codePoint, ignoreUnknown=True, skipValidation=True), 'glyphCount': locale.format("%d", glyph.count, grouping=True), 'glyphPercent': '%0.2f%%' % (100.0 * glyph.count / float(len(self.nonEmptyPostscriptNames))), 'glyphColor': '%06X' % glyphColor, } # pre['value'] = '%s %s: %d (%0.2f%%)' % ( hex(glyph.codePoint), # getUnicodeCharacterName(glyph.codePoint, # ignoreUnknown=True, # skipValidation=True), # glyph.count, # glyph.count / float(len(self.nonEmptyPostscriptNames)), # ) # print 'pre', pre headerPres.append(pre) # tableSvg = self.getTableSvg(glyphs, maxGlyphCount) self.writeMustacheLog('gia_pre_template.txt', 'most_common_glyphs.html', mustacheVars = { 'pres': pres, 'headerPres': headerPres, 'pageTitle': '1,000 Most Commonly Implemented Font Glyphs', 'headerTitle': 'Glyph Implementation Statistics', 'statsTitle': 'Statistics', 'stats': ( { 'key': 'Total Fonts Scanned', 'value': locale.format("%d", len(self.processedPostscriptNames), grouping=True), }, { 'key': 'Distinct Code Points Observed', 'value': locale.format("%d", len(self.glyphCountMap), grouping=True), }, ), } # replaceMap = {'<!-- SVG Graph Placeholder -->': tableSvg, # } )
def _makeUnicodedataCategoryMap(): ''' http://bugs.python.org/file19991/unicodedata-doc.diff + +--------------------------------------------------------------------------+ + | **General Categories** | + +----+-------------+------------------+------------------------------------+ + |Name|Major |Minor |Examples | + +====+=============+==================+====================================+ + |Lu | Letter | uppercase | | + +----+-------------+------------------+------------------------------------+ + |Ll | Letter | lowercase | | + +----+-------------+------------------+------------------------------------+ + |Lt | Letter | titlecase | | + +----+-------------+------------------+------------------------------------+ + |Lm | Letter | modifier | | + +----+-------------+------------------+------------------------------------+ + |Lo | Letter | other | | + +----+-------------+------------------+------------------------------------+ + |Mn | Mark | nonspacing | | + +----+-------------+------------------+------------------------------------+ + |Mc | Mark | spacing combining| | + +----+-------------+------------------+------------------------------------+ + |Me | Mark | enclosing | | + +----+-------------+------------------+------------------------------------+ + |Nd | Number | decimal digit | | + +----+-------------+------------------+------------------------------------+ + |Nl | Number | letter | | + +----+-------------+------------------+------------------------------------+ + |No | Number | other | | + +----+-------------+------------------+------------------------------------+ + |Pc | Punctuation | connector | | + +----+-------------+------------------+------------------------------------+ + |Pd | Punctuation | dash | | + +----+-------------+------------------+------------------------------------+ + |Ps | Punctuation | open | | + +----+-------------+------------------+------------------------------------+ + |Pe | Punctuation | close | | + +----+-------------+------------------+------------------------------------+ + |Pi | Punctuation | initial quote | | + +----+-------------+------------------+------------------------------------+ + |Pf | Punctuation | final quote | | + +----+-------------+------------------+------------------------------------+ + |Po | Punctuation | other | | + +----+-------------+------------------+------------------------------------+ + |Sm | Symbol | math | | + +----+-------------+------------------+------------------------------------+ + |Sc | Symbol | currency | | + +----+-------------+------------------+------------------------------------+ + |Sk | Symbol | modifier | | + +----+-------------+------------------+------------------------------------+ + |So | Symbol | other | | + +----+-------------+------------------+------------------------------------+ + |Zs | Separator | space | | + +----+-------------+------------------+------------------------------------+ + |Zl | Separator | line | | + +----+-------------+------------------+------------------------------------+ + |Zp | Separator | paragraph | | + +----+-------------+------------------+------------------------------------+ + |Cc | Other | control | | + +----+-------------+------------------+------------------------------------+ + |Cf | Other | format | | + +----+-------------+------------------+------------------------------------+ + |Cs | Other | surrogate | | + +----+-------------+------------------+------------------------------------+ + |Co | Other | private use | | + +----+-------------+------------------+------------------------------------+ + |Cn | Other | not assigned | | + +----+-------------+------------------+------------------------------------+ ''' result = {} for name, major, minor in ( ( 'Lu', 'Letter', 'uppercase', ), ( 'Ll', 'Letter', 'lowercase', ), ( 'Lt', 'Letter', 'titlecase', ), ( 'Lm', 'Letter', 'modifier', ), ( 'Lo', 'Letter', 'other', ), ( 'Mn', 'Mark', 'nonspacing', ), ( 'Mc', 'Mark', 'spacing combining', ), ( 'Me', 'Mark', 'enclosing', ), ( 'Nd', 'Number', 'decimal digit', ), ( 'Nl', 'Number', 'letter', ), ( 'No', 'Number', 'other', ), ( 'Pc', 'Punctuation', 'connector', ), ( 'Pd', 'Punctuation', 'dash', ), ( 'Ps', 'Punctuation', 'open', ), ( 'Pe', 'Punctuation', 'close', ), ( 'Pi', 'Punctuation', 'initial quote', ), ( 'Pf', 'Punctuation', 'final quote', ), ( 'Po', 'Punctuation', 'other', ), ( 'Sm', 'Symbol', 'math', ), ( 'Sc', 'Symbol', 'currency', ), ( 'Sk', 'Symbol', 'modifier', ), ( 'So', 'Symbol', 'other', ), ( 'Zs', 'Separator', 'space', ), ( 'Zl', 'Separator', 'line', ), ( 'Zp', 'Separator', 'paragraph', ), ( 'Cc', 'Other', 'control', ), ( 'Cf', 'Other', 'format', ), ( 'Cs', 'Other', 'surrogate', ), ( 'Co', 'Other', 'private use', ), ( 'Cn', 'Other', 'not assigned', ), ): category = TFSMap() category.name = name category.major = major category.minor = minor result[category.name] = category return result