UNPKG

fonteditor-core

Version:

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

154 lines (125 loc) 4.21 kB
/** * @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) { let prevGlyph = null; const result = []; let segment = {}; glyfUnicodes.forEach((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) { const unicodes = []; glyfUnicodes.forEach((u) => { if (u.unicode !== undefined && u.unicode < 256) { unicodes.push([u.unicode, u.id]); } }); // 按编码排序 unicodes.sort((a, b) => a[0] - b[0]); return unicodes; } /** * 对cmap数据进行预处理,获取大小 * * @param {Object} ttf ttf对象 * @return {number} 大小 */ export default function sizeof(ttf) { ttf.support.cmap = {}; let glyfUnicodes = []; ttf.glyf.forEach((glyph, index) => { let unicodes = glyph.unicode; if (typeof glyph.unicode === 'number') { unicodes = [glyph.unicode]; } if (unicodes && unicodes.length) { unicodes.forEach((unicode) => { glyfUnicodes.push({ unicode, id: unicode !== 0xFFFF ? index : 0 }); }); } }); glyfUnicodes = glyfUnicodes.sort((a, b) => a.unicode - b.unicode); ttf.support.cmap.unicodes = glyfUnicodes; const 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. const hasGLyphsOver2Bytes = unicodes2Bytes.some((glyph) => glyph.unicode > 0xFFFF); if (hasGLyphsOver2Bytes) { ttf.support.cmap.hasGLyphsOver2Bytes = hasGLyphsOver2Bytes; const unicodes4Bytes = glyfUnicodes; ttf.support.cmap.format12Segments = getSegments(unicodes4Bytes); ttf.support.cmap.format12Size = 16 + ttf.support.cmap.format12Segments.length * 12; } const 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; }