Search code examples
metadatafontforge

Where/how does fontforge get a 'fontid'/filename value?


I tried asking this question on the github discussions for the fontforge repository, but no one appears to be answering it. I am using fontforge to generate SVG fonts for a php utility that generates SVG files from text strings.

Since I'm also trying to make a web-based gui to make generating these files easier, I'm also using fontforge to generate WOFF* equivalents.

While the final form will use a generate script, initially I was using the fontforge GUI and noticed it creates/suggests a uniform 'output' filename.

e.g. for Arial.ttf, output files are named ArialMT.woff or ArialMT.svg. I also noticed in the SVG file that it sets the 'fontid' attribute to the same value.

However, looking in the headers (both in fontforge 'elements' tabs and using multiple ttf-meta parsing libraries in php) I can't seem to find a 1-to-1 field where this value is coming from. So I suspect something in fontforge itself is sanitizing some other field to come up with this value.

I'm hoping to find out the 'rules' the method of coming up with this name follow (or if the value is hiding somewhere else, where to find it) so that I can generate names in my script that would be consistent with names generated by the GUI.

Does anyone know how fontforge comes up with it's suggestion for filename/fontid?

Looked in ttf headers, fontforge 'elements' tabs, dumped meta details with more than one php ttf-library tools.


Solution

  • With the advice from Heirstrietzel, I found a better solution for converting the fonts right in the browser or node.js using opentype.js. And it should avoid having to store different versions of the font entirely or coming up with names for them. The core of it from the browser side is an async function using the browser version of opentype.js.

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/opentype.min.js"></script>
    <script type="application/ecmascript">
        const FONTDIR = './fonts/';
    
        function roundTwo(num) { return Math.round(num * 100) / 100; }
    
        async function svgFont(fontname='ArialMT', text=null, fontSize=24) {
            let fnbase = fontname.replace(/\.[^/.]{3,5}$/, "");
            if(text === null) text = fnbase;
            // assumes fonts are .ttf
            let fonturl = FONTDIR + fnbase + '.ttf';
            let buffer = await (await fetch(fonturl)).arrayBuffer();
            let font = opentype.parse(buffer);
            let pathOT = font.getPath(text, 0, fontSize, fontSize);
            let bb = pathOT.getBoundingBox();
    
            let newSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            newSvg.setAttribute('viewBox', [ roundTwo(bb.x1-1), roundTwo(bb.y1-1), roundTwo(bb.x2-bb.x1+2), roundTwo(bb.y2-bb.y1+1) ].join());
            let newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            newPath.setAttribute('d', pathOT.toPathData());
            newSvg.appendChild(newPath);
            return newSvg.outerHTML;
        }
    
    </script>