UNPKG

fonteditor-core

Version:

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

138 lines (128 loc) 3.92 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = sizeof; /** * @file 获取cmap表的大小 * @author mengke01(kekee000@gmail.com) */ /** * 获取format4 delta值 * Delta is saved in signed int in cmap format 4 subtable, * but can be in -0xFFFF..0 interval. * -0x10000..-0x7FFF values are stored with offset. * * @param {number} delta delta值 * @return {number} delta值 */ function encodeDelta(delta) { return delta > 0x7FFF ? delta - 0x10000 : delta < -0x7FFF ? delta + 0x10000 : delta; } /** * 根据bound获取glyf segment * * @param {Array} glyfUnicodes glyf编码集合 * @param {number} bound 编码范围 * @return {Array} 码表 */ function getSegments(glyfUnicodes, bound) { var prevGlyph = null; var result = []; var segment = {}; glyfUnicodes.forEach(function (glyph) { if (bound === undefined || glyph.unicode <= bound) { // 初始化编码头部,这里unicode和graph id 都必须连续 if (prevGlyph === null || glyph.unicode !== prevGlyph.unicode + 1 || glyph.id !== prevGlyph.id + 1) { if (prevGlyph !== null) { segment.end = prevGlyph.unicode; result.push(segment); segment = { start: glyph.unicode, startId: glyph.id, delta: encodeDelta(glyph.id - glyph.unicode) }; } else { segment.start = glyph.unicode; segment.startId = glyph.id; segment.delta = encodeDelta(glyph.id - glyph.unicode); } } prevGlyph = glyph; } }); // need to finish the last segment if (prevGlyph !== null) { segment.end = prevGlyph.unicode; result.push(segment); } // 返回编码范围 return result; } /** * 获取format0编码集合 * * @param {Array} glyfUnicodes glyf编码集合 * @return {Array} 码表 */ function getFormat0Segment(glyfUnicodes) { var unicodes = []; glyfUnicodes.forEach(function (u) { if (u.unicode !== undefined && u.unicode < 256) { unicodes.push([u.unicode, u.id]); } }); // 按编码排序 unicodes.sort(function (a, b) { return a[0] - b[0]; }); return unicodes; } /** * 对cmap数据进行预处理,获取大小 * * @param {Object} ttf ttf对象 * @return {number} 大小 */ function sizeof(ttf) { ttf.support.cmap = {}; var glyfUnicodes = []; ttf.glyf.forEach(function (glyph, index) { var unicodes = glyph.unicode; if (typeof glyph.unicode === 'number') { unicodes = [glyph.unicode]; } if (unicodes && unicodes.length) { unicodes.forEach(function (unicode) { glyfUnicodes.push({ unicode: unicode, id: unicode !== 0xFFFF ? index : 0 }); }); } }); glyfUnicodes = glyfUnicodes.sort(function (a, b) { return a.unicode - b.unicode; }); ttf.support.cmap.unicodes = glyfUnicodes; var unicodes2Bytes = glyfUnicodes; ttf.support.cmap.format4Segments = getSegments(unicodes2Bytes, 0xFFFF); ttf.support.cmap.format4Size = 24 + ttf.support.cmap.format4Segments.length * 8; ttf.support.cmap.format0Segments = getFormat0Segment(glyfUnicodes); ttf.support.cmap.format0Size = 262; // we need subtable 12 only if found unicodes with > 2 bytes. var hasGLyphsOver2Bytes = unicodes2Bytes.some(function (glyph) { return glyph.unicode > 0xFFFF; }); if (hasGLyphsOver2Bytes) { ttf.support.cmap.hasGLyphsOver2Bytes = hasGLyphsOver2Bytes; var unicodes4Bytes = glyfUnicodes; ttf.support.cmap.format12Segments = getSegments(unicodes4Bytes); ttf.support.cmap.format12Size = 16 + ttf.support.cmap.format12Segments.length * 12; } var size = 4 + (hasGLyphsOver2Bytes ? 32 : 24) // cmap header + ttf.support.cmap.format0Size // format 0 + ttf.support.cmap.format4Size // format 4 + (hasGLyphsOver2Bytes ? ttf.support.cmap.format12Size : 0); // format 12 return size; }