fonteditor-core
Version:
fonts (ttf, woff, woff2, eot, svg, otf) parse, write, transform, glyph adjust.
251 lines (237 loc) • 9.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _table = _interopRequireDefault(require("./table"));
var _struct = _interopRequireDefault(require("./struct"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @file OS/2表
* @author mengke01(kekee000@gmail.com)
*
* http://www.microsoft.com/typography/otspec/os2.htm
*/
var _default = exports.default = _table.default.create('OS/2', [['version', _struct.default.Uint16], ['xAvgCharWidth', _struct.default.Int16], ['usWeightClass', _struct.default.Uint16], ['usWidthClass', _struct.default.Uint16], ['fsType', _struct.default.Uint16], ['ySubscriptXSize', _struct.default.Uint16], ['ySubscriptYSize', _struct.default.Uint16], ['ySubscriptXOffset', _struct.default.Uint16], ['ySubscriptYOffset', _struct.default.Uint16], ['ySuperscriptXSize', _struct.default.Uint16], ['ySuperscriptYSize', _struct.default.Uint16], ['ySuperscriptXOffset', _struct.default.Uint16], ['ySuperscriptYOffset', _struct.default.Uint16], ['yStrikeoutSize', _struct.default.Uint16], ['yStrikeoutPosition', _struct.default.Uint16], ['sFamilyClass', _struct.default.Uint16],
// Panose
['bFamilyType', _struct.default.Uint8], ['bSerifStyle', _struct.default.Uint8], ['bWeight', _struct.default.Uint8], ['bProportion', _struct.default.Uint8], ['bContrast', _struct.default.Uint8], ['bStrokeVariation', _struct.default.Uint8], ['bArmStyle', _struct.default.Uint8], ['bLetterform', _struct.default.Uint8], ['bMidline', _struct.default.Uint8], ['bXHeight', _struct.default.Uint8],
// unicode range
['ulUnicodeRange1', _struct.default.Uint32], ['ulUnicodeRange2', _struct.default.Uint32], ['ulUnicodeRange3', _struct.default.Uint32], ['ulUnicodeRange4', _struct.default.Uint32],
// char 4
['achVendID', _struct.default.String, 4], ['fsSelection', _struct.default.Uint16], ['usFirstCharIndex', _struct.default.Uint16], ['usLastCharIndex', _struct.default.Uint16], ['sTypoAscender', _struct.default.Int16], ['sTypoDescender', _struct.default.Int16], ['sTypoLineGap', _struct.default.Int16], ['usWinAscent', _struct.default.Uint16], ['usWinDescent', _struct.default.Uint16],
// version 0 above 39
['ulCodePageRange1', _struct.default.Uint32], ['ulCodePageRange2', _struct.default.Uint32],
// version 1 above 41
['sxHeight', _struct.default.Int16], ['sCapHeight', _struct.default.Int16], ['usDefaultChar', _struct.default.Uint16], ['usBreakChar', _struct.default.Uint16], ['usMaxContext', _struct.default.Uint16]
// version 2,3,4 above 46
], {
read: function read(reader, ttf) {
var format = reader.readUint16(this.offset);
var struct = this.struct;
// format2
if (format === 0) {
struct = struct.slice(0, 39);
} else if (format === 1) {
struct = struct.slice(0, 41);
}
var OS2Head = _table.default.create('os2head', struct);
var tbl = new OS2Head(this.offset).read(reader, ttf);
// 补齐其他version的字段
var os2Fields = {
ulCodePageRange1: 1,
ulCodePageRange2: 0,
sxHeight: 0,
sCapHeight: 0,
usDefaultChar: 0,
usBreakChar: 32,
usMaxContext: 0
};
return Object.assign(os2Fields, tbl);
},
size: function size(ttf) {
// 更新其他表的统计信息
// header
var xMin = 16384;
var yMin = 16384;
var xMax = -16384;
var yMax = -16384;
// hhea
var advanceWidthMax = -1;
var minLeftSideBearing = 16384;
var minRightSideBearing = 16384;
var xMaxExtent = -16384;
// os2 count
var xAvgCharWidth = 0;
var usFirstCharIndex = 0x10FFFF;
var usLastCharIndex = -1;
// maxp
var maxPoints = 0;
var maxContours = 0;
var maxCompositePoints = 0;
var maxCompositeContours = 0;
var maxSizeOfInstructions = 0;
var maxComponentElements = 0;
var glyfNotEmpty = 0; // 非空glyf
var hinting = ttf.writeOptions ? ttf.writeOptions.hinting : false;
// 计算instructions和functiondefs
if (hinting) {
if (ttf.cvt) {
maxSizeOfInstructions = Math.max(maxSizeOfInstructions, ttf.cvt.length);
}
if (ttf.prep) {
maxSizeOfInstructions = Math.max(maxSizeOfInstructions, ttf.prep.length);
}
if (ttf.fpgm) {
maxSizeOfInstructions = Math.max(maxSizeOfInstructions, ttf.fpgm.length);
}
}
ttf.glyf.forEach(function (glyf) {
// 统计control point信息
if (glyf.compound) {
var compositeContours = 0;
var compositePoints = 0;
glyf.glyfs.forEach(function (g) {
var cglyf = ttf.glyf[g.glyphIndex];
if (!cglyf) {
return;
}
compositeContours += cglyf.contours ? cglyf.contours.length : 0;
if (cglyf.contours && cglyf.contours.length) {
cglyf.contours.forEach(function (contour) {
compositePoints += contour.length;
});
}
});
maxComponentElements = Math.max(maxComponentElements, glyf.glyfs.length);
maxCompositePoints = Math.max(maxCompositePoints, compositePoints);
maxCompositeContours = Math.max(maxCompositeContours, compositeContours);
}
// 简单图元
else if (glyf.contours && glyf.contours.length) {
maxContours = Math.max(maxContours, glyf.contours.length);
var points = 0;
glyf.contours.forEach(function (contour) {
points += contour.length;
});
maxPoints = Math.max(maxPoints, points);
}
if (hinting && glyf.instructions) {
maxSizeOfInstructions = Math.max(maxSizeOfInstructions, glyf.instructions.length);
}
// 统计边界信息
if (null != glyf.xMin && glyf.xMin < xMin) {
xMin = glyf.xMin;
}
if (null != glyf.yMin && glyf.yMin < yMin) {
yMin = glyf.yMin;
}
if (null != glyf.xMax && glyf.xMax > xMax) {
xMax = glyf.xMax;
}
if (null != glyf.yMax && glyf.yMax > yMax) {
yMax = glyf.yMax;
}
advanceWidthMax = Math.max(advanceWidthMax, glyf.advanceWidth);
minLeftSideBearing = Math.min(minLeftSideBearing, glyf.leftSideBearing);
if (null != glyf.xMax) {
minRightSideBearing = Math.min(minRightSideBearing, glyf.advanceWidth - glyf.xMax);
xMaxExtent = Math.max(xMaxExtent, glyf.xMax);
}
if (null != glyf.advanceWidth) {
xAvgCharWidth += glyf.advanceWidth;
glyfNotEmpty++;
}
var unicodes = glyf.unicode;
if (typeof glyf.unicode === 'number') {
unicodes = [glyf.unicode];
}
if (Array.isArray(unicodes)) {
unicodes.forEach(function (unicode) {
if (unicode !== 0xFFFF) {
usFirstCharIndex = Math.min(usFirstCharIndex, unicode);
usLastCharIndex = Math.max(usLastCharIndex, unicode);
}
});
}
});
// 重新设置version 4
ttf['OS/2'].version = 0x4;
ttf['OS/2'].achVendID = (ttf['OS/2'].achVendID + ' ').slice(0, 4);
ttf['OS/2'].xAvgCharWidth = xAvgCharWidth / (glyfNotEmpty || 1);
ttf['OS/2'].ulUnicodeRange2 = 268435456;
ttf['OS/2'].usFirstCharIndex = usFirstCharIndex;
ttf['OS/2'].usLastCharIndex = usLastCharIndex;
// rewrite hhea
ttf.hhea.version = ttf.hhea.version || 0x1;
ttf.hhea.advanceWidthMax = advanceWidthMax;
ttf.hhea.minLeftSideBearing = minLeftSideBearing;
ttf.hhea.minRightSideBearing = minRightSideBearing;
ttf.hhea.xMaxExtent = xMaxExtent;
// rewrite head
ttf.head.version = ttf.head.version || 0x1;
ttf.head.lowestRecPPEM = ttf.head.lowestRecPPEM || 0x8;
ttf.head.xMin = xMin;
ttf.head.yMin = yMin;
ttf.head.xMax = xMax;
ttf.head.yMax = yMax;
// head rewrite
if (ttf.support.head) {
var _ttf$support$head = ttf.support.head,
_xMin = _ttf$support$head.xMin,
_yMin = _ttf$support$head.yMin,
_xMax = _ttf$support$head.xMax,
_yMax = _ttf$support$head.yMax;
if (_xMin != null) {
ttf.head.xMin = _xMin;
}
if (_yMin != null) {
ttf.head.yMin = _yMin;
}
if (_xMax != null) {
ttf.head.xMax = _xMax;
}
if (_yMax != null) {
ttf.head.yMax = _yMax;
}
}
// hhea rewrite
if (ttf.support.hhea) {
var _ttf$support$hhea = ttf.support.hhea,
_advanceWidthMax = _ttf$support$hhea.advanceWidthMax,
_xMaxExtent = _ttf$support$hhea.xMaxExtent,
_minLeftSideBearing = _ttf$support$hhea.minLeftSideBearing,
_minRightSideBearing = _ttf$support$hhea.minRightSideBearing;
if (_advanceWidthMax != null) {
ttf.hhea.advanceWidthMax = _advanceWidthMax;
}
if (_xMaxExtent != null) {
ttf.hhea.xMaxExtent = _xMaxExtent;
}
if (_minLeftSideBearing != null) {
ttf.hhea.minLeftSideBearing = _minLeftSideBearing;
}
if (_minRightSideBearing != null) {
ttf.hhea.minRightSideBearing = _minRightSideBearing;
}
}
// 这里根据存储的maxp来设置新的maxp,避免重复计算maxp
ttf.maxp = ttf.maxp || {};
ttf.support.maxp = {
version: 1.0,
numGlyphs: ttf.glyf.length,
maxPoints: maxPoints,
maxContours: maxContours,
maxCompositePoints: maxCompositePoints,
maxCompositeContours: maxCompositeContours,
maxZones: ttf.maxp.maxZones || 0,
maxTwilightPoints: ttf.maxp.maxTwilightPoints || 0,
maxStorage: ttf.maxp.maxStorage || 0,
maxFunctionDefs: ttf.maxp.maxFunctionDefs || 0,
maxStackElements: ttf.maxp.maxStackElements || 0,
maxSizeOfInstructions: maxSizeOfInstructions,
maxComponentElements: maxComponentElements,
maxComponentDepth: maxComponentElements ? 1 : 0
};
return _table.default.size.call(this, ttf);
}
});