860 lines
26 KiB
Plaintext
860 lines
26 KiB
Plaintext
"use strict";
|
|
|
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
var _lang = require("../common/lang");
|
|
var _string = _interopRequireDefault(require("./util/string"));
|
|
var _pathAdjust = _interopRequireDefault(require("../graphics/pathAdjust"));
|
|
var _pathCeil = _interopRequireDefault(require("../graphics/pathCeil"));
|
|
var _computeBoundingBox = require("../graphics/computeBoundingBox");
|
|
var _compound2simpleglyf = _interopRequireDefault(require("./util/compound2simpleglyf"));
|
|
var _glyfAdjust = _interopRequireDefault(require("./util/glyfAdjust"));
|
|
var _optimizettf = _interopRequireDefault(require("./util/optimizettf"));
|
|
var _default = _interopRequireDefault(require("./data/default"));
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } /**
|
|
* @file ttf相关处理对象
|
|
* @author mengke01(kekee000@gmail.com)
|
|
*/
|
|
/**
|
|
* 缩放到EM框
|
|
*
|
|
* @param {Array} glyfList glyf列表
|
|
* @param {number} ascent 上升
|
|
* @param {number} descent 下降
|
|
* @param {number} adjustToEmPadding 顶部和底部留白
|
|
* @return {Array} glyfList
|
|
*/
|
|
function adjustToEmBox(glyfList, ascent, descent, adjustToEmPadding) {
|
|
glyfList.forEach(function (g) {
|
|
if (g.contours && g.contours.length) {
|
|
var rightSideBearing = g.advanceWidth - g.xMax;
|
|
var bound = _computeBoundingBox.computePath.apply(void 0, _toConsumableArray(g.contours));
|
|
var scale = (ascent - descent - adjustToEmPadding) / bound.height;
|
|
var center = (ascent + descent) / 2;
|
|
var yOffset = center - (bound.y + bound.height / 2) * scale;
|
|
g.contours.forEach(function (contour) {
|
|
if (scale !== 1) {
|
|
(0, _pathAdjust.default)(contour, scale, scale);
|
|
}
|
|
(0, _pathAdjust.default)(contour, 1, 1, 0, yOffset);
|
|
(0, _pathCeil.default)(contour);
|
|
});
|
|
var box = _computeBoundingBox.computePathBox.apply(void 0, _toConsumableArray(g.contours));
|
|
g.xMin = box.x;
|
|
g.xMax = box.x + box.width;
|
|
g.yMin = box.y;
|
|
g.yMax = box.y + box.height;
|
|
g.leftSideBearing = g.xMin;
|
|
g.advanceWidth = g.xMax + rightSideBearing;
|
|
}
|
|
});
|
|
return glyfList;
|
|
}
|
|
|
|
/**
|
|
* 调整字形位置
|
|
*
|
|
* @param {Array} glyfList 字形列表
|
|
* @param {number=} leftSideBearing 左边距
|
|
* @param {number=} rightSideBearing 右边距
|
|
* @param {number=} verticalAlign 垂直对齐
|
|
*
|
|
* @return {Array} 改变的列表
|
|
*/
|
|
function adjustPos(glyfList, leftSideBearing, rightSideBearing, verticalAlign) {
|
|
var changed = false;
|
|
|
|
// 左边轴
|
|
if (null != leftSideBearing) {
|
|
changed = true;
|
|
glyfList.forEach(function (g) {
|
|
if (g.leftSideBearing !== leftSideBearing) {
|
|
(0, _glyfAdjust.default)(g, 1, 1, leftSideBearing - g.leftSideBearing);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 右边轴
|
|
if (null != rightSideBearing) {
|
|
changed = true;
|
|
glyfList.forEach(function (g) {
|
|
g.advanceWidth = g.xMax + rightSideBearing;
|
|
});
|
|
}
|
|
|
|
// 基线高度
|
|
if (null != verticalAlign) {
|
|
changed = true;
|
|
glyfList.forEach(function (g) {
|
|
if (g.contours && g.contours.length) {
|
|
var bound = _computeBoundingBox.computePath.apply(void 0, _toConsumableArray(g.contours));
|
|
var offset = verticalAlign - bound.y;
|
|
(0, _glyfAdjust.default)(g, 1, 1, 0, offset);
|
|
}
|
|
});
|
|
}
|
|
return changed ? glyfList : [];
|
|
}
|
|
|
|
/**
|
|
* 合并两个ttfObject,此处仅合并简单字形
|
|
*
|
|
* @param {Object} ttf ttfObject
|
|
* @param {Object} imported ttfObject
|
|
* @param {Object} options 参数选项
|
|
* @param {boolean} options.scale 是否自动缩放,默认true
|
|
* @param {boolean} options.adjustGlyf 是否调整字形以适应边界
|
|
* (与 options.scale 互斥)
|
|
*
|
|
* @return {Object} 合并后的ttfObject
|
|
*/
|
|
function merge(ttf, imported) {
|
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
scale: true
|
|
};
|
|
var list = imported.glyf.filter(function (g) {
|
|
return (
|
|
// 简单轮廓
|
|
g.contours && g.contours.length
|
|
// 非预定义字形
|
|
&& g.name !== '.notdef' && g.name !== '.null' && g.name !== 'nonmarkingreturn'
|
|
);
|
|
});
|
|
|
|
// 调整字形以适应边界
|
|
if (options.adjustGlyf) {
|
|
var ascent = ttf.hhea.ascent;
|
|
var descent = ttf.hhea.descent;
|
|
var adjustToEmPadding = 16;
|
|
adjustPos(list, 16, 16);
|
|
adjustToEmBox(list, ascent, descent, adjustToEmPadding);
|
|
list.forEach(function (g) {
|
|
ttf.glyf.push(g);
|
|
});
|
|
}
|
|
// 根据unitsPerEm 进行缩放
|
|
else if (options.scale) {
|
|
var scale = 1;
|
|
|
|
// 调整glyf对导入的轮廓进行缩放处理
|
|
if (imported.head.unitsPerEm && imported.head.unitsPerEm !== ttf.head.unitsPerEm) {
|
|
scale = ttf.head.unitsPerEm / imported.head.unitsPerEm;
|
|
}
|
|
list.forEach(function (g) {
|
|
(0, _glyfAdjust.default)(g, scale, scale);
|
|
ttf.glyf.push(g);
|
|
});
|
|
}
|
|
return list;
|
|
}
|
|
var TTF = exports.default = /*#__PURE__*/function () {
|
|
/**
|
|
* ttf读取函数
|
|
*
|
|
* @constructor
|
|
* @param {Object} ttf ttf文件结构
|
|
*/
|
|
function TTF(ttf) {
|
|
_classCallCheck(this, TTF);
|
|
this.ttf = ttf;
|
|
}
|
|
|
|
/**
|
|
* 获取所有的字符信息
|
|
*
|
|
* @return {Object} 字符信息
|
|
*/
|
|
return _createClass(TTF, [{
|
|
key: "codes",
|
|
value: function codes() {
|
|
return Object.keys(this.ttf.cmap);
|
|
}
|
|
|
|
/**
|
|
* 根据编码获取字形索引
|
|
*
|
|
* @param {string} c 字符或者字符编码
|
|
*
|
|
* @return {?number} 返回glyf索引号
|
|
*/
|
|
}, {
|
|
key: "getGlyfIndexByCode",
|
|
value: function getGlyfIndexByCode(c) {
|
|
var charCode = typeof c === 'number' ? c : c.codePointAt(0);
|
|
var glyfIndex = this.ttf.cmap[charCode] || -1;
|
|
return glyfIndex;
|
|
}
|
|
|
|
/**
|
|
* 根据索引获取字形
|
|
*
|
|
* @param {number} glyfIndex glyf的索引
|
|
*
|
|
* @return {?Object} 返回glyf对象
|
|
*/
|
|
}, {
|
|
key: "getGlyfByIndex",
|
|
value: function getGlyfByIndex(glyfIndex) {
|
|
var glyfList = this.ttf.glyf;
|
|
var glyf = glyfList[glyfIndex];
|
|
return glyf;
|
|
}
|
|
|
|
/**
|
|
* 根据编码获取字形
|
|
*
|
|
* @param {string} c 字符或者字符编码
|
|
*
|
|
* @return {?Object} 返回glyf对象
|
|
*/
|
|
}, {
|
|
key: "getGlyfByCode",
|
|
value: function getGlyfByCode(c) {
|
|
var glyfIndex = this.getGlyfIndexByCode(c);
|
|
return this.getGlyfByIndex(glyfIndex);
|
|
}
|
|
|
|
/**
|
|
* 设置ttf对象
|
|
*
|
|
* @param {Object} ttf ttf对象
|
|
* @return {this}
|
|
*/
|
|
}, {
|
|
key: "set",
|
|
value: function set(ttf) {
|
|
this.ttf = ttf;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 获取ttf对象
|
|
*
|
|
* @return {ttfObject} ttf ttf对象
|
|
*/
|
|
}, {
|
|
key: "get",
|
|
value: function get() {
|
|
return this.ttf;
|
|
}
|
|
|
|
/**
|
|
* 添加glyf
|
|
*
|
|
* @param {Object} glyf glyf对象
|
|
*
|
|
* @return {number} 添加的glyf
|
|
*/
|
|
}, {
|
|
key: "addGlyf",
|
|
value: function addGlyf(glyf) {
|
|
return this.insertGlyf(glyf);
|
|
}
|
|
|
|
/**
|
|
* 插入glyf
|
|
*
|
|
* @param {Object} glyf glyf对象
|
|
* @param {Object} insertIndex 插入的索引
|
|
* @return {number} 添加的glyf
|
|
*/
|
|
}, {
|
|
key: "insertGlyf",
|
|
value: function insertGlyf(glyf, insertIndex) {
|
|
if (insertIndex >= 0 && insertIndex < this.ttf.glyf.length) {
|
|
this.ttf.glyf.splice(insertIndex, 0, glyf);
|
|
} else {
|
|
this.ttf.glyf.push(glyf);
|
|
}
|
|
return [glyf];
|
|
}
|
|
|
|
/**
|
|
* 合并两个ttfObject,此处仅合并简单字形
|
|
*
|
|
* @param {Object} imported ttfObject
|
|
* @param {Object} options 参数选项
|
|
* @param {boolean} options.scale 是否自动缩放
|
|
* @param {boolean} options.adjustGlyf 是否调整字形以适应边界
|
|
* (和 options.scale 参数互斥)
|
|
*
|
|
* @return {Array} 添加的glyf
|
|
*/
|
|
}, {
|
|
key: "mergeGlyf",
|
|
value: function mergeGlyf(imported, options) {
|
|
var list = merge(this.ttf, imported, options);
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* 删除指定字形
|
|
*
|
|
* @param {Array} indexList 索引列表
|
|
* @return {Array} 删除的glyf
|
|
*/
|
|
}, {
|
|
key: "removeGlyf",
|
|
value: function removeGlyf(indexList) {
|
|
var glyf = this.ttf.glyf;
|
|
var removed = [];
|
|
for (var i = glyf.length - 1; i >= 0; i--) {
|
|
if (indexList.indexOf(i) >= 0) {
|
|
removed.push(glyf[i]);
|
|
glyf.splice(i, 1);
|
|
}
|
|
}
|
|
return removed;
|
|
}
|
|
|
|
/**
|
|
* 设置unicode代码
|
|
*
|
|
* @param {string} unicode unicode代码 $E021, $22
|
|
* @param {Array=} indexList 索引列表
|
|
* @param {boolean} isGenerateName 是否生成name
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "setUnicode",
|
|
value: function setUnicode(unicode, indexList, isGenerateName) {
|
|
var glyf = this.ttf.glyf;
|
|
var list = [];
|
|
if (indexList && indexList.length) {
|
|
var first = indexList.indexOf(0);
|
|
if (first >= 0) {
|
|
indexList.splice(first, 1);
|
|
}
|
|
list = indexList.map(function (item) {
|
|
return glyf[item];
|
|
});
|
|
} else {
|
|
list = glyf.slice(1);
|
|
}
|
|
|
|
// 需要选出 unicode >32 的glyf
|
|
if (list.length > 1) {
|
|
var less32 = function less32(u) {
|
|
return u < 33;
|
|
};
|
|
list = list.filter(function (g) {
|
|
return !g.unicode || !g.unicode.some(less32);
|
|
});
|
|
}
|
|
if (list.length) {
|
|
unicode = Number('0x' + unicode.slice(1));
|
|
list.forEach(function (g) {
|
|
// 空格有可能会放入 nonmarkingreturn 因此不做编码
|
|
if (unicode === 0xA0 || unicode === 0x3000) {
|
|
unicode++;
|
|
}
|
|
g.unicode = [unicode];
|
|
if (isGenerateName) {
|
|
g.name = _string.default.getUnicodeName(unicode);
|
|
}
|
|
unicode++;
|
|
});
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* 生成字形名称
|
|
*
|
|
* @param {Array=} indexList 索引列表
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "genGlyfName",
|
|
value: function genGlyfName(indexList) {
|
|
var glyf = this.ttf.glyf;
|
|
var list = [];
|
|
if (indexList && indexList.length) {
|
|
list = indexList.map(function (item) {
|
|
return glyf[item];
|
|
});
|
|
} else {
|
|
list = glyf;
|
|
}
|
|
if (list.length) {
|
|
var first = this.ttf.glyf[0];
|
|
list.forEach(function (g) {
|
|
if (g === first) {
|
|
g.name = '.notdef';
|
|
} else if (g.unicode && g.unicode.length) {
|
|
g.name = _string.default.getUnicodeName(g.unicode[0]);
|
|
} else {
|
|
g.name = '.notdef';
|
|
}
|
|
});
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* 清除字形名称
|
|
*
|
|
* @param {Array=} indexList 索引列表
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "clearGlyfName",
|
|
value: function clearGlyfName(indexList) {
|
|
var glyf = this.ttf.glyf;
|
|
var list = [];
|
|
if (indexList && indexList.length) {
|
|
list = indexList.map(function (item) {
|
|
return glyf[item];
|
|
});
|
|
} else {
|
|
list = glyf;
|
|
}
|
|
if (list.length) {
|
|
list.forEach(function (g) {
|
|
delete g.name;
|
|
});
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* 添加并体替换指定的glyf
|
|
*
|
|
* @param {Array} glyfList 添加的列表
|
|
* @param {Array=} indexList 需要替换的索引列表
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "appendGlyf",
|
|
value: function appendGlyf(glyfList, indexList) {
|
|
var glyf = this.ttf.glyf;
|
|
var result = glyfList.slice(0);
|
|
if (indexList && indexList.length) {
|
|
var l = Math.min(glyfList.length, indexList.length);
|
|
for (var i = 0; i < l; i++) {
|
|
glyf[indexList[i]] = glyfList[i];
|
|
}
|
|
glyfList = glyfList.slice(l);
|
|
}
|
|
if (glyfList.length) {
|
|
Array.prototype.splice.apply(glyf, [glyf.length, 0].concat(_toConsumableArray(glyfList)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 调整glyf位置
|
|
*
|
|
* @param {Array=} indexList 索引列表
|
|
* @param {Object} setting 选项
|
|
* @param {number=} setting.leftSideBearing 左边距
|
|
* @param {number=} setting.rightSideBearing 右边距
|
|
* @param {number=} setting.verticalAlign 垂直对齐
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "adjustGlyfPos",
|
|
value: function adjustGlyfPos(indexList, setting) {
|
|
var glyfList = this.getGlyf(indexList);
|
|
return adjustPos(glyfList, setting.leftSideBearing, setting.rightSideBearing, setting.verticalAlign);
|
|
}
|
|
|
|
/**
|
|
* 调整glyf
|
|
*
|
|
* @param {Array=} indexList 索引列表
|
|
* @param {Object} setting 选项
|
|
* @param {boolean=} setting.reverse 字形反转操作
|
|
* @param {boolean=} setting.mirror 字形镜像操作
|
|
* @param {number=} setting.scale 字形缩放
|
|
* @param {boolean=} setting.adjustToEmBox 是否调整字形到 em 框
|
|
* @param {number=} setting.adjustToEmPadding 调整到 em 框的留白
|
|
* @return {boolean}
|
|
*/
|
|
}, {
|
|
key: "adjustGlyf",
|
|
value: function adjustGlyf(indexList, setting) {
|
|
var glyfList = this.getGlyf(indexList);
|
|
var changed = false;
|
|
setting.adjustToEmBox = setting.ajdustToEmBox || setting.adjustToEmBox;
|
|
setting.adjustToEmPadding = setting.ajdustToEmPadding || setting.adjustToEmPadding;
|
|
if (setting.reverse || setting.mirror) {
|
|
changed = true;
|
|
glyfList.forEach(function (g) {
|
|
if (g.contours && g.contours.length) {
|
|
var offsetX = g.xMax + g.xMin;
|
|
var offsetY = g.yMax + g.yMin;
|
|
g.contours.forEach(function (contour) {
|
|
(0, _pathAdjust.default)(contour, setting.mirror ? -1 : 1, setting.reverse ? -1 : 1);
|
|
(0, _pathAdjust.default)(contour, 1, 1, setting.mirror ? offsetX : 0, setting.reverse ? offsetY : 0);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
if (setting.scale && setting.scale !== 1) {
|
|
changed = true;
|
|
var scale = setting.scale;
|
|
glyfList.forEach(function (g) {
|
|
if (g.contours && g.contours.length) {
|
|
(0, _glyfAdjust.default)(g, scale, scale);
|
|
}
|
|
});
|
|
}
|
|
// 缩放到embox
|
|
else if (setting.adjustToEmBox) {
|
|
changed = true;
|
|
var ascent = this.ttf.hhea.ascent;
|
|
var descent = this.ttf.hhea.descent;
|
|
var adjustToEmPadding = 2 * (setting.adjustToEmPadding || 0);
|
|
adjustToEmBox(glyfList, ascent, descent, adjustToEmPadding);
|
|
}
|
|
return changed ? glyfList : [];
|
|
}
|
|
|
|
/**
|
|
* 获取glyf列表
|
|
*
|
|
* @param {Array=} indexList 索引列表
|
|
* @return {Array} glyflist
|
|
*/
|
|
}, {
|
|
key: "getGlyf",
|
|
value: function getGlyf(indexList) {
|
|
var glyf = this.ttf.glyf;
|
|
if (indexList && indexList.length) {
|
|
return indexList.map(function (item) {
|
|
return glyf[item];
|
|
});
|
|
}
|
|
return glyf;
|
|
}
|
|
|
|
/**
|
|
* 查找相关字形
|
|
*
|
|
* @param {Object} condition 查询条件
|
|
* @param {Array|number} condition.unicode unicode编码列表或者单个unicode编码
|
|
* @param {string} condition.name glyf名字,例如`uniE001`, `uniE`
|
|
* @param {Function} condition.filter 自定义过滤器
|
|
* @example
|
|
* condition.filter = function (glyf) {
|
|
* return glyf.name === 'logo';
|
|
* }
|
|
* @return {Array} glyf字形索引列表
|
|
*/
|
|
}, {
|
|
key: "findGlyf",
|
|
value: function findGlyf(condition) {
|
|
if (!condition) {
|
|
return [];
|
|
}
|
|
var filters = [];
|
|
|
|
// 按unicode数组查找
|
|
if (condition.unicode) {
|
|
var unicodeList = Array.isArray(condition.unicode) ? condition.unicode : [condition.unicode];
|
|
var unicodeHash = {};
|
|
unicodeList.forEach(function (unicode) {
|
|
if (typeof unicode === 'string') {
|
|
unicode = Number('0x' + unicode.slice(1));
|
|
}
|
|
unicodeHash[unicode] = true;
|
|
});
|
|
filters.push(function (glyf) {
|
|
if (!glyf.unicode || !glyf.unicode.length) {
|
|
return false;
|
|
}
|
|
for (var i = 0, l = glyf.unicode.length; i < l; i++) {
|
|
if (unicodeHash[glyf.unicode[i]]) {
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 按名字查找
|
|
if (condition.name) {
|
|
var name = condition.name;
|
|
filters.push(function (glyf) {
|
|
return glyf.name && glyf.name.indexOf(name) === 0;
|
|
});
|
|
}
|
|
|
|
// 按筛选函数查找
|
|
if (typeof condition.filter === 'function') {
|
|
filters.push(condition.filter);
|
|
}
|
|
var indexList = [];
|
|
this.ttf.glyf.forEach(function (glyf, index) {
|
|
for (var filterIndex = 0, filter; filter = filters[filterIndex++];) {
|
|
if (true === filter(glyf)) {
|
|
indexList.push(index);
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
return indexList;
|
|
}
|
|
|
|
/**
|
|
* 更新指定的glyf
|
|
*
|
|
* @param {Object} glyf glyfobject
|
|
* @param {string} index 需要替换的索引列表
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "replaceGlyf",
|
|
value: function replaceGlyf(glyf, index) {
|
|
if (index >= 0 && index < this.ttf.glyf.length) {
|
|
this.ttf.glyf[index] = glyf;
|
|
return [glyf];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* 设置glyf
|
|
*
|
|
* @param {Array} glyfList glyf列表
|
|
* @return {Array} 设置的glyf列表
|
|
*/
|
|
}, {
|
|
key: "setGlyf",
|
|
value: function setGlyf(glyfList) {
|
|
delete this.glyf;
|
|
this.ttf.glyf = glyfList || [];
|
|
return this.ttf.glyf;
|
|
}
|
|
|
|
/**
|
|
* 对字形按照unicode编码排序,此处不对复合字形进行排序,如果存在复合字形, 不进行排序
|
|
*
|
|
* @param {Array} glyfList glyf列表
|
|
* @return {Array} 设置的glyf列表
|
|
*/
|
|
}, {
|
|
key: "sortGlyf",
|
|
value: function sortGlyf() {
|
|
var glyf = this.ttf.glyf;
|
|
if (glyf.length > 1) {
|
|
// 如果存在复合字形则退出
|
|
if (glyf.some(function (a) {
|
|
return a.compound;
|
|
})) {
|
|
return -2;
|
|
}
|
|
var notdef = glyf.shift();
|
|
// 按代码点排序, 首先将空字形排到最后,然后按照unicode第一个编码进行排序
|
|
glyf.sort(function (a, b) {
|
|
if ((!a.unicode || !a.unicode.length) && (!b.unicode || !b.unicode.length)) {
|
|
return 0;
|
|
} else if ((!a.unicode || !a.unicode.length) && b.unicode) {
|
|
return 1;
|
|
} else if (a.unicode && (!b.unicode || !b.unicode.length)) {
|
|
return -1;
|
|
}
|
|
return Math.min.apply(null, a.unicode) - Math.min.apply(null, b.unicode);
|
|
});
|
|
glyf.unshift(notdef);
|
|
return glyf;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* 设置名字
|
|
*
|
|
* @param {string} name 名字字段
|
|
* @return {Object} 名字对象
|
|
*/
|
|
}, {
|
|
key: "setName",
|
|
value: function setName(name) {
|
|
if (name) {
|
|
this.ttf.name.fontFamily = this.ttf.name.fullName = name.fontFamily || _default.default.name.fontFamily;
|
|
this.ttf.name.fontSubFamily = name.fontSubFamily || _default.default.name.fontSubFamily;
|
|
this.ttf.name.uniqueSubFamily = name.uniqueSubFamily || '';
|
|
this.ttf.name.postScriptName = name.postScriptName || '';
|
|
}
|
|
return this.ttf.name;
|
|
}
|
|
|
|
/**
|
|
* 设置head信息
|
|
*
|
|
* @param {Object} head 头部信息
|
|
* @return {Object} 头对象
|
|
*/
|
|
}, {
|
|
key: "setHead",
|
|
value: function setHead(head) {
|
|
if (head) {
|
|
// unitsperem
|
|
if (head.unitsPerEm && head.unitsPerEm >= 64 && head.unitsPerEm <= 16384) {
|
|
this.ttf.head.unitsPerEm = head.unitsPerEm;
|
|
}
|
|
|
|
// lowestrecppem
|
|
if (head.lowestRecPPEM && head.lowestRecPPEM >= 8 && head.lowestRecPPEM <= 16384) {
|
|
this.ttf.head.lowestRecPPEM = head.lowestRecPPEM;
|
|
}
|
|
// created
|
|
if (head.created) {
|
|
this.ttf.head.created = head.created;
|
|
}
|
|
if (head.modified) {
|
|
this.ttf.head.modified = head.modified;
|
|
}
|
|
}
|
|
return this.ttf.head;
|
|
}
|
|
|
|
/**
|
|
* 设置hhea信息
|
|
*
|
|
* @param {Object} fields 字段值
|
|
* @return {Object} 头对象
|
|
*/
|
|
}, {
|
|
key: "setHhea",
|
|
value: function setHhea(fields) {
|
|
(0, _lang.overwrite)(this.ttf.hhea, fields, ['ascent', 'descent', 'lineGap']);
|
|
return this.ttf.hhea;
|
|
}
|
|
|
|
/**
|
|
* 设置OS2信息
|
|
*
|
|
* @param {Object} fields 字段值
|
|
* @return {Object} 头对象
|
|
*/
|
|
}, {
|
|
key: "setOS2",
|
|
value: function setOS2(fields) {
|
|
(0, _lang.overwrite)(this.ttf['OS/2'], fields, ['usWinAscent', 'usWinDescent', 'sTypoAscender', 'sTypoDescender', 'sTypoLineGap', 'sxHeight', 'bXHeight', 'usWeightClass', 'usWidthClass', 'yStrikeoutPosition', 'yStrikeoutSize', 'achVendID',
|
|
// panose
|
|
'bFamilyType', 'bSerifStyle', 'bWeight', 'bProportion', 'bContrast', 'bStrokeVariation', 'bArmStyle', 'bLetterform', 'bMidline', 'bXHeight']);
|
|
return this.ttf['OS/2'];
|
|
}
|
|
|
|
/**
|
|
* 设置post信息
|
|
*
|
|
* @param {Object} fields 字段值
|
|
* @return {Object} 头对象
|
|
*/
|
|
}, {
|
|
key: "setPost",
|
|
value: function setPost(fields) {
|
|
(0, _lang.overwrite)(this.ttf.post, fields, ['underlinePosition', 'underlineThickness']);
|
|
return this.ttf.post;
|
|
}
|
|
|
|
/**
|
|
* 计算度量信息
|
|
*
|
|
* @return {Object} 度量信息
|
|
*/
|
|
}, {
|
|
key: "calcMetrics",
|
|
value: function calcMetrics() {
|
|
var ascent = -16384;
|
|
var descent = 16384;
|
|
var uX = 0x78;
|
|
var uH = 0x48;
|
|
var sxHeight;
|
|
var sCapHeight;
|
|
this.ttf.glyf.forEach(function (g) {
|
|
if (g.yMax > ascent) {
|
|
ascent = g.yMax;
|
|
}
|
|
if (g.yMin < descent) {
|
|
descent = g.yMin;
|
|
}
|
|
if (g.unicode) {
|
|
if (g.unicode.indexOf(uX) >= 0) {
|
|
sxHeight = g.yMax;
|
|
}
|
|
if (g.unicode.indexOf(uH) >= 0) {
|
|
sCapHeight = g.yMax;
|
|
}
|
|
}
|
|
});
|
|
ascent = Math.round(ascent);
|
|
descent = Math.round(descent);
|
|
return {
|
|
// 此处非必须自动设置
|
|
ascent: ascent,
|
|
descent: descent,
|
|
sTypoAscender: ascent,
|
|
sTypoDescender: descent,
|
|
// 自动设置项目
|
|
usWinAscent: ascent,
|
|
usWinDescent: -descent,
|
|
sxHeight: sxHeight || 0,
|
|
sCapHeight: sCapHeight || 0
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 优化ttf字形信息
|
|
*
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "optimize",
|
|
value: function optimize() {
|
|
return (0, _optimizettf.default)(this.ttf);
|
|
}
|
|
|
|
/**
|
|
* 复合字形转简单字形
|
|
*
|
|
* @param {Array=} indexList 索引列表
|
|
* @return {Array} 改变的glyf
|
|
*/
|
|
}, {
|
|
key: "compound2simple",
|
|
value: function compound2simple(indexList) {
|
|
var ttf = this.ttf;
|
|
if (ttf.maxp && !ttf.maxp.maxComponentElements) {
|
|
return [];
|
|
}
|
|
var i;
|
|
var l;
|
|
// 全部的compound glyf
|
|
if (!indexList || !indexList.length) {
|
|
indexList = [];
|
|
for (i = 0, l = ttf.glyf.length; i < l; ++i) {
|
|
if (ttf.glyf[i].compound) {
|
|
indexList.push(i);
|
|
}
|
|
}
|
|
}
|
|
var list = [];
|
|
for (i = 0, l = indexList.length; i < l; ++i) {
|
|
var glyfIndex = indexList[i];
|
|
if (ttf.glyf[glyfIndex] && ttf.glyf[glyfIndex].compound) {
|
|
(0, _compound2simpleglyf.default)(glyfIndex, ttf, true);
|
|
list.push(ttf.glyf[glyfIndex]);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
}]);
|
|
}(); |