diff --git a/vendor/fonteditor-core/lib/graphics/pathCeil.js b/vendor/fonteditor-core/lib/graphics/pathCeil.js index 4e88753..8d0b8b8 100644 --- a/vendor/fonteditor-core/lib/graphics/pathCeil.js +++ b/vendor/fonteditor-core/lib/graphics/pathCeil.js @@ -12,20 +12,35 @@ exports.default = pathCeil; /** * 对path坐标进行调整 * - * @param {Array} contour 轮廓点数组 + * @param {Array} contour 轮廓点数组(对象格式或扁平格式 [x, y, onCurve, ...]) * @param {number} point 四舍五入的点数 * @return {Object} contour 坐标点 */ function pathCeil(contour, point) { - var p; - for (var i = 0, l = contour.length; i < l; i++) { - p = contour[i]; - if (!point) { - p.x = Math.round(p.x); - p.y = Math.round(p.y); - } else { - p.x = Number(p.x.toFixed(point)); - p.y = Number(p.y.toFixed(point)); + if (!contour.length) { + return contour; + } + /* 优化66: 检测扁平格式 - 第一个元素是 number 则为扁平格式 */ + if (typeof contour[0] === 'number') { + for (var i = 0, l = contour.length; i < l; i += 3) { + if (!point) { + contour[i] = Math.round(contour[i]); + contour[i + 1] = Math.round(contour[i + 1]); + } else { + contour[i] = Number(contour[i].toFixed(point)); + contour[i + 1] = Number(contour[i + 1].toFixed(point)); + } + } + } else { + for (var i = 0, l = contour.length; i < l; i++) { + var p = contour[i]; + if (!point) { + p.x = Math.round(p.x); + p.y = Math.round(p.y); + } else { + p.x = Number(p.x.toFixed(point)); + p.y = Number(p.y.toFixed(point)); + } } } return contour; diff --git a/vendor/fonteditor-core/lib/graphics/pathTransform.js b/vendor/fonteditor-core/lib/graphics/pathTransform.js index a8761ea..5cf3fc7 100644 --- a/vendor/fonteditor-core/lib/graphics/pathTransform.js +++ b/vendor/fonteditor-core/lib/graphics/pathTransform.js @@ -22,25 +22,35 @@ exports.default = transform; /** * 图形仿射矩阵变换 * - * @param {Array.} contour 轮廓点 + * @param {Array} contour 轮廓点(对象格式或扁平格式 [x, y, onCurve, ...]) * @param {number} a m11 * @param {number} b m12 * @param {number} c m21 * @param {number} d m22 * @param {number} e dx * @param {number} f dy - * @return {Array.} contour 轮廓点 + * @return {Array} contour 轮廓点 */ function transform(contour, a, b, c, d, e, f) { - var x; - var y; - var p; - for (var i = 0, l = contour.length; i < l; i++) { - p = contour[i]; - x = p.x; - y = p.y; - p.x = x * a + y * c + e; - p.y = x * b + y * d + f; + if (!contour.length) { + return contour; + } + /* 优化66: 检测扁平格式 - 第一个元素是 number 则为扁平格式 */ + if (typeof contour[0] === 'number') { + for (var i = 0, l = contour.length; i < l; i += 3) { + var x = contour[i]; + var y = contour[i + 1]; + contour[i] = x * a + y * c + e; + contour[i + 1] = x * b + y * d + f; + } + } else { + for (var i = 0, l = contour.length; i < l; i++) { + var p = contour[i]; + var x = p.x; + var y = p.y; + p.x = x * a + y * c + e; + p.y = x * b + y * d + f; + } } return contour; } \ No newline at end of file diff --git a/vendor/fonteditor-core/lib/graphics/reducePath.js b/vendor/fonteditor-core/lib/graphics/reducePath.js index 4edb77b..a3cd4ca 100644 --- a/vendor/fonteditor-core/lib/graphics/reducePath.js +++ b/vendor/fonteditor-core/lib/graphics/reducePath.js @@ -4,6 +4,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.default = reducePath; +var _reducePathFlat = _interopRequireDefault(require("./reducePathFlat")); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * @file 缩减path大小,去除冗余节点 * @author mengke01(kekee000@gmail.com) @@ -38,13 +40,17 @@ function redundant(prev, p, next) { /** * 缩减glyf,去除冗余节点 * - * @param {Array} contour 路径对象 + * @param {Array} contour 路径对象(对象格式或扁平格式 [x, y, onCurve, ...]) * @return {Array} 路径对象 */ function reducePath(contour) { if (!contour.length) { return contour; } + /* 优化66: 检测扁平格式 - 第一个元素是 number 则为扁平格式 */ + if (typeof contour[0] === 'number') { + return (0, _reducePathFlat.default)(contour); + } var prev; var next; var p; diff --git a/vendor/fonteditor-core/lib/ttf/table/glyf/parse.js b/vendor/fonteditor-core/lib/ttf/table/glyf/parse.js index 0a50995..50e2ebc 100644 --- a/vendor/fonteditor-core/lib/ttf/table/glyf/parse.js +++ b/vendor/fonteditor-core/lib/ttf/table/glyf/parse.js @@ -90,25 +90,26 @@ function parseSimpleGlyf(reader, glyf) { reader.offset = vOffset - view.byteOffset; - /* 优化9: 一次遍历构建 contours,消除中间数组 */ + /* 优化66: 扁平 contours [x, y, onCurve, x, y, onCurve, ...],消除大量小对象 */ if (numberOfCoordinates > 0) { var endPtsOfContours = glyf.endPtsOfContours; var contours = new Array(endPtsOfContours.length); var start = 0; for (var ci = 0, cl = endPtsOfContours.length; ci < cl; ci++) { var end = endPtsOfContours[ci] + 1; - var contour = new Array(end - start); + var numPoints = end - start; + var contour = new Array(numPoints * 3); + var ki = 0; for (var pi = start; pi < end; pi++) { - contour[pi - start] = { - x: xArr[pi], - y: yArr[pi], - onCurve: !!(flags[pi] & ONCURVE) - }; + contour[ki++] = xArr[pi]; + contour[ki++] = yArr[pi]; + contour[ki++] = !!(flags[pi] & ONCURVE); } contours[ci] = contour; start = end; } glyf.contours = contours; + glyf._flatContours = true; } return glyf; } diff --git a/vendor/fonteditor-core/lib/ttf/table/glyf/sizeof.js b/vendor/fonteditor-core/lib/ttf/table/glyf/sizeof.js index 59e2e69..ac00be3 100644 --- a/vendor/fonteditor-core/lib/ttf/table/glyf/sizeof.js +++ b/vendor/fonteditor-core/lib/ttf/table/glyf/sizeof.js @@ -12,7 +12,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de */ /** - * 优化33+38+39+40+48+49+57: getFlagsAndSize 单遍扫描替代两遍扫描 + * 优化33+38+39+40+48+49+57+66: getFlagsAndSize 单遍扫描替代两遍扫描,支持扁平 contours */ function getFlagsAndSize(glyf, glyfSupport, hinting) { if (!glyf.contours || glyf.contours.length === 0) { @@ -36,70 +36,128 @@ function getFlagsAndSize(glyf, glyfSupport, hinting) { var prevFlag = -1; var repeatPoint = -1; + /* 优化66: 检测扁平格式 */ + var isFlat = glyf._flatContours; + /* 单次遍历: delta坐标计算 + flag压缩 + 坐标编码 + 大小累加 */ var encodedCoordSize = 0; for (var j = 0, cl = contours.length; j < cl; j++) { var contour = contours[j]; - for (var i = 0, l = contour.length; i < l; i++) { - var point = contour[i]; - var px = point.x; - var py = point.y; - var dx, dy; - var flag = point.onCurve ? ONCURVE : 0; + if (isFlat) { + /* 优化66: 扁平格式,每3个元素为一个点 [x, y, onCurve, ...] */ + for (var i = 0, l = contour.length; i < l; i += 3) { + var px = contour[i]; + var py = contour[i + 1]; + var onCurve = contour[i + 2]; + var dx, dy; + var flag = onCurve ? ONCURVE : 0; - if (isFirst) { - dx = px; - dy = py; - isFirst = false; - } else { - dx = px - prevX; - dy = py - prevY; - } - prevX = px; - prevY = py; - - var xEncoded = 0; - var yEncoded = 0; - - if (dx === 0) { - flag += XSAME; - } else if (-0xFF <= dx && dx <= 0xFF) { - flag += XSHORT; - if (dx > 0) flag += XSAME; - xEncoded = Math.abs(dx); - xCoordC.push(xEncoded); - encodedCoordSize += 1; - } else { - xCoordC.push(dx); - encodedCoordSize += 2; - } - - if (dy === 0) { - flag += YSAME; - } else if (-0xFF <= dy && dy <= 0xFF) { - flag += YSHORT; - if (dy > 0) flag += YSAME; - yEncoded = Math.abs(dy); - yCoordC.push(yEncoded); - encodedCoordSize += 1; - } else { - yCoordC.push(dy); - encodedCoordSize += 2; - } - - /* REPEAT 压缩 */ - if (flag === prevFlag && !isFirst) { - if (repeatPoint === -1) { - repeatPoint = flagsC.length - 1; - flagsC[repeatPoint] |= REPEAT; - flagsC.push(1); + if (isFirst) { + dx = px; + dy = py; + isFirst = false; } else { - ++flagsC[repeatPoint + 1]; + dx = px - prevX; + dy = py - prevY; + } + prevX = px; + prevY = py; + + if (dx === 0) { + flag += XSAME; + } else if (-0xFF <= dx && dx <= 0xFF) { + flag += XSHORT; + if (dx > 0) flag += XSAME; + xCoordC.push(Math.abs(dx)); + encodedCoordSize += 1; + } else { + xCoordC.push(dx); + encodedCoordSize += 2; + } + + if (dy === 0) { + flag += YSAME; + } else if (-0xFF <= dy && dy <= 0xFF) { + flag += YSHORT; + if (dy > 0) flag += YSAME; + yCoordC.push(Math.abs(dy)); + encodedCoordSize += 1; + } else { + yCoordC.push(dy); + encodedCoordSize += 2; + } + + /* REPEAT 压缩 */ + if (flag === prevFlag && !isFirst) { + if (repeatPoint === -1) { + repeatPoint = flagsC.length - 1; + flagsC[repeatPoint] |= REPEAT; + flagsC.push(1); + } else { + ++flagsC[repeatPoint + 1]; + } + } else { + repeatPoint = -1; + flagsC.push(prevFlag = flag); + } + } + } else { + for (var i = 0, l = contour.length; i < l; i++) { + var point = contour[i]; + var px = point.x; + var py = point.y; + var dx, dy; + var flag = point.onCurve ? ONCURVE : 0; + + if (isFirst) { + dx = px; + dy = py; + isFirst = false; + } else { + dx = px - prevX; + dy = py - prevY; + } + prevX = px; + prevY = py; + + if (dx === 0) { + flag += XSAME; + } else if (-0xFF <= dx && dx <= 0xFF) { + flag += XSHORT; + if (dx > 0) flag += XSAME; + xCoordC.push(Math.abs(dx)); + encodedCoordSize += 1; + } else { + xCoordC.push(dx); + encodedCoordSize += 2; + } + + if (dy === 0) { + flag += YSAME; + } else if (-0xFF <= dy && dy <= 0xFF) { + flag += YSHORT; + if (dy > 0) flag += YSAME; + yCoordC.push(Math.abs(dy)); + encodedCoordSize += 1; + } else { + yCoordC.push(dy); + encodedCoordSize += 2; + } + + /* REPEAT 压缩 */ + if (flag === prevFlag && !isFirst) { + if (repeatPoint === -1) { + repeatPoint = flagsC.length - 1; + flagsC[repeatPoint] |= REPEAT; + flagsC.push(1); + } else { + ++flagsC[repeatPoint + 1]; + } + } else { + repeatPoint = -1; + flagsC.push(prevFlag = flag); } - } else { - repeatPoint = -1; - flagsC.push(prevFlag = flag); } } } diff --git a/vendor/fonteditor-core/lib/ttf/table/glyf/write.js b/vendor/fonteditor-core/lib/ttf/table/glyf/write.js index 36803d7..cd6a07a 100644 --- a/vendor/fonteditor-core/lib/ttf/table/glyf/write.js +++ b/vendor/fonteditor-core/lib/ttf/table/glyf/write.js @@ -96,11 +96,13 @@ function write(writer, ttf) { } } } else { - /* 优化32: endPtsOfContours 直接 view 写入 */ + /* 优化32+66: endPtsOfContours 直接 view 写入,支持扁平格式 */ var contours = glyf.contours || []; var endPts = -1; + /* 优化66: 扁平格式 contour.length 是点的3倍 */ + var isFlat = glyf._flatContours; for (var ci = 0, cl = contours.length; ci < cl; ci++) { - endPts += contours[ci].length; + endPts += isFlat ? contours[ci].length / 3 : contours[ci].length; view.setUint16(pos, endPts, false); pos += 2; } diff --git a/vendor/fonteditor-core/lib/ttf/util/compound2simpleglyf.js b/vendor/fonteditor-core/lib/ttf/util/compound2simpleglyf.js index abb06a5..e9d9a7f 100644 --- a/vendor/fonteditor-core/lib/ttf/util/compound2simpleglyf.js +++ b/vendor/fonteditor-core/lib/ttf/util/compound2simpleglyf.js @@ -39,10 +39,19 @@ function compound2simpleglyf(glyf, ttf, recrusive) { (0, _transformGlyfContours.default)(glyf, ttf, contoursList, glyfIndex); if (recrusive) { Object.keys(contoursList).forEach(function (index) { - (0, _compound2simple.default)(ttf.glyf[index], contoursList[index]); + var target = ttf.glyf[index]; + (0, _compound2simple.default)(target, contoursList[index]); + /* 优化66: 检测扁平格式并设置标记 */ + if (target.contours && target.contours.length && typeof target.contours[0][0] === 'number') { + target._flatContours = true; + } }); } else { (0, _compound2simple.default)(glyf, contoursList[glyfIndex]); + /* 优化66: 检测扁平格式并设置标记 */ + if (glyf.contours && glyf.contours.length && typeof glyf.contours[0][0] === 'number') { + glyf._flatContours = true; + } } return glyf; } \ No newline at end of file diff --git a/vendor/fonteditor-core/lib/ttf/util/optimizettf.js b/vendor/fonteditor-core/lib/ttf/util/optimizettf.js index e4eb7bb..d9846c3 100644 --- a/vendor/fonteditor-core/lib/ttf/util/optimizettf.js +++ b/vendor/fonteditor-core/lib/ttf/util/optimizettf.js @@ -6,12 +6,41 @@ Object.defineProperty(exports, "__esModule", { exports.default = optimizettf; var _reduceGlyf = _interopRequireDefault(require("./reduceGlyf")); var _pathCeil = _interopRequireDefault(require("../../graphics/pathCeil")); +var _reducePathFlat = _interopRequireDefault(require("../../graphics/reducePathFlat")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * @file 对ttf对象进行优化,查找错误,去除冗余点 * @author mengke01(kekee000@gmail.com) */ +/** + * 优化17+66: 扁平格式单次遍历 pathCeil + reducePath + * 先四舍五入坐标,再去除冗余点,一次循环完成 + */ +function ceilAndReduceFlat(glyf) { + var contours = glyf.contours; + for (var j = contours.length - 1; j >= 0; j--) { + var contour = contours[j]; + /* 先原地四舍五入 */ + for (var i = 0, l = contour.length; i < l; i += 3) { + contour[i] = Math.round(contour[i]); + contour[i + 1] = Math.round(contour[i + 1]); + } + /* 再去除冗余点 */ + contour = (0, _reducePathFlat.default)(contour); + /* 空轮廓:扁平格式 <= 6 元素(2个点) */ + if (contour.length <= 6) { + contours.splice(j, 1); + } else { + contours[j] = contour; + } + } + if (0 === contours.length) { + delete glyf.contours; + } + return glyf; +} + /** * 对ttf对象进行优化 * @@ -37,12 +66,17 @@ function optimizettf(ttf) { }); } if (!glyf.compound && glyf.contours) { - // 整数化 - glyf.contours.forEach(function (contour) { - (0, _pathCeil.default)(contour); - }); - // 缩减glyf - (0, _reduceGlyf.default)(glyf); + if (glyf._flatContours) { + /* 优化17+66: 扁平格式单次遍历 pathCeil + reduceGlyf */ + ceilAndReduceFlat(glyf); + } else { + /* 整数化 */ + glyf.contours.forEach(function (contour) { + (0, _pathCeil.default)(contour); + }); + /* 缩减glyf */ + (0, _reduceGlyf.default)(glyf); + } } // 整数化 diff --git a/vendor/fonteditor-core/lib/ttf/util/reduceGlyf.js b/vendor/fonteditor-core/lib/ttf/util/reduceGlyf.js index 30b2190..8cb2d7d 100644 --- a/vendor/fonteditor-core/lib/ttf/util/reduceGlyf.js +++ b/vendor/fonteditor-core/lib/ttf/util/reduceGlyf.js @@ -20,11 +20,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de function reduceGlyf(glyf) { var contours = glyf.contours; var contour; + /* 优化66: 扁平格式下 contour.length 是点的3倍 */ + var isFlat = glyf._flatContours; + var minLen = isFlat ? 6 : 2; for (var j = contours.length - 1; j >= 0; j--) { contour = (0, _reducePath.default)(contours[j]); - // 空轮廓 - if (contour.length <= 2) { + /* 空轮廓:扁平格式 <= 6 元素(2个点),对象格式 <= 2 个点 */ + if (contour.length <= minLen) { contours.splice(j, 1); continue; } diff --git a/vendor/fonteditor-core/lib/ttf/util/transformGlyfContours.js b/vendor/fonteditor-core/lib/ttf/util/transformGlyfContours.js index b393f3d..e05d713 100644 --- a/vendor/fonteditor-core/lib/ttf/util/transformGlyfContours.js +++ b/vendor/fonteditor-core/lib/ttf/util/transformGlyfContours.js @@ -13,6 +13,20 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de * @author mengke01(kekee000@gmail.com) */ +/** + * 优化15+66: 扁平格式单次遍历 pathTransform + pathCeil + * 先仿射变换坐标,再四舍五入,一次循环完成 + */ +function transformAndCeilFlat(contour, a, b, c, d, e, f) { + for (var i = 0, l = contour.length; i < l; i += 3) { + var x = contour[i]; + var y = contour[i + 1]; + contour[i] = Math.round(x * a + y * c + e); + contour[i + 1] = Math.round(x * b + y * d + f); + } + return contour; +} + /** * 转换复合字形轮廓,结果保存在contoursList中,并返回当前glyf的轮廓 * @@ -40,12 +54,22 @@ function transformGlyfContours(glyf, ttf) { transformGlyfContours(glyph, ttf, contoursList, g.glyphIndex); } - // 这里需要进行matrix变换,需要复制一份 - var contours = (0, _lang.clone)(glyph.compound ? contoursList[g.glyphIndex] || [] : glyph.contours); + var sourceContours = glyph.compound ? contoursList[g.glyphIndex] || [] : glyph.contours; var transform = g.transform; - for (var i = 0, l = contours.length; i < l; i++) { - (0, _pathTransform.default)(contours[i], transform.a, transform.b, transform.c, transform.d, transform.e, transform.f); - compoundContours.push((0, _pathCeil.default)(contours[i])); + + if (sourceContours.length && typeof sourceContours[0][0] === 'number') { + /* 优化14+15+66: 扁平格式 - 浅拷贝 + 单次遍历 transform+ceil */ + for (var i = 0, l = sourceContours.length; i < l; i++) { + var contour = sourceContours[i].slice(); + compoundContours.push(transformAndCeilFlat(contour, transform.a, transform.b, transform.c, transform.d, transform.e, transform.f)); + } + } else { + /* 传统对象格式 - 深拷贝 + 分别调用 transform+ceil */ + var contours = (0, _lang.clone)(sourceContours); + for (var i = 0, l = contours.length; i < l; i++) { + (0, _pathTransform.default)(contours[i], transform.a, transform.b, transform.c, transform.d, transform.e, transform.f); + compoundContours.push((0, _pathCeil.default)(contours[i])); + } } });