in src/core/fonts.js [763:881]
function createOS2Table(properties, charstrings, override) {
override ||= {
unitsPerEm: 0,
yMax: 0,
yMin: 0,
ascent: 0,
descent: 0,
};
let ulUnicodeRange1 = 0;
let ulUnicodeRange2 = 0;
let ulUnicodeRange3 = 0;
let ulUnicodeRange4 = 0;
let firstCharIndex = null;
let lastCharIndex = 0;
let position = -1;
if (charstrings) {
for (let code in charstrings) {
code |= 0;
if (firstCharIndex > code || !firstCharIndex) {
firstCharIndex = code;
}
if (lastCharIndex < code) {
lastCharIndex = code;
}
position = getUnicodeRangeFor(code, position);
if (position < 32) {
ulUnicodeRange1 |= 1 << position;
} else if (position < 64) {
ulUnicodeRange2 |= 1 << (position - 32);
} else if (position < 96) {
ulUnicodeRange3 |= 1 << (position - 64);
} else if (position < 123) {
ulUnicodeRange4 |= 1 << (position - 96);
} else {
throw new FormatError(
"Unicode ranges Bits > 123 are reserved for internal usage"
);
}
}
if (lastCharIndex > 0xffff) {
// OS2 only supports a 16 bit int. The spec says if supplementary
// characters are used the field should just be set to 0xFFFF.
lastCharIndex = 0xffff;
}
} else {
// TODO
firstCharIndex = 0;
lastCharIndex = 255;
}
const bbox = properties.bbox || [0, 0, 0, 0];
const unitsPerEm =
override.unitsPerEm ||
(properties.fontMatrix
? 1 / Math.max(...properties.fontMatrix.slice(0, 4).map(Math.abs))
: 1000);
// if the font units differ to the PDF glyph space units
// then scale up the values
const scale = properties.ascentScaled
? 1.0
: unitsPerEm / PDF_GLYPH_SPACE_UNITS;
const typoAscent =
override.ascent || Math.round(scale * (properties.ascent || bbox[3]));
let typoDescent =
override.descent || Math.round(scale * (properties.descent || bbox[1]));
if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
typoDescent = -typoDescent; // fixing incorrect descent
}
const winAscent = override.yMax || typoAscent;
const winDescent = -override.yMin || -typoDescent;
return (
"\x00\x03" + // version
"\x02\x24" + // xAvgCharWidth
"\x01\xF4" + // usWeightClass
"\x00\x05" + // usWidthClass
"\x00\x00" + // fstype (0 to let the font loads via font-face on IE)
"\x02\x8A" + // ySubscriptXSize
"\x02\xBB" + // ySubscriptYSize
"\x00\x00" + // ySubscriptXOffset
"\x00\x8C" + // ySubscriptYOffset
"\x02\x8A" + // ySuperScriptXSize
"\x02\xBB" + // ySuperScriptYSize
"\x00\x00" + // ySuperScriptXOffset
"\x01\xDF" + // ySuperScriptYOffset
"\x00\x31" + // yStrikeOutSize
"\x01\x02" + // yStrikeOutPosition
"\x00\x00" + // sFamilyClass
"\x00\x00\x06" +
String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) +
"\x00\x00\x00\x00\x00\x00" + // Panose
string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31)
string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63)
string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95)
string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127)
"\x2A\x32\x31\x2A" + // achVendID
string16(properties.italicAngle ? 1 : 0) + // fsSelection
string16(firstCharIndex || properties.firstChar) + // usFirstCharIndex
string16(lastCharIndex || properties.lastChar) + // usLastCharIndex
string16(typoAscent) + // sTypoAscender
string16(typoDescent) + // sTypoDescender
"\x00\x64" + // sTypoLineGap (7%-10% of the unitsPerEM value)
string16(winAscent) + // usWinAscent
string16(winDescent) + // usWinDescent
"\x00\x00\x00\x00" + // ulCodePageRange1 (Bits 0-31)
"\x00\x00\x00\x00" + // ulCodePageRange2 (Bits 32-63)
string16(properties.xHeight) + // sxHeight
string16(properties.capHeight) + // sCapHeight
string16(0) + // usDefaultChar
string16(firstCharIndex || properties.firstChar) + // usBreakChar
"\x00\x03"
); // usMaxContext
}