UNPKG

fonteditor-core

Version:

fonts (ttf, woff, woff2, eot, svg, otf) parse, write, transform, glyph adjust.

274 lines (257 loc) 7.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = parseGlyf; var _glyFlag = _interopRequireDefault(require("../../enum/glyFlag")); var _componentFlag = _interopRequireDefault(require("../../enum/componentFlag")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * @file 解析glyf轮廓 * @author mengke01(kekee000@gmail.com) */ var MAX_INSTRUCTION_LENGTH = 5000; // 设置instructions阈值防止读取错误 var MAX_NUMBER_OF_COORDINATES = 20000; // 设置坐标最大个数阈值,防止glyf读取错误 /** * 读取简单字形 * * @param {Reader} reader Reader对象 * @param {Object} glyf 空glyf * @return {Object} 解析后的glyf */ function parseSimpleGlyf(reader, glyf) { var offset = reader.offset; // 轮廓点个数 var numberOfCoordinates = glyf.endPtsOfContours[glyf.endPtsOfContours.length - 1] + 1; // 判断坐标是否超过最大个数 if (numberOfCoordinates > MAX_NUMBER_OF_COORDINATES) { console.warn('error read glyf coordinates:' + offset); return glyf; } // 获取flag标志 var i; var length; var flags = []; var flag; i = 0; while (i < numberOfCoordinates) { flag = reader.readUint8(); flags.push(flag); i++; // 标志位3重复flag if (flag & _glyFlag.default.REPEAT && i < numberOfCoordinates) { // 重复个数 var repeat = reader.readUint8(); for (var j = 0; j < repeat; j++) { flags.push(flag); i++; } } } // 坐标集合 var coordinates = []; var xCoordinates = []; var prevX = 0; var x; for (i = 0, length = flags.length; i < length; ++i) { x = 0; flag = flags[i]; // 标志位1 // If set, the corresponding y-coordinate is 1 byte long, not 2 if (flag & _glyFlag.default.XSHORT) { x = reader.readUint8(); // 标志位5 x = flag & _glyFlag.default.XSAME ? x : -1 * x; } // 与上一值一致 else if (flag & _glyFlag.default.XSAME) { x = 0; } // 新值 else { x = reader.readInt16(); } prevX += x; xCoordinates[i] = prevX; coordinates[i] = { x: prevX, y: 0 }; if (flag & _glyFlag.default.ONCURVE) { coordinates[i].onCurve = true; } } var yCoordinates = []; var prevY = 0; var y; for (i = 0, length = flags.length; i < length; i++) { y = 0; flag = flags[i]; if (flag & _glyFlag.default.YSHORT) { y = reader.readUint8(); y = flag & _glyFlag.default.YSAME ? y : -1 * y; } else if (flag & _glyFlag.default.YSAME) { y = 0; } else { y = reader.readInt16(); } prevY += y; yCoordinates[i] = prevY; if (coordinates[i]) { coordinates[i].y = prevY; } } // 计算轮廓集合 if (coordinates.length) { var endPtsOfContours = glyf.endPtsOfContours; var contours = []; contours.push(coordinates.slice(0, endPtsOfContours[0] + 1)); for (i = 1, length = endPtsOfContours.length; i < length; i++) { contours.push(coordinates.slice(endPtsOfContours[i - 1] + 1, endPtsOfContours[i] + 1)); } glyf.contours = contours; } return glyf; } /** * 读取复合字形 * * @param {Reader} reader Reader对象 * @param {Object} glyf glyf对象 * @return {Object} glyf对象 */ function parseCompoundGlyf(reader, glyf) { glyf.compound = true; glyf.glyfs = []; var flags; var g; // 读取复杂字形 do { flags = reader.readUint16(); g = {}; g.flags = flags; g.glyphIndex = reader.readUint16(); var arg1 = 0; var arg2 = 0; var scaleX = 16384; var scaleY = 16384; var scale01 = 0; var scale10 = 0; if (_componentFlag.default.ARG_1_AND_2_ARE_WORDS & flags) { arg1 = reader.readInt16(); arg2 = reader.readInt16(); } else { arg1 = reader.readInt8(); arg2 = reader.readInt8(); } if (_componentFlag.default.ROUND_XY_TO_GRID & flags) { arg1 = Math.round(arg1); arg2 = Math.round(arg2); } if (_componentFlag.default.WE_HAVE_A_SCALE & flags) { scaleX = reader.readInt16(); scaleY = scaleX; } else if (_componentFlag.default.WE_HAVE_AN_X_AND_Y_SCALE & flags) { scaleX = reader.readInt16(); scaleY = reader.readInt16(); } else if (_componentFlag.default.WE_HAVE_A_TWO_BY_TWO & flags) { scaleX = reader.readInt16(); scale01 = reader.readInt16(); scale10 = reader.readInt16(); scaleY = reader.readInt16(); } if (_componentFlag.default.ARGS_ARE_XY_VALUES & flags) { g.useMyMetrics = !!flags & _componentFlag.default.USE_MY_METRICS; g.overlapCompound = !!flags & _componentFlag.default.OVERLAP_COMPOUND; g.transform = { a: Math.round(10000 * scaleX / 16384) / 10000, b: Math.round(10000 * scale01 / 16384) / 10000, c: Math.round(10000 * scale10 / 16384) / 10000, d: Math.round(10000 * scaleY / 16384) / 10000, e: arg1, f: arg2 }; } else { g.points = [arg1, arg2]; g.transform = { a: Math.round(10000 * scaleX / 16384) / 10000, b: Math.round(10000 * scale01 / 16384) / 10000, c: Math.round(10000 * scale10 / 16384) / 10000, d: Math.round(10000 * scaleY / 16384) / 10000, e: 0, f: 0 }; } glyf.glyfs.push(g); } while (_componentFlag.default.MORE_COMPONENTS & flags); if (_componentFlag.default.WE_HAVE_INSTRUCTIONS & flags) { var length = reader.readUint16(); if (length < MAX_INSTRUCTION_LENGTH) { var instructions = []; for (var i = 0; i < length; ++i) { instructions.push(reader.readUint8()); } glyf.instructions = instructions; } else { console.warn(length); } } return glyf; } /** * 解析glyf轮廓 * * @param {Reader} reader 读取器 * @param {Object} ttf ttf对象 * @param {number=} offset 偏移 * @return {Object} glyf对象 */ function parseGlyf(reader, ttf, offset) { if (null != offset) { reader.seek(offset); } var glyf = {}; var i; var length; var instructions; // 边界值 var numberOfContours = reader.readInt16(); glyf.xMin = reader.readInt16(); glyf.yMin = reader.readInt16(); glyf.xMax = reader.readInt16(); glyf.yMax = reader.readInt16(); // 读取简单字形 if (numberOfContours >= 0) { // endPtsOfConturs glyf.endPtsOfContours = []; if (numberOfContours > 0) { for (i = 0; i < numberOfContours; i++) { glyf.endPtsOfContours.push(reader.readUint16()); } } else { delete glyf.xMin; delete glyf.yMin; delete glyf.xMax; delete glyf.yMax; } // instructions length = reader.readUint16(); if (length) { // range错误 if (length < MAX_INSTRUCTION_LENGTH) { instructions = []; for (i = 0; i < length; ++i) { instructions.push(reader.readUint8()); } glyf.instructions = instructions; } else { console.warn(length); } } parseSimpleGlyf(reader, glyf); delete glyf.endPtsOfContours; } else { parseCompoundGlyf(reader, glyf); } return glyf; }