You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

90 lines
4.0 KiB

'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;