UNPKG

svg2ttf

Version:

Converts SVG font to TTF font

90 lines (80 loc) 4.05 kB
'use strict' // See documentation here: http://www.microsoft.com/typography/otspec/os2.htm var _ = require('lodash') var identifier = require('../utils.js').identifier var ByteBuffer = require('microbuffer') // get first glyph unicode function getFirstCharIndex (font) { return Math.max(0, Math.min(0xffff, Math.abs(_.minBy(Object.keys(font.codePoints), function (point) { return parseInt(point, 10) })))) } // get last glyph unicode function getLastCharIndex (font) { return Math.max(0, Math.min(0xffff, Math.abs(_.maxBy(Object.keys(font.codePoints), function (point) { return parseInt(point, 10) })))) } // OpenType spec: https://docs.microsoft.com/en-us/typography/opentype/spec/os2 function createOS2Table (font) { // use at least 2 for ligatures and kerning var maxContext = font.ligatures.map(function (l) { return l.unicode.length }).reduce(function (a, b) { return Math.max(a, b) }, 2) var buf = new ByteBuffer(96) // Version 5 is not supported in the Android 5 browser. buf.writeUint16(4) // version buf.writeInt16(font.avgWidth) // xAvgCharWidth buf.writeUint16(font.weightClass) // usWeightClass buf.writeUint16(font.widthClass) // usWidthClass buf.writeInt16(font.fsType) // fsType buf.writeInt16(font.ySubscriptXSize) // ySubscriptXSize buf.writeInt16(font.ySubscriptYSize) // ySubscriptYSize buf.writeInt16(font.ySubscriptXOffset) // ySubscriptXOffset buf.writeInt16(font.ySubscriptYOffset) // ySubscriptYOffset buf.writeInt16(font.ySuperscriptXSize) // ySuperscriptXSize buf.writeInt16(font.ySuperscriptYSize) // ySuperscriptYSize buf.writeInt16(font.ySuperscriptXOffset) // ySuperscriptXOffset buf.writeInt16(font.ySuperscriptYOffset) // ySuperscriptYOffset buf.writeInt16(font.yStrikeoutSize) // yStrikeoutSize buf.writeInt16(font.yStrikeoutPosition) // yStrikeoutPosition buf.writeInt16(font.familyClass) // sFamilyClass buf.writeUint8(font.panose.familyType) // panose.bFamilyType buf.writeUint8(font.panose.serifStyle) // panose.bSerifStyle buf.writeUint8(font.panose.weight) // panose.bWeight buf.writeUint8(font.panose.proportion) // panose.bProportion buf.writeUint8(font.panose.contrast) // panose.bContrast buf.writeUint8(font.panose.strokeVariation) // panose.bStrokeVariation buf.writeUint8(font.panose.armStyle) // panose.bArmStyle buf.writeUint8(font.panose.letterform) // panose.bLetterform buf.writeUint8(font.panose.midline) // panose.bMidline buf.writeUint8(font.panose.xHeight) // panose.bXHeight // TODO: This field is used to specify the Unicode blocks or ranges based on the 'cmap' table. buf.writeUint32(0) // ulUnicodeRange1 buf.writeUint32(0) // ulUnicodeRange2 buf.writeUint32(0) // ulUnicodeRange3 buf.writeUint32(0) // ulUnicodeRange4 buf.writeUint32(identifier('PfEd')) // achVendID, equal to PfEd buf.writeUint16(font.fsSelection) // fsSelection buf.writeUint16(getFirstCharIndex(font)) // usFirstCharIndex buf.writeUint16(getLastCharIndex(font)) // usLastCharIndex buf.writeInt16(font.ascent) // sTypoAscender buf.writeInt16(font.descent) // sTypoDescender buf.writeInt16(font.lineGap) // lineGap // Enlarge win acscent/descent to avoid clipping // WinAscent - WinDecent should at least be equal to TypoAscender - TypoDescender + TypoLineGap: // https://www.high-logic.com/font-editor/fontcreator/tutorials/font-metrics-vertical-line-spacing buf.writeInt16(Math.max(font.yMax, font.ascent + font.lineGap)) // usWinAscent buf.writeInt16(-Math.min(font.yMin, font.descent)) // usWinDescent buf.writeInt32(1) // ulCodePageRange1, Latin 1 buf.writeInt32(0) // ulCodePageRange2 buf.writeInt16(font.xHeight) // sxHeight buf.writeInt16(font.capHeight) // sCapHeight buf.writeUint16(0) // usDefaultChar, pointing to missing glyph (always id=0) buf.writeUint16(0) // usBreakChar, code=32 isn't guaranteed to be a space in icon fonts buf.writeUint16(maxContext) // usMaxContext, use at least 2 for ligatures and kerning return buf } module.exports = createOS2Table