mirror of
https://github.com/2234839/web-font.git
synced 2026-06-30 04:38:24 +08:00
优化2
This commit is contained in:
parent
d43255aba0
commit
2aa6852dca
35
vendor/fonteditor-core/lib/graphics/pathCeil.js
vendored
35
vendor/fonteditor-core/lib/graphics/pathCeil.js
vendored
@ -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;
|
||||
|
||||
@ -22,25 +22,35 @@ exports.default = transform;
|
||||
/**
|
||||
* 图形仿射矩阵变换
|
||||
*
|
||||
* @param {Array.<Object>} 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.<Object>} 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;
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
172
vendor/fonteditor-core/lib/ttf/table/glyf/sizeof.js
vendored
172
vendor/fonteditor-core/lib/ttf/table/glyf/sizeof.js
vendored
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
// 整数化
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user