def main(): global newfont, oldfont, fontName newfont = fontforge.font() # newfont.em = 2048 oldfont = fontforge.open("Gregoria.otf") fontName = "gregoria" newfont.encoding="ISO10646-1" newfont.fontname="gregoriao" newfont.fullname="gregoriao" newfont.familyname="gregoriao" newfont.weight=oldfont.weight newfont.copyright=oldfont.copyright first_step() adjustAdditionalGlyphs() oldfont.close() oldfont = fontforge.open("Gregoria-Deminutae.otf") fontName="gregoria-deminutae" first_step() adjustAdditionalGlyphs() oldfont.close() oldfont = fontforge.open("Gregoria-Auctae.otf") fontName="gregoria-auctae" first_step() adjustAdditionalGlyphs() oldfont.close() newfont.em = 2048 newfont.generate("gregoriao.ttf") newfont.close()
def generate_lettering(se_path, om_path, le_path, weight, version): # Oradana明朝 を開く font = fontforge.open(om_path) # EMの大きさを2048に設定する font.em = 2048 # SpecialElite を開く sefont = fontforge.open(se_path) # SpecialElite に含まれるグリフを削除する font.selection.none() sefont.selection.all() for glyph in sefont.selection.byGlyphs: if glyph.glyphname in font: font.selection.select(("more",), glyph.glyphname) font.clear() # SpecialElite をマージする font.mergeFonts(se_path) # フォント情報の設定 font.sfnt_names = lettering_sfnt_names(weight, version) font.os2_vendor = "ltrg" # Grid Fittingの設定 font.gasp = lettering_gasp() # TTF の生成 font.generate(le_path, '', ('short-post', 'opentype', 'PfEd-lookups'))
def main(): os.makedirs('generated/', exist_ok = True) # Merge math-upright (which contains U+1D53D, a double-struck F) # into Calluna Sans. calluna_sans = fontforge.open('original/calluna-sans.otf') calluna_sans.mergeFonts('extra/math-upright.sfd') calluna_sans.generate('generated/calluna-sans.otf', flags = 'opentype') calluna_sans.close() prune_font('generated/calluna-sans.otf', 'generated/') # Merge math-italic (which contains a sigma) into Calluna Sans Italic. calluna_sansi = fontforge.open('original/calluna-sans-italic.otf') calluna_sansi.mergeFonts('extra/math-italic.sfd') calluna_sansi.generate('generated/calluna-sans-italic.otf', flags = 'opentype') calluna_sansi.close() prune_font('generated/calluna-sans-italic.otf', 'generated/') # Just copy over the other fonts, prune them in the process. prune_font('original/calluna-bold.otf', 'generated/') prune_font('original/calluna-italic.otf', 'generated/') prune_font('original/calluna.otf', 'generated/') prune_font('original/calluna-sans-bold.otf', 'generated/') prune_font('original/inconsolata.otf', 'generated/')
def modFont(fontFile, style, outDir, newFamilyName, changeHints, legacyKern, addWeight, stripPanose, modBearings, nameHack): # Open font file and immediately save as a fontforge file f = fontforge.open(fontFile.strip()) newFontFile = os.path.normpath(outDir+"/"+newFamilyName+"-"+style+".sfd") newFontTTF = os.path.normpath(outDir+"/"+newFamilyName+"-"+style+".ttf") f.save(newFontFile) f.close() # Open new fontforge file f = fontforge.open(newFontFile) # Set the font names in the SFNT names table setNames(f, newFamilyName, style) # Replace PANOSE Data with "Any", or 0 if stripPanose: f.os2_panose = (0,0,0,0,0,0,0,0,0,0) # Iterate over all glyphs in font, and darken regular and italic fonts only allGlyphs=f.glyphs() for glyph in allGlyphs: if style in (FNT_REGULAR, FNT_ITALIC) and addWeight: changeWeight(glyph, addWeight, modBearings) # Make some modifications to better suit truetype outlines modLayer(glyph) # Autohint glyph if changeHints == "auto": glyph.autoHint() # If I've understood things correctly, this should be the same as setting the curves in the # font information screen of the GUI for l in range(0, f.layer_cnt): if not f.layers[l].is_quadratic: f.layers[l].is_quadratic = True print("The curves in the "+f.layers[l].name+" layer were converted to be quadratic") print("\nSaving "+newFontTTF+". . .\n") flagsTTF = generateFlags(changeHints, legacyKern) f.generate(newFontTTF, flags=flagsTTF) f.save(newFontFile) f.close() try: os.remove(newFontFile) except: print('There was an error removing the file!') """ This is an ugly workaround to the font renaming issue some fonts seem to have One day, I hope to find a proper fix, or a more elegent workaround """ if nameHack: f = fontforge.open(newFontTTF) setNames(f, newFamilyName, style) f.generate(newFontTTF, flags=flagsTTF) f.close()
def reset_config(origin_font, tpl_font): global c_font, c_tpl_font, c_emsize, c_halfsize, c_descent, c_middle c_font = fontforge.open(origin_font) c_tpl_font = fontforge.open(tpl_font) c_emsize = c_font.em - 100 c_halfsize = c_emsize / 2 c_descent = c_font.descent - 50 c_middle = c_halfsize - c_descent
def prepare_font(): global BASE_FONT global TMP_FONT global FONT fontbase = fontforge.open(BASE_FONT) # Delta char has conflict by otf generation, so delete it fontbase["Delta"].clear() fontbase.generate(TMP_FONT) FONT = fontforge.open(TMP_FONT)
def patch_fonts(source_file, target_files, rename_font=True): source_font = fontforge.open(source_file.name) for target_file in target_files: target_font = fontforge.open(target_file.name) try: patch_one_font(source_font, target_font, rename_font) finally: target_font.close() return 0
def load_font(self, fontpath): if fontpath.find('/') >= 0 and cadmium._abs_fontpath_allowed_: return fontforge.open(fontpath) else: # Lookup in fonts directory if os.path.exists(cadmium._font_dir_): available_fonts = os.listdir(cadmium._font_dir_) if fontpath in available_fonts: return fontforge.open(os.path.join(cadmium._font_dir_, fontpath)) raise Exception('Font not found')
def main(): args = parse_args() source_font = fontforge.open(args.source_font.name) target_font = fontforge.open(args.target_font.name) new_font = args.new_font glyphs = source_font.glyphs() if args.all_glyphs else args.glyphs new_suffix = args.new_suffix if args.new_suffix else '' overwrite = args.overwrite copy_glyphs(glyphs, source_font, target_font, new_font, new_suffix, overwrite) args.source_font.close() args.target_font.close()
def featureChange(Font, Feature, ResultFont, FontName): font1 = fontforge.open(Font) font1.save(TMP_FONT) font = fontforge.open(TMP_FONT) for l in font.gsub_lookups: font.removeLookup(l) font.mergeFeature(Feature) font.fullname = FontName font.familyname = FontName font.fontname = FontName font.version = "1.0" font.generate(ResultFont)
def __init__(self, aFontFamily, aFontDir, aConfig): self.mFontFamily = aFontFamily self.mDelimiters = aConfig.DELIMITERS self.mDelimitersExtra = aConfig.DELIMITERS_EXTRA self.mFontSplittingExtra = aConfig.FONTSPLITTING_EXTRA # Open the fonts self.mMathFont = fontforge.open("%s/%s" % (aFontDir, aConfig.MATHFONT)) self.mMainFonts = {} for key in aConfig.MAINFONTS: self.mMainFonts[key] = \ fontforge.open("%s/%s" % (aFontDir, aConfig.MAINFONTS[key])) # Pointer to the PUA to store the horizontal/vertical components self.mPUAPointer=0xE000 self.mPUAContent=dict() self.mMovedNonUnicodeGlyphs=dict() # Lists of stretchy operators self.mStretchyOperators=dict() # List of normal size glyphs self.mNormalSize=[] # Determine the maximum size self.mMaxSize = 0 for glyph in self.mMathFont.glyphs(): if (glyph.unicode == -1): continue if (glyph.horizontalVariants is not None): variants = glyph.horizontalVariants.split() elif (glyph.verticalVariants is not None): variants = glyph.verticalVariants.split() else: continue n = len(variants) if variants[0] == glyph.glyphname: n -= 1 # ignore the normal size variant self.mMaxSize = max(self.mMaxSize, n) # Create a new font for each size self.mMathSize=[] for i in range(0, self.mMaxSize): self.mMathSize.append(newFont(self.mFontFamily, "%s/%s" % (aFontDir, aConfig.MATHFONT), aConfig, "Size%d" % (i+1), "Regular"))
def featureChange(Font, Feature, ResultFont): font1 = fontforge.open(Font) font1.save(TMP_FONT) font = fontforge.open(TMP_FONT) for l in font.gsub_lookups: font.removeLookup(l) font.mergeFeature(Feature) resultName = ResultFont.split(".ttf")[0] font.fullname = resultName font.familyname = resultName font.fontname = resultName font.version = "7.7" font.generate(resultName+".ttf")
def deobliqize(outfont, infont): glyphs = ("parenleft", "parenright", "exclam", "bracketleft", "bracketright", "braceleft", "braceright",) font = fontforge.open(infont) for glyph in glyphs: font.selection.select(("more", "singletons"), glyph) font.copy() font2 = fontforge.open(outfont) for glyph in glyphs: font2.selection.select(("more", "singletons"), glyph) font2.paste() font.close() font2.save(outfont)
def testGlyphConsistency(self): cm = GlyphConsistency() testfont = fontforge.open("unittests/lohit.ttf") test1 = cm.glyph_basicConsistency(testfont,(0x900,0x97f)) testfont = fontforge.open("unittests/lohit.ttf") test2 = cm.glyph_basicset_consistency(testfont,(0x900,0x97f)) testfont = fontforge.open("unittests/lohit.ttf") test3 = cm.glyph_round_consistency(testfont,(0x900,0x97f),50) test = (0 <= test1[0][1] <= 10) self.failUnless(test) test2 = (0 <= test2 <= 10) self.failUnless(test2) test3 = (0 <= test3 <= 10) self.failUnless(test3)
def process_fonts(ref_paths, fnt_paths, save_to, merge, copy_metrics): for ref in ref_paths: reference = fontforge.open(ref) ref_width = FontScaler.most_common_width(reference) print(">>> For reference font {}:".format(reference.familyname)) for fnt in fnt_paths: fallback = fontforge.open(fnt) print(">>> - Monospacifying {}".format(fallback.familyname)) gscaler = StretchingGlyphScaler(ref_width, FontScaler.average_width(fallback)) path = make_monospace(reference, fallback, gscaler, save_to, copy_metrics) if merge: monospacified = fontforge.open(path) print(">>> - Merging with {}".format(monospacified.familyname)) path = merge_fonts(reference, monospacified, save_to) yield (reference.familyname, fallback.familyname, path)
def print_private( fontPath ): font = fontforge.open( fontPath ) print '<div style="font-family: \'' + font.familyname + '\'; ' \ '\">' print '<h2>Private Use Area in ' + font.fontname + '</h2>' font.selection.select(("ranges",None),0xe000,0xf8ff) print '<table>' for g in font.selection.byGlyphs: print '<tr><td>' print '%s%0.4x%s' %( "0x", g.encoding, "" ) print '</td><td>' print '' + g.glyphname print '</td><td>' if g.getPosSub( '*' ): print "is ligature" if g.references: print "has references" print '</td><td>' print '</td></tr>' print '</table>' print '</div>' sys.stdout.flush()
def fontDownloader(self, destinationFolder = False): if destinationFolder: self.fontfaceFolder = destinationFolder else: self.fontfaceFolder = self.fontName fontsFolder = self.fontfaceFolder + '/' + 'fonts' if not os.path.exists(fontsFolder): os.makedirs(fontsFolder) css = self.fontfaceFolder + '/' + self.fontName + '.css' opener = build_opener() opener.addheaders = {('Referer', self.typekitUrl)} for item in self.fontInfo: alias = item['preview']['alias'] fvd = item['preview']['fvd'] subset = item['preview']['subset'] fontUrl = baseUrl % (alias, fvd, subset, self.token) print fontUrl otf = opener.open(fontUrl).read() dump = fontsFolder + '/' + self.fontSlug +'-'+ item['name'].lower() + '.font' open(dump,'w+').write(otf) fontfactory = fontforge.open(dump, 1) fontfactory.fontname = self.fontName.replace(" ", "") + item["name"].replace(" ", "") fontfactory.familyname = self.fontName fontfactory.fullname = self.fontName + ' ' + item["name"] extensions = ['.eot', '.ttf', '.otf', '.svg', '.woff'] for ext in extensions: fontfactory.generate(fontsFolder + '/' + fontfactory.fullname + ext) try: os.remove(dump) # for some reason, probably an error during conversion, an .afm file in created # the code bellow removes the .afm file if it does exists. os.remove(fontsFolder + '/' + fontfactory.fullname + '.afm') except: pass template = "@font-face {\ \n\tfont-family: '" + fontfactory.fullname + "';\ \n\tsrc: url('fonts/" + fontfactory.fullname + ".eot');\ \n\tsrc: url('fonts/" + fontfactory.fullname + ".eot?#iefix') format('embedded-opentype'),\ \n\turl('fonts/" + fontfactory.fullname + ".woff') format('woff'),\ \n\turl('fonts/" + fontfactory.fullname + ".ttf') format('truetype'),\ \n\turl('fonts/" + fontfactory.fullname + ".svg#ywftsvg') format('svg');\ \n\tfont-style: normal;\ \n\tfont-weight: normal;\ \n}\n\n" open(css, 'a').writelines(template)
def process_font(filename, n=-1, chars=None): font = fontforge.open(filename) if n <= 0: n = len(font) for i, name in enumerate(font): if i >= n: break print "process [%s - %d/%d]" % (name, i, n) glyph = font[name] glyph_new = process_glyph(glyph) pen = glyph.glyphPen(True) for layer in glyph_new: for c in layer: x0, y0, f = c[0] pen.moveTo((x0, y0)) i = 1 nr = len(c) while i < nr: x1, y1, f1 = c[i] if f1: pen.lineTo((x1, y1)) i += 1 else: x2, y2, f2 = c[i + 1] pen.curveTo((x1, y1), (x2, y2)) i += 2 pen.closePath() pen = None font.generate("new.ttf")
def setFontInfo(source,family,feature): font = fontforge.open(source) font.familyname = family font.fontname = family + '-' + feature font.fullname = family + ' ' + feature font.version = version font.copyright = copyright
def checkGlyphNumbers( fontDir, fontFile ): if isinstance( fontFile, ( list, tuple ) ): print( "In directory " + fontDir ) for fontName in fontFile: checkGlyphNumbers( fontDir, fontName ) return print( "Checking slot numbers in " + fontFile ) font = fontforge.open( path.join( fontDir, fontFile ) ) g = font.selection.all() g = font.selection.byGlyphs valid = True for glyph in g: if isSpecialTrueType( glyph ): # FIXME really should complain if it DOESNT exist pass elif inPrivateUseRange( glyph ): if glyph.unicode != -1: print( "Glyph at slot " + str( glyph.encoding ) + " is Private Use but has Unicode" ) problem = True else: if glyph.encoding != glyph.unicode: print( "Glyph at slot " + str( glyph.encoding ) + " has wrong Unicode" ) problem = True
def _count_font_glyphs(self, font_file): f = fontforge.open(font_file) i = 0 for glyph in f.glyphs(): i += 1 f.close() return i
def generate_fonts(): print 'Generating fonts...\n' for f in fonts: font_filename = f.get('rescaled', f['orig']) infont_path = '%s/%s' % (srcfont_rescaled_dir, font_filename) infont_basename, infont_ext = os.path.splitext(font_filename) print 'in: %s' % infont_path font = fontforge.open(infont_path) for ext in formats: outfont_path = '%s/%s%s' % (outfont_dir, infont_basename, ext) if ext == '.eot': continue elif infont_ext == ext: print 'out: copying to %s' % outfont_path subprocess.call(['cp', infont_path, outfont_path]) continue print 'out: %s' % outfont_path font.generate(outfont_path) if '.eot' in formats: infont_path = '%s/%s%s' % (outfont_dir, infont_basename, '.ttf') outfont_path = '%s/%s%s' % (outfont_dir, infont_basename, '.eot') print 'out: ttf2eot to %s' % outfont_path subprocess.call(['sh', '-c', '%s < %s > %s' % (ttf2eot, infont_path, outfont_path)]) print print 'done\n'
def optimize(self, builddir): filename = self.postscript_fontname # convert the ttf to a ttx file - this may fail font = fontforge.open(op.join(builddir, filename) + '.ttf') glyphs = [] for g in font.glyphs(): if not g.codepoint: continue glyphs.append(g.codepoint) from fontTools import subset args = [op.join(builddir, filename) + '.ttf'] + glyphs args += ['--layout-features="*"'] subset.main(args) self.stdout_pipe.write('$ pyftsubset %s' % ' '.join(args)) # compare filesizes TODO print analysis of this :) comment = "# look at the size savings of that subset process" cmd = "ls -l '%s.ttf'* %s" % (filename, comment) run(cmd, cwd=builddir, log=self.stdout_pipe) # move ttx files to src shutil.move(op.join(builddir, filename + '.ttf.subset'), op.join(builddir, filename + '.ttf'), log=self.stdout_pipe)
def _build(dstdir, font, permutations): # Ensure that the destination directory exists try: mkdir(dstdir) except OSError: pass for prcnt, opts in permutations: # Open the original font fnt = fontforge.open(font) # Get the base name for the font name = join(dstdir, fnt.fontname) for opt in opts: # Append this option to the font name name += '-' + str(opt) # Run all the operations for this option for oper in option.operations[opt]: oper(fnt) # Add the extension name += ".ttf" # Output the file and cleanup fnt.generate(name) fnt.close() # Log progress to prevent timeoout print(str(prcnt) + '%.. ' + name)
def rescale_font(infont_path, outfont_path): def calc_bbox(glyphs): def get_outer_bbox(a, b): x = min(a[0], b[0]) y = min(a[1], b[1]) w = max(a[0] + a[2], b[0] + b[2]) - x h = max(a[1] + a[3], b[1] + b[3]) - y return (x, y, w, h) return reduce(get_outer_bbox, glyphs) font = fontforge.open(infont_path) #ScaleToEm(800, 200); font.ascent = 800 font.descent = 200 #bbox=GetFontBoundingBox() bbox = calc_bbox([g.boundingBox() for g in font.glyphs()]) #print "bbox=", bbox #SelectAll(); font.selection.all() #Move(-bbox[0], -bbox[1]); #Scale(100*1000/(bbox[3]-bbox[1]), 0, 0); #Move(0, -200); matrix1 = psMat.translate(-bbox[0], -bbox[1]) matrix2 = psMat.scale(1000.0/(bbox[3]-bbox[1])) matrix3 = psMat.translate(0, -200) transform_matrix = psMat.compose(psMat.compose(matrix1, matrix2), matrix3) font.transform(transform_matrix) font.generate(outfont_path)
def test_stylename_less_than_32_chars(self): """ <Style Name> limitation is 32 chars """ font = fontforge.open(self.operator.path) length = len(font.sfnt_names[2][2]) self.assertLess(length, 32, msg=('`Style Name` limitation is < 32 chars.' ' Now: %s') % length)
def test_postscriptname_less_than_30_chars(self): """ <Postscript name> limitation is < 30 chars """ font = fontforge.open(self.operator.path) length = len(font.sfnt_names[6][2]) self.assertLess(length, 30, msg=('`PostScript Name` limitation is less' ' than 30 chars. Now: %s') % length)
def __init__( self, fontPath, short ): font = fontforge.open( fontPath ) self.name = font.fontname self.short = short self.myInfos = {} self.totalGlyphs = 0 self.fontTotalGlyphs = 0 self.privateUseGlyphs = 0 r = font.os2_unicoderanges # print >> stderr, font.fontname, hex( r[0] ), hex( r[1] ),hex( r[2] ),hex( r[3] ); nRanges = len( ulUnicodeRange ) for index in range( 0, nRanges ): byte = index / 32 bit = index % 32 self.collectRangeInfo( font, r[byte], bit, index ) for g in font.glyphs(): self.fontTotalGlyphs += 1 cp = g.encoding if ( not codepointIsInSomeRange( cp ) and not codepointIsSpecialTT( cp ) ): print( font.fontname, "no range for", hex( cp ), file=stderr ) """ '''Would like to check that special TT slots are
def main(aDirectory, aFont): testfile = open("./%s/index.html" % aDirectory, "w+") print("\ <!doctype html>\n\ <html><head><title>%s</title><meta charset=\"utf-8\"/>\n\ <link rel=\"stylesheet\" type=\"text/css\" href=\"./mathfonts.css\"/>\n\ %s\n\ <body class=\"htmlmathparagraph\">\n\ <h1>%s</h1>\n\ <a href=\"./CheckFontLog.txt\">CheckFontLog.txt</a> - \ <a href=\"./CheckFontError.txt\">CheckFontError.txt</a>" % (aFont, kStyle, aFont), file=testfile) font = fontforge.open("%s/%s" % (aDirectory, aFont)) printBasicFontInfo(testfile, font) printMathConstants(testfile, font) printMathVariants(testfile, font) printLargeOp(testfile, font) printMathematicalAlphanumericCharacters(testfile, font) printScriptedOperators(testfile, font) printUnicodeCoverage(testfile, font) font.close() print("\ </body>\n\ </html>", file=testfile)
def main(): "Main function." try: opts, args = getopt.gnu_getopt(sys.argv[1:], "h", ["help"]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) outputfile = None for opt, arg in opts: if opt in ("-h", "--help"): usage() sys.exit() if len(args) == 0: usage() sys.exit(2) if args[0][-3:] == "sfd": outputfile = "%s.ttf" % args[0][:-4] inputfile = args[0] else: usage() sys.exit(2) font = fontforge.open(inputfile) font.generate(outputfile) font.close()
def main(): try: assert len(argv) > 1 except AssertionError: usage_info = '[Usage] python2 %s <fontFile>' % __file__ print(usage_info) exit(1) with ff.open(argv[1]) as font: font_name = get_font_name(font) full_name = get_full_name(font) family = get_family(font) preferred_family = get_preferred_family(font) weight = get_weight(font) print('font name: %s\n' 'full name: %s\n' 'family: %s\n' 'preferred family: %s\n' 'weight: %s\n' % (font_name, full_name, family, preferred_family, weight))
def main(): "Main function." try: opts, args = getopt.gnu_getopt(sys.argv[1:], "h", ["help"]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) outputfile = None for opt, arg in opts: if opt in ("-h", "--help"): usage() sys.exit() if len(args) == 0: usage() sys.exit(2) fontfile = args[0] font = fontforge.open(fontfile) font.selection.all() font.simplify(0.1, ('mergelines','ignoreslopes','setstarttoextremum')) font.generate(fontfile) font.close()
def finish_fonts(blocks): """Create several font formats from an SVG font DOM tree""" for blk in blocks: block = blk[0] cache = '{}cache/font_{}.tmp'.format(TARGET_DIR, block) if not op.isfile(cache) or \ not os.stat(cache).st_size: logger.debug('No font created for block {}...'.format(block)) continue else: logger.info('Creating font for block {}...'.format(block)) with open(TARGET_DIR + 'fonts/' + block + '.svg', 'w') as svgfile: with open(cache) as _cache: svgfile.write(svg_font_skeleton.format(block, _cache.read())) font = fontforge.open(TARGET_DIR + 'fonts/' + block + '.svg') font.generate(TARGET_DIR + 'fonts/' + block + '.woff') font.generate(TARGET_DIR + 'fonts/' + block + '.ttf') font.close() with open(TARGET_DIR + 'fonts/' + block + '.eot', 'w') as eotfile: subprocess.call( ['ttf2eot', TARGET_DIR + 'fonts/' + block + '.ttf'], stdout=eotfile)
def main(): scp = fontforge.open(scpFile) dejavu = fontforge.open(dejavuFile) noto = fontforge.open(notoFile) bbold = fontforge.open(bboldFile) felipa = fontforge.open(felipaFile) unifracktur = fontforge.open(unifrackturFile) amateur = fontforge.open(amateurFile) out = scp out.copyright = "Copyright (c) 2021 Zankoku Okuno, with Reserved Font Name 'Eexpr Reference'." out.familyname = "Eexpr Reference Mono" out.fontname = "EexprReferenceMono-Regular" out.fullname = "Eexpr Reference Mono" out.version = "0.001" out.sfntRevision = None dozenal(out, scp) script(out, felipa) fraktur(out, unifracktur) blackboard(out, bbold) subscripts(out, scp) hebrew(out, noto) customGlyphs(out, amateur) relations(out) setTheory(out, dejavu, amateur) operators(out, dejavu) nAry(out) arrows(out, dejavu) misc(out, noto) checkSizes(out) print(f"copyright: {out.copyright}") print(f"familyname: {out.familyname}") print(f"fondname: {out.fondname}") print(f"fontname: {out.fontname}") print(f"fullname: {out.fullname}") print(f"uniqueid: {out.uniqueid}") print(f"version: {out.version}") out.save(outFile)
def display_unicode_utf8(ctx, fd=sys.stdout): """display unicode characters as UTF-8 :param MergingContext ctx: a merging font context :param file fd: display target""" font = fontforge.open(ctx.filename) unicode_range = ctx.unicode_range start = 0 end = 0 if len(unicode_range) >= 1: start = int(unicode_range[0], 16) if len(unicode_range) >= 2: end = int(unicode_range[1], 16) remap_start_point = ctx.remap_start_point delta = 0 if remap_start_point is not None: delta = int(remap_start_point, 16) - start if start is 0: font.selection.all() else: font.selection.select(('ranges', 'unicode'), start, end) length = 0 line = '' fd.write('{0:-^80}\n'.format(' ' + ctx.id + ' ')) for glyph in list(font.selection.byGlyphs): line += unichr(glyph.encoding + delta) info = get_glyph_size_info(glyph) if info.width <= font.em / 2: # half width line += ' ' length += 1 if length is 40: fd.write(line.encode('utf-8') + '\n') length = 0 line = '' if length > 0: fd.write(line.encode('utf-8') + '\n') fd.flush() font.close()
def generate_font(sfdfile, type=FT_OTF, outdir=None): font = fontforge.open(sfdfile) if outdir is None: fontprefix = os.path.splitext(sfdfile)[0] else: fontprefix = os.path.join( outdir, os.path.basename(os.path.splitext(sfdfile)[0])) if type == FT_TTF: font.familyname = font.familyname + " TT" splitname = font.fullname.split() splitname.insert(-1, "TT") font.fullname = " ".join(splitname) splitname = font.fontname.split("-") splitname.insert(-1, "TT-") font.fontname = "".join(splitname) try: font.generate(fontprefix + ".ttf", flags=("opentype", "old-kern", "PfEd-colors", "PfEd-lookups")) except EnvironmentError, e: print("!!! %s" % e, file=sys.stderr) sys.exit(EX_GENFAIL)
def convert_truetype_svg(): fontfile = sys.argv[1] try: font = fontforge.open(fontfile) except EnvironmentError: sys.exit(1) font.selection.all() font.correctDirection() font.removeOverlap() font.simplify() font.round() for glyph in font: file_name = '{:x}'.format(font[glyph].unicode).upper() file_path = 'exports/{}.svg'.format(file_name) if font[glyph].unicode < 0: continue font[glyph].export(file_path, True) print(file_path)
def merge_fonts(reference, fallback, save_to, renames): fontname = "{}_extended_with_{}".format( cleanup_font_name(reference.fontname, renames), cleanup_font_name(fallback.fontname, renames)) familyname = "{} extended with {}".format( cleanup_font_name(reference.familyname, renames), cleanup_font_name(fallback.familyname, renames)) fullname = "{} extended with {}".format( cleanup_font_name(reference.fullname, renames), cleanup_font_name(fallback.fullname, renames)) destination = os.path.join(save_to, fontname + ".ttf") shutil.copy(reference.path, destination) merged = fontforge.open(destination) merged.sfnt_names = [] merged.fontname = fontname merged.familyname = familyname merged.fullname = fullname merged.mergeFonts(fallback.path) merged.generate(destination) return destination
def main(): start_json = json.load(sys.stdin) for font, chars in metrics_to_extract.iteritems(): fontInfo = fontforge.open("../static/fonts/KaTeX_" + font + ".ttf") for glyph in fontInfo.glyphs(): try: char = unichr(glyph.unicode) except ValueError: continue if char in chars: _, depth, _, height = glyph.boundingBox() depth = -depth base_char = chars[char] if base_char: base_char_str = str(ord(base_char)) base_metrics = start_json[font][base_char_str] italic = base_metrics["italic"] skew = base_metrics["skew"] else: italic = 0 skew = 0 start_json[font][ord(char)] = { "height": height / fontInfo.em, "depth": depth / fontInfo.em, "italic": italic, "skew": skew, } sys.stdout.write( json.dumps(start_json, separators=(',', ':'), sort_keys=True))
def generate_subset(chars, fontpath): ''' >>> font = generate_subset('abc', 'Love Letter Typewriter.ttf') >>> font.generate('./hogehoge.ttf') ''' import fontforge _logger.info('========================') _logger.info('load font file') font = fontforge.open(fontpath) _logger.info('========================') fontname = _get_fontname(font) _logger.info('reducing font name is ' + fontname) chars_append = chars.append for i in range(0, len(chars)): sample_char = chars[i] try: char_in_fontfile = font[sample_char] except TypeError: _logger.info(unichr(sample_char) + ' is missing font code') continue else: uni = char_in_fontfile.unicode if uni != sample_char: chars_append(uni) alts = char_in_fontfile.altuni if alts is None: continue for alt in alts: if alt[0] != sample_char: chars_append(alt[0]) for c in chars: font.selection.select((b"more", None), c) font.selection.invert() font.clear() return font
def main(): parser = argparse.ArgumentParser() parser.add_argument("font") parser.add_argument("name") parser.add_argument("out") args = parser.parse_args() font = fontforge.open(args.font) sys.stdin.reconfigure(encoding="utf-8") for i in sys.stdin.read(): font.selection[ord(i)] = True font.selection.invert() for i in font.selection.byGlyphs: font.removeGlyph(i) postscript_font_name = args.name.replace(" ", "") style = None for s in font.sfnt_names: if s[1] == "SubFamily": style = s[2] break assert style font.familyname = args.name font.fullname = f"{postscript_font_name}-{style.replace(' ', '')}" font.fontname = f"{postscript_font_name}-{style.replace(' ', '')}" font.generate(args.out) print("saved to", args.out)
def main(): for f in sys.argv[1:] : font = fontforge.open(f) gsub_tables = [] for gsub in font.gsub_lookups: subtables = [] for sub in font.getLookupSubtables(gsub): glyphs = [] for g in font.glyphs(): pos = g.getPosSub(sub) if pos: glyphs.append({ 'name': g.glyphname, 'glyphclass': g.glyphclass, 'script': g.script, 'encoding': g.encoding, 'unicode': g.unicode, 'pos': pos }) subtables.append({ 'name': sub, 'glyphs': glyphs }) gsub_tables.append({ 'name': gsub, 'info': font.getLookupInfo(gsub), 'subtables': subtables }) print(json.dumps(gsub_tables))
def convert_fonts(base): desired_ext = ('woff', 'svg', 'eot', 'ttf') for font in os.listdir(base): if not is_font(font): continue font = base / font (name, ext) = font.name.split('.') ff = fontforge.open(str(font)) for convert_to in desired_ext: target_name = base / '{}.{}'.format(name, convert_to) if target_name.is_file(): continue print('Generating {}'.format(target_name)) ff.generate(str(target_name)) if not target_name.is_file(): print('Tried to generate {} but failed'.format(target_name)) afm = base / '{}.afm'.format(name) try: afm.unlink() except OSError: pass
def __init__(self, char, thickness, font=None, fontpath=None, center=False): if font: self.font = font elif fontpath: self.font = fontforge.open(fontpath) self.char = char self.center = center glyph = self.font[str(char)] self.thickness = thickness self.bbox = glyph.boundingBox() self.left_side_bearing = glyph.left_side_bearing self.right_side_bearing = glyph.right_side_bearing if cadmium._brep_caching_enabled_: breppath = os.path.join(cadmium._brep_cache_path_, self.get_signature(char,self.font.path,thickness,center)) if os.path.exists(breppath): Solid.__init__(self, None) self.fromBREP(breppath) else: Solid.__init__(self, self.char_to_solid(glyph), center=center) self.toBREP(breppath)
def print_private(fontPath): font = fontforge.open(fontPath) print('<div style="font-family: \'%s\'; ">' % (font.familyname)) print('<h2>Private Use Area in ' + font.fontname + '</h2>') font.selection.select(("ranges", None), 0xe000, 0xf8ff) print('<table>') for g in font.selection.byGlyphs: print('<tr><td>') print('%s%0.4x%s' % ("0x", g.encoding, "")) print('</td><td>') print('' + g.glyphname) print('</td><td>') if g.getPosSub('*'): print("is ligature") if g.references: print("has references") print('</td><td>') print('</td></tr>') print('</table>') print('</div>') stdout.flush()
def get_font_id_split_name(opts): """Verfiying every downloaded fonts, and get font_id, split, font_name""" alphabet_chars = opts.alphabet valid_fonts_urls = open(opts.downloaded_fonts_urls_file, 'r').readlines() font_id_split_name = open(opts.font_id_split_name_file, 'w') fonts_file_path = opts.ttf_path font_id = 0 for font_line in valid_fonts_urls: font_name = font_line.strip().split(', ')[-1].split('/')[-1] split = font_line.strip().split(', ')[1] font_file_path = os.path.join(fonts_file_path, split, font_name) try: # open a font cur_font = fontforge.open(font_file_path) except Exception as e: print('Cannot open', font_name) print(e) continue try: # select all the 52 chars for char in alphabet_chars: cur_font.selection.select(char) except Exception as e: print(font_name, 'does not have all chars') print(e) continue font_id_split_name.write("{:06d}".format(font_id) + ', ' + split + ', ' + font_name + '\n') font_id += 1 font_id_split_name.close()
outname = conf.get('main', 'ap') if os.path.exists(outname) : readAP(font, outname) mergeAPInfo(font) myFfFont = FfFont(font) buildGraphite(conf, None, myFfFont, outputfont) else : buildGraphite(conf, None, None, outputfont) writecfg(conf, cfg) os.chdir(cwd) def loadFont(font) : if getcfg(font) : if 'initScriptString' not in font.persistent : font.persistent['initScriptString'] = None if not font.temporary : font.temporary = {} font.temporary['generateFontPostHook'] = doGenerate if fontforge.hasUserInterface() : fontforge.hooks['loadFontHook'] = loadFont fontforge.registerMenuItem(loadConfig, None, None, "Font", None, "Graide", "Load configuration") fontforge.registerMenuItem(editConfig, None, None, "Font", None, "Graide", "Edit configuration") else: f = fontforge.open(os.path.abspath(sys.argv[1])) cfg = getcfg(f) if not cfg : print "No configuration, can't build" sys.exit(1) conf = RawConfigParser() conf.read(cfg) f.generate(conf.get('main', 'font'), flags = ('opentype',)) sys.exit(0)
def build(fontdir: Path, outdir: Path, bold=False): # フォントをロード hack_path = fontdir / f"Hack-{'Bold' if bold else 'Regular'}.ttf" mplus_path = fontdir / f"mplus-1m-{'bold' if bold else 'regular'}.ttf" hack: ff.font = ff.open(str(hack_path)) mplus: ff.font = ff.open(str(mplus_path)) # フォントのサイズ調整用に「M」の字でサイズ比と差を計算。 # ただし Hack と M+1M は文字の縦横比が違うため、単純な拡縮ではマッチしない。 # ここでは、まず高さを一致させ、横幅の拡大率を高さの 1.1 倍を超えない程度に # 抑え、かつ不足する横幅を記録しておく(これを元にパディング量を調整し、 # いわゆる全角文字の幅が英数字のちょうど 2 倍になるようにする) vert_ratio = hack[0x4d].vwidth / mplus[0x4d].vwidth horiz_ratio = min(hack[0x4d].width / mplus[0x4d].width, vert_ratio * 1.1) horiz_pad = int(hack[0x4d].width - mplus[0x4d].width * horiz_ratio) scaling_ratio = psMat.scale(horiz_ratio, vert_ratio) _logger.info("scaling ratio: %s", scaling_ratio) _logger.info("horizontal padding: %s", horiz_pad) # Hack に無く M+ にあるコードポイントを列挙する font_code_points = set(g.encoding for g in hack.glyphs()) mplus_code_points = set(g.encoding for g in mplus.glyphs()) for code_point in mplus_code_points - font_code_points: # BMP の外にある文字は無視する if 0xffff < code_point: continue try: # この M+ のグリフを Hack に合うよう拡縮とパディング挿入を行う g = mplus[code_point] g.transform(scaling_ratio) g.left_side_bearing = int(g.left_side_bearing + horiz_pad / 2) g.right_side_bearing = int(g.right_side_bearing + horiz_pad / 2) g.width = int(g.width + horiz_pad) # このグリフを Hack の方にコピー mplus.selection.select(code_point) mplus.copy() hack.selection.select(code_point) hack.paste() except Exception as e: _logger.warning("Error on copying %s (%s): %s", mplus[code_point], f"u{code_point:x}", e) # オリジナルから合成して引き継ぐべきメタデータを準備 # 字体のデザイン特性はコンセプト上の主体である Hack のそれを踏襲する。 # サポートする文字集合は、両フォントのそれの和集合とする。 _logger.info("[os2_version]") _logger.info("hack: %s", hack.os2_version) _logger.info("mplus: %s", mplus.os2_version) hack.os2_version = 1 # OS/2 table version number _logger.info("hm: %s", hack.os2_version) _logger.info("[os2_weight]") _logger.info("hack: %s", hack.os2_weight) _logger.info("mplus: %s", mplus.os2_weight) hack.os2_weight = 400 # Regular _logger.info("hm: %s", hack.os2_weight) _logger.info("[os2_width]") _logger.info("hack: %s", hack.os2_width) _logger.info("mplus: %s", mplus.os2_width) hack.os2_width = 5 # Medium (normal) _logger.info("hm: %s", hack.os2_width) _logger.info("[os2_fstype]") _logger.info("hack: %s", hack.os2_fstype) _logger.info("mplus: %s", mplus.os2_fstype) hack.os2_fstype = 0 # Installable Embedding _logger.info("hm: %s", hack.os2_fstype) _logger.info("[os2_vendor]") _logger.info("hack: %s", hack.os2_vendor) _logger.info("mplus: %s", mplus.os2_vendor) hack.os2_vendor = "" _logger.info("hm: %s", hack.os2_vendor) # https://monotype.github.io/panose/pan2.htm _logger.info("[os2_panose]") _logger.info("hack: %s", hack.os2_panose) _logger.info("mplus: %s", mplus.os2_panose) hack.os2_panose = ( 2, # (Faimly Kind) Latin Text 11, # (Serif Style Classification) Normal Sans 6, # (Weight) Medium 9, # (Propotion) Monospaced 3, # (Contrast) Very Low 2, # (Stroke Variation) No Variation 2, # (Arm Style) Straight Arms/Horizontal 2, # (Letterform) Normal/Contact 2, # (Midline) Standard/Trimmed 4, # (X-height) Constant/Large ) _logger.info("hm: %s", hack.os2_panose) # https://docs.microsoft.com/en-us/typography/opentype/otspec140/os2ver1#ur _logger.info("[os2_unicoderanges]") _logger.info("hack: %s", bits_repr(*hack.os2_unicoderanges)) _logger.info("mplus: %s", bits_repr(*mplus.os2_unicoderanges)) hack.os2_unicoderanges = tuple( h | m for h, m in zip(hack.os2_unicoderanges, mplus.os2_unicoderanges)) _logger.info("hm: %s", bits_repr(*hack.os2_unicoderanges)) _logger.info("[os2_os2_codepages]") _logger.info("hack: %s", bits_repr(*hack.os2_codepages)) _logger.info("mplus: %s", bits_repr(*mplus.os2_codepages)) hack.os2_codepages = tuple( h | m for h, m in zip(hack.os2_codepages, mplus.os2_codepages)) _logger.info("hm: %s", bits_repr(*hack.os2_codepages)) # フォントのメタ情報を生成 try: hack_version = hack.sfnt_names[5][2].split(";")[0].lower() except Exception as e: _logger.error("Failed to extrace Hack version: %s\n\n%s", e, hack.sfnt_names) sys.exit(2) try: mplus_version = mplus.sfnt_names[5][2].lower() except Exception as e: _logger.error("Failed to extrace M+ version: %s\n\n%s", e, mplus.sfnt_names) sys.exit(2) version_string = ("Version {}; derivative of Hack {} and M+1m {}".format( __version__, hack_version, mplus_version)) license_text = Path("LICENSE").read_text() # フォントに設定 family_name = "HM" subfamily_name = "Bold" if bold else "Regular" hack.fontname = f"{family_name}-{subfamily_name}" hack.familyname = family_name hack.fullname = f"{family_name} {subfamily_name}" locale = "English (US)" license_url = "https://github.com/sgryjp/hm-font/blob/master/LICENSE" meta = ( __copyright__, # 0:Copyright family_name, # 1:Family subfamily_name, # 2:SubFamily f"{family_name}-{subfamily_name}-{__version__}", # 3:UniqueID hack.fullname, # 4:Fullname version_string, # 5:Version f"{family_name}-{subfamily_name}", # 6:PostScriptName "", # 7:Trademark "", # 8:Manufacturer "", # 9:Designer "", # 10:Descriptor "", # 11:Vendor URL "", # 12:Designer URL license_text, # 13:License license_url, # 14:License URL None, # 15:N/A family_name, # 16:Preferred Family subfamily_name, # 17:Preferred Styles ) for i, value in enumerate(meta): if value is not None: hack.appendSFNTName(locale, i, value) # デバッグ用に設定したメタ情報を表示 for _, k, v in hack.sfnt_names: if k != "License": _logger.debug("[%s]", k) _logger.debug("%s", v) # フォントを出力 os.makedirs(outdir, exist_ok=True) hack.generate(str(outdir / f"hm-{'bold' if bold else 'regular'}.ttf"))
def generate(filename): f.generate(filename) # TTF generate(fontfile + '.ttf') # Hint the TTF file # ttfautohint is optional if find_executable('ttfautohint'): call( "ttfautohint --symbol --fallback-script=latn --windows-compatibility --no-info '" + fontfile + ".ttf' '" + fontfile + "-hinted.ttf' && mv '" + fontfile + "-hinted.ttf' '" + fontfile + ".ttf'", shell=True) f = fontforge.open(fontfile + '.ttf') # SVG if 'svg' in args.types: generate(fontfile + '.svg') # Fix SVG header for webkit (from: https://github.com/fontello/font-builder/blob/master/bin/fontconvert.py) svgfile = open(fontfile + '.svg', 'r+') svgtext = svgfile.read() svgfile.seek(0) svgfile.write( svgtext.replace('<svg>', '<svg xmlns="http://www.w3.org/2000/svg">')) svgfile.close() scriptPath = os.path.dirname(os.path.realpath(__file__))
] glyphs_set = " ".join(glyphs) def adjust_space(): for glyph in glyphs_set.split(" "): glyphname = "uni0C%s" % glyph if not glyphname in font: continue left_space = font[glyphname].left_side_bearing right_space = font[glyphname].right_side_bearing print("%s,%s,%s,%s,%s" % (glyphname, left_space, LSPACE, right_space, RSPACE)) font[glyphname].left_side_bearing = LSPACE font[glyphname].right_side_bearing = RSPACE if __name__ == "__main__": if len(sys.argv) < 2: print "USAGE: python adjust_spacing.py <sfd file>" sys.exit(1) sfd_name = sys.argv[1] font = fontforge.open(sfd_name) print("name,left_old,left_new,right_old,right_new") adjust_space() font.save() font.close()
import fontforge ## ## THIS FILE IS A FONTFORGE SCRIPT THAT GENERATES THE HIRMOS PONOMAR FONT FAMILY ## ## base_name = "IndictionUnicode" full_name = "Indiction Unicode" #fontforge.setPrefs ("AutoHint", False) #fontforge.setPrefs ("ClearInstrsBigChanges",False ) #fontforge.setPrefs ( "CopyTTFInstrs",False ) ## open up the font font = fontforge.open(base_name + ".sfd") ## Evidently, this can break Evince, so it may need to be commented out font.head_optimized_for_cleartype = True ## not sure if we need this #font.encoding = "mac" ttnames = list(font.sfnt_names) for ttname in ttnames: if ttname[1] == 'SubFamil': ttnames.append( (ttname[0], 'Fullname', "%s %s" % (full_name, ttname[2]))) font.sfnt_names = tuple(ttnames) font.generate(base_name + ".otf",
#!/usr/bin/python import os import fontforge fontFileName = os.sys.argv[1] path = fontFileName try: font = fontforge.open(path) font.generate(os.path.splitext(fontFileName)[0] + ".ttf") font.generate(os.path.splitext(fontFileName)[0] + ".otf") font.generate(os.path.splitext(fontFileName)[0] + ".svg") font.generate(os.path.splitext(fontFileName)[0] + ".woff") except EnvironmentError: print("Error opening font file %s!" % fontFileName) os.sys.exit(1)
# prepare config to view: # [(from_code1, to_code1), (from_code2, to_code2), ...] remap_config = [(glyph.get('from', glyph['code']), glyph['code']) for glyph in config['glyphs']] # validate config: fetcy duplicate 'from' codes src_codes = zip(*remap_config)[0] if len(src_codes) != len(set(src_codes)): stderr.write("Error in file %s: glyph codes aren't unique:\n" % args.config) for code in set(src_codes): if src_codes.count(code) > 1: stderr.write("Duplicate 'from:' 0x%04x\n" % code) sys.exit(1) try: font = fontforge.open(args.src_font) # set font encoding so we can select any unicode code point font.encoding = 'UnicodeFull' except: stderr.write("Error: Fontforge can't open source %s" % args.src_font) sys.exit(1) new_font = fontforge.font() new_font.encoding = 'UnicodeFull' # load font properties from config for key, value in config.get('font', {}).items(): setattr(new_font, key, value) for from_code, to_code in remap_config:
def set_font(self, fontfile): self.tt = truetype(fontfile, self.size[1]) self.ff = fontforge.open(fontfile)
## ## THIS FILE IS A FONTFORGE SCRIPT THAT GENERATES WEB FONTS FAMILY ## ## base_name = "FiraSlav" fontforge.setPrefs("AutoHint", False) fontforge.setPrefs("ClearInstrsBigChanges", False) fontforge.setPrefs("CopyTTFInstrs", True) flavor = ("Regular", "Bold") for i in range(0, len(flavor)): ## open up the font font = fontforge.open(base_name + "-" + flavor[i] + ".sfd") font.head_optimized_for_cleartype = True # generate TTF fonts font.em = 1024 font.generate(base_name + "-" + flavor[i] + ".ttf", flags=("opentype", "old-kern", "PfEd-colors", "PfEd-lookups", "dummy-dsig"), layer="Fore") #generate WOFF fonts woff_meta = base_name + "-WOFF-metadata.xml" f = file(woff_meta, 'r') lines = f.readlines() f.close() font.woffMetadata = "".join(lines)
if args.i is None or args.k is None: parser.print_help() exit(1) src_path = args.i[0] if args.o is None: dest_path = args.i[0][:-4] + "-kerned.otf" else: dest_path = args.o[0] spec = json.load(open(args.k[0], "r", encoding="utf-8")) r = spec["config"]["r"] gap = spec["config"]["gap"][0] print("processing font:", src_path) font = fontforge.open(src_path) print("cleaning glyphs...") font.selection.all() font.removeOverlap() font.simplify() font.correctDirection() font.addLookup( "kern", "gpos_pair", ( "ignore_ligatures", "ignore_marks", ), (("kern", (("DFLT", ("dflt")), )), ),
), charZKKana = list( u"ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ" ), charHKKana = list( u"、。・ー゙゚「」アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォャュョッ") charZEisu = list( u"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") ######################################## # modified ReplaceParts ######################################## print() print("Open " + srcfont_MyricaReplaceParts) fRp = fontforge.open(srcfont_MyricaReplaceParts) # modify em fRp.em = newfont_em fRp.ascent = newfont_ascent fRp.descent = newfont_descent # post-process fRp.selection.all() fRp.round() ######################################## # modified Inconsolata ######################################## print()
#!/usr/bin/env python2 import fontforge import sys if len(sys.argv) < 4: print "Usage: %s <font file> <ascent> <descent>" % sys.argv[0] sys.exit(1) font_file = sys.argv[1] ascent = int(sys.argv[2]) descent = int(sys.argv[3]) font = fontforge.open(font_file) font.os2_winascent = ascent font.os2_windescent = descent font.hhea_ascent = ascent font.hhea_descent = -descent font.generate(font_file, flags=("TeX-table"))
#!/usr/local/bin/fontforge #Needs: fonts/nuvo-medium-woff-demo.woff import fontforge woff = fontforge.open("fonts/nuvo-medium-woff-demo.woff") if (woff.woffMajor != 7): raise ValueError, "Wrong return from woffMajor" if (woff.woffMinor != 504): raise ValueError, "Wrong return from woffMinor" if (len(woff.woffMetadata) != 959): raise ValueError, "Wrong return from woffMetadata" woff.woffMajor = 8 woff.generate("results/Foo.woff") wofftest = fontforge.open("results/Foo.woff") if (wofftest.woffMajor != 8 | wofftest.woffMinor != 504): raise ValueError, "Wrong return from woffMajor woffMinor after saving" if (len(wofftest.woffMetadata) != 959): raise ValueError, "Wrong return from woffMetadata after saving"
# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys import fontforge if __name__ == "__main__": if len(sys.argv) < 3: print "USAGE: python apply_featurefile.py <sfd file> <featurefile>" else: font = fontforge.open(sys.argv[1]) # Remove all GSUB lookups for lookup in font.gsub_lookups: font.removeLookup(lookup) # Remove all GPOS lookups # These lines are disable since gpos tables are font specific and simply importing from lohit will not help it. # for lookup in font.gpos_lookups: # font.removeLookup(lookup) # Merge the new featurefile font.mergeFeature(sys.argv[2]) font.save() font.close() print "[SUCCESS]", sys.argv[2], "feature file applied"