Search code examples
pythonpython-3.xwoff

assistance with using fontTools


So i’ve been trying to compact primer/Octicons into a singular woff file such that it could be used in tandem with a css file referencing each and every svg as a unicode character, ive gotten to the point of being able to at least get a general idea of what it does but the documentation does not explain enough as to sucessfully tie svgs in a woff file to unicode characters

my expected result was a result like with Bootstrap Icons, where all their svgs are packed in a singular woff file and referenced in a css file such that it could be used with the < i > class (yes i know its italics), but every attempt i try to do it i either get hit in the face with a error, Ive used ai to no avail, so I'm ending up trying to build the script myself

ive managed to produce some result but i haven't tested it in a web dev environment the repo can be found here

Update: does not work, each icon appears as an unknown unicode character woff file not working

<!--I WANT THIS TO STAY LIKE THIS-->
<i class='oi oi-codepilot-16'></i>
/*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(https://extravagantboost.github.io/octicons-css/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: antiailiased;
    -mos-osx-font-smoothing: grayscale
}
/*. . .*/
/*python generated code*/
.oi-copilot-16::before { content: "\f57481"; }
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: antiailiased;
    -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)



Solution

  • Found different module supporting different language, svgtofont, does exactly what i want, without having to create tables or some really advanced python script