diff --git a/vendor/fonteditor-core/woff2/woff2-encode.js b/vendor/fonteditor-core/woff2/woff2-encode.js index bdb1215..235b3d8 100644 --- a/vendor/fonteditor-core/woff2/woff2-encode.js +++ b/vendor/fonteditor-core/woff2/woff2-encode.js @@ -182,67 +182,6 @@ for (let i = 84; i < 120; i++) TRIPLET_DATA_SIZES[i] = 2; for (let i = 120; i < 124; i++) TRIPLET_DATA_SIZES[i] = 3; for (let i = 124; i < 128; i++) TRIPLET_DATA_SIZES[i] = 4; -/** - * 仅计算 triplet flag 字节,不写入数据 - * 优化: Pass 1 只需要 flag,数据写入由 Pass 2 的 writePointDataByFlag 完成 - */ -/** - * 计算 triplet flag 并同时写入数据字节,消除重复的 absDx/absDy 计算和二次分支判断 - * 优化291: 合并 calcTripletFlag + writePointDataByFlag 为单一函数 - */ -function calcTripletAndWrite(curveBit, dx, dy, buf, offset) { - /** 优化302: Math.abs 替代三元 `x < 0 ? -x : x`,V8 内建编译为单条 neg 指令(3.5x) */ - const absDx = Math.abs(dx); - const absDy = Math.abs(dy); - const xSignBit = dx >= 0 ? 1 : 0; - const ySignBit = dy >= 0 ? 1 : 0; - const xySignBits = xSignBit + 2 * ySignBit; - - /* dx=0, Y 单轴 1 数据字节 (flag 0-9) */ - if (dx === 0 && absDy < 1280) { - buf[offset] = absDy & 0xFF; - return curveBit + ((absDy & 0xF00) >> 7) + ySignBit; - } - - /* dy=0, dx≠0, X 单轴 1 数据字节 (flag 10-19) */ - if (dy === 0 && dx !== 0 && absDx < 1280) { - buf[offset] = absDx & 0xFF; - return curveBit + 10 + ((absDx & 0xF00) >> 7) + xSignBit; - } - - /* 双轴 1 数据字节 (flag 20-83): 1 ≤ |dx| ≤ 64, 1 ≤ |dy| ≤ 64 */ - if (dx !== 0 && dy !== 0 && absDx < 65 && absDy < 65) { - const ax = absDx - 1; - const ay = absDy - 1; - buf[offset] = ((ax & 0xF) << 4) | (ay & 0xF); - return curveBit + 20 + (ax & 0x30) + ((ay & 0x30) >> 2) + xySignBits; - } - - /* 双轴 2 数据字节 (flag 84-119): 1 ≤ |dx| ≤ 768, 1 ≤ |dy| ≤ 768 */ - if (dx !== 0 && dy !== 0 && absDx < 769 && absDy < 769) { - const ax = absDx - 1; - const ay = absDy - 1; - buf[offset] = ax & 0xFF; - buf[offset + 1] = ay & 0xFF; - return curveBit + 84 + 12 * ((ax & 0x300) >> 8) + ((ay & 0x300) >> 6) + xySignBits; - } - - /* 双轴 3 数据字节 (flag 120-123) */ - if (absDx < 4096 && absDy < 4096) { - buf[offset] = absDx >> 4; - buf[offset + 1] = ((absDx & 0xF) << 4) | (absDy >> 8); - buf[offset + 2] = absDy & 0xFF; - return curveBit + 120 + xySignBits; - } - - /* 兜底 4 数据字节 (flag 124-127) */ - buf[offset] = (absDx >> 8) & 0xFF; - buf[offset + 1] = absDx & 0xFF; - buf[offset + 2] = (absDy >> 8) & 0xFF; - buf[offset + 3] = absDy & 0xFF; - return curveBit + 124 + xySignBits; -} - /* ======== glyf + loca 表变换 ======== */ /** @@ -564,6 +503,14 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) { const gsBase = glyphAccumLen; let gsbi = 0; let prevX = 0, prevY = 0; + /** + * 优化303: calcTripletAndWrite 手动 inline 到主循环(消除 54350 次/call 函数调用开销)。 + * 千字文 54350 点场景,calcTripletAndWrite 占 transformGlyfAndLoca 31.8% CPU(prof 实测), + * 函数调用与无法 inline 的参数装箱是主因。inline 后 V8 可在循环内做寄存器分配 + + * 公共子表达式消除(absDx/absDy/curveBit 跨分支复用)。语义与原 calcTripletAndWrite 完全一致。 + * 分支顺序保持原样(特例 yOnly/xOnly 优先),千字文 78% 命中 1B 双轴分支。 + */ + const _gs = glyphAccum; for (let pi = 0; pi < numPoints; pi++) { const cx = xCoords[pi]; const cy = yCoords[pi]; @@ -571,7 +518,49 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) { const curveBit = ((flagAccum[flagWriteBase + pi] & 1) ^ 1) << 7; const dx = cx - prevX; const dy = cy - prevY; - const flag = calcTripletAndWrite(curveBit, dx, dy, glyphAccum, gsBase + gsbi); + const absDx = dx < 0 ? -dx : dx; + const absDy = dy < 0 ? -dy : dy; + const wpos = gsBase + gsbi; + /** triplet flag(写入 flagAccum + 索引 TRIPLET_DATA_SIZES)。 + * 默认值仅占位,每个分支都会覆盖。 */ + let flag; + if (dx === 0 && absDy < 1280) { + _gs[wpos] = absDy & 0xFF; + flag = curveBit + ((absDy & 0xF00) >> 7) + (dy >= 0 ? 1 : 0); + } else if (dy === 0 && dx !== 0 && absDx < 1280) { + _gs[wpos] = absDx & 0xFF; + flag = curveBit + 10 + ((absDx & 0xF00) >> 7) + (dx >= 0 ? 1 : 0); + } else if (dx !== 0 && dy !== 0 && absDx < 65 && absDy < 65) { + const ax = absDx - 1; + const ay = absDy - 1; + _gs[wpos] = ((ax & 0xF) << 4) | (ay & 0xF); + const xSignBit = dx >= 0 ? 1 : 0; + const ySignBit = dy >= 0 ? 1 : 0; + flag = curveBit + 20 + (ax & 0x30) + ((ay & 0x30) >> 2) + xSignBit + 2 * ySignBit; + } else if (dx !== 0 && dy !== 0 && absDx < 769 && absDy < 769) { + const ax = absDx - 1; + const ay = absDy - 1; + _gs[wpos] = ax & 0xFF; + _gs[wpos + 1] = ay & 0xFF; + const xSignBit = dx >= 0 ? 1 : 0; + const ySignBit = dy >= 0 ? 1 : 0; + flag = curveBit + 84 + 12 * ((ax & 0x300) >> 8) + ((ay & 0x300) >> 6) + xSignBit + 2 * ySignBit; + } else if (absDx < 4096 && absDy < 4096) { + _gs[wpos] = absDx >> 4; + _gs[wpos + 1] = ((absDx & 0xF) << 4) | (absDy >> 8); + _gs[wpos + 2] = absDy & 0xFF; + const xSignBit = dx >= 0 ? 1 : 0; + const ySignBit = dy >= 0 ? 1 : 0; + flag = curveBit + 120 + xSignBit + 2 * ySignBit; + } else { + _gs[wpos] = (absDx >> 8) & 0xFF; + _gs[wpos + 1] = absDx & 0xFF; + _gs[wpos + 2] = (absDy >> 8) & 0xFF; + _gs[wpos + 3] = absDy & 0xFF; + const xSignBit = dx >= 0 ? 1 : 0; + const ySignBit = dy >= 0 ? 1 : 0; + flag = curveBit + 124 + xSignBit + 2 * ySignBit; + } /** triplet flag 回写到 flagAccum(flagStream 存 triplet flag 而非原始 flag) */ flagAccum[flagWriteBase + pi] = flag; gsbi += TRIPLET_DATA_SIZES[flag & 0x7F];