使用FontTools打包Primer/Octicons为WOFF字体并关联CSS类的实现问题求助
FontTools打包Primer/Octicons为WOFF字体并关联CSS类的实现问题求助
我最近一直在尝试把Primer/Octicons的所有SVG图标打包成单个WOFF字体文件,搭配CSS用Unicode字符引用每个图标,就像Bootstrap Icons那样——能通过<i class='oi oi-codepilot-16'></i>这种方式调用图标。目前我大概摸清楚了整体思路,但相关文档讲得不够细致,始终没法把WOFF文件里的SVG图标和Unicode字符成功绑定。
我原本的预期是做出和Bootstrap Icons一样的效果:所有SVG打包进单个WOFF,通过CSS类来调用。但每次尝试要么报错,要么最后生成的文件没法用。试过AI工具找方案也没解决,最后只能自己写Python脚本。
现在脚本已经能生成WOFF文件和对应的CSS,但放到Web环境测试后发现完全不行——每个图标都显示成未知的Unicode字符(类似方块占位符)。
我期望的HTML调用方式如下(希望保持这个写法):
<!--I WANT THIS TO STAY LIKE THIS--> <i class='oi oi-codepilot-16'></i>
参考Bootstrap Icons修改的CSS代码:
/*this code ripped from bootstrap-icons.css, edited to include icons i want to use, and include the woff font the python program creates*/ @font-face { font-display:block; font-family:"octicons"; src: url(./fonts/octicon.woff) format("woff"); } .oi::before, [class^="oi-"]::before, [class*="oi-"]::before { display:inline-block; font-family: octicons !important; font-style: normal; font-weight: normal !important; font-variant: normal; text-transform: none; line-height: 1; vertical-align: -.125em; -webkit-font-smoothing: antialiased; -mos-osx-font-smoothing: grayscale } /*. . .*/ /*python generated code*/ .oi-copilot-16::before { content: "\f57481"; }
我自己编写的Python脚本:
import os import json import defcon from fontTools.ttLib import TTFont, newTable,getTableClass as gtc ,getTableModule as gtm,identifierToTag as idt from fontTools.ttLib.tables.DefaultTable import DefaultTable from fontTools.svgLib.path import SVGPath as svgPath #from fontTools.ttLib.woff import WOFFFlavor from svgpathtools import svg2paths import math def svg_to_glyph(svg_file, glyph_name,glyph_unicode): paths, attributes = svg2paths(svg_file) glyph_code = '' for path in paths: glyph_code += f'<path d="{path.d()}" />' #unicode = math.round(math.random() * 10000) return f'<glyph glyph-name="{glyph_name}" unicode="{glyph_unicode}" d="{glyph_code}" />' def create_woff_font(svg_files, output_woff, output_json): jsn = {}; font = TTFont() CmapSubtable = gtm("cmap").CmapSubtable cmap4_0_3 = CmapSubtable.newSubtable(4) cmap4_0_3.platformID = 0 cmap4_0_3.platEncID = 3 cmap4_0_3.language = 0 cmap4_0_3.cmap = {}; unicode = 0x0E000 for file in svg_files: handle = open(file,"r") print(file) name = str(file).split("/")[::-1][0].replace(".svg","") #print(file.split("/").reverse()) svg = handle.read() unicode+=1 glyph = defcon.Glyph() path = svgPath.fromstring(svg) path.draw(glyph.getPen()) cmap4_0_3.cmap[unicode] = glyph jsn[unicode] = name handle.close() cmap = newTable("cmap"); cmap.tableVersion = 0; cmap.tables = [cmap4_0_3] font.cmap = cmap font.flavor = "woff" font.save(output_woff + ".woff") #font.flavor = "woff2" #font.save(output_woff + ".woff2") #json.dump(jsn,json_file, indent=4) with open(output_json, 'w') as json_file: json.dump(jsn, json_file, indent=4) def create_css(output_css,jsn): csstxt = "" csstxt += """ @font-face {\n font-display:block; font-family:\"octicons\"; src: url(./fonts/octicon.woff2) format("woff2"), url(./fonts/octicon.woff) format("woff"); }\n""" csstxt += """.oi::before, [class^="oi-"]::before, [class*="oi-"]::before { display:inline-block; font-family: octicons !important; font-style: normal; font-weight: normal !important; font-variant: normal; text-transform: none; line-height: 1; vertical-align: -.125em; -webkit-font-smoothing: antialiased; -mos-osx-font-smoothing: grayscale }\n""" with open(output_json, "r") as jsn: m = jsn.read() jso = json.loads(m) for i in jso.items(): csstxt += ".oi-"+str(i[1]) + "::before { content: \"\\f"+i[0] + "\"; }\n" handle = open(output_css,"w");handle.write(csstxt) if __name__ == "__main__": svg_directory = './icons' output_woff = './css/octicon' output_json = './css/octicon-map.json' output_css = "./css/octicon.css" svg_files = [os.path.join(svg_directory, f) for f in os.listdir(svg_directory) if f.endswith('.svg')] create_woff_font(svg_files, output_woff, output_json) create_css(output_css,output_json)
备注:内容来源于stack exchange,提问作者The Heavy
相关产品推荐
相关产品推荐

