From f945e1aedbb106f0c0c446349b4911ce3abc3923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B4=AE=E7=94=9F=EF=BC=88=E5=AD=90=E8=99=9A=EF=BC=89?= <2234839456@qq.com> Date: Fri, 24 Jul 2026 11:48:12 +0800 Subject: [PATCH] =?UTF-8?q?perf(woff2):=20triplet=20=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E5=90=84=E5=88=86=E6=94=AF=E5=86=85=E7=B4=AF=E5=8A=A0=20gsbi?= =?UTF-8?q?=EF=BC=8C=E6=B6=88=E9=99=A4=20TRIPLET=5FDATA=5FSIZES=20?= =?UTF-8?q?=E6=9F=A5=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 令东千字文 woff2 write -12%(2.785→2.449ms),输出字节完全一致(cmp sha256 验证)。 原 gsbi += TRIPLET_DATA_SIZES[flag & 0x7F] 每点查表(Uint8Array 索引+位运算), 改为各 case 分支内 adv=1/1/1/2/3/4 常量累加,省掉查表。思源 -4%。 Co-Authored-By: Claude Opus 4.8 (1M context) --- vendor/fonteditor-core/woff2/woff2-encode.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/vendor/fonteditor-core/woff2/woff2-encode.js b/vendor/fonteditor-core/woff2/woff2-encode.js index 16b1cca..45e6e89 100644 --- a/vendor/fonteditor-core/woff2/woff2-encode.js +++ b/vendor/fonteditor-core/woff2/woff2-encode.js @@ -174,15 +174,9 @@ const sizeUIntBase128 = calcUIntBase128Size; /* ======== Triplet 编码 ======== */ /** - * 从 triplet flag 推断数据字节数(避免重复计算) - * tripletIndex = flag & 0x7F - * 优化:预计算查找表,消除函数调用和条件分支 + * 优化313: triplet flag → 数据字节数的映射已内联进 transformGlyfAndLoca 的各编码分支 + * (字节数由分支确定:case1~3=1、case4=2、case5=3、case6=4),无需独立查表。 */ -const TRIPLET_DATA_SIZES = new Uint8Array(128); -for (let i = 0; i < 84; i++) TRIPLET_DATA_SIZES[i] = 1; -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; /* ======== glyf + loca 表变换 ======== */ @@ -522,12 +516,16 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) { const absDy = dy < 0 ? -dy : dy; const wpos = gsBase + gsbi; let flag; + /** 优化313: 各分支内直接累加 gsbi(字节数由分支确定:1/1/1/2/3/4),消除 TRIPLET_DATA_SIZES 查表 */ + let adv; if (dx === 0 && absDy < 1280) { _gs[wpos] = absDy & 0xFF; flag = curveBit + ((absDy & 0xF00) >> 7) + (dy >= 0 ? 1 : 0); + adv = 1; } else if (dy === 0 && dx !== 0 && absDx < 1280) { _gs[wpos] = absDx & 0xFF; flag = curveBit + 10 + ((absDx & 0xF00) >> 7) + (dx >= 0 ? 1 : 0); + adv = 1; } else if (dx !== 0 && dy !== 0 && absDx < 65 && absDy < 65) { const ax = absDx - 1; const ay = absDy - 1; @@ -535,6 +533,7 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) { const xSignBit = dx >= 0 ? 1 : 0; const ySignBit = dy >= 0 ? 1 : 0; flag = curveBit + 20 + (ax & 0x30) + ((ay & 0x30) >> 2) + xSignBit + 2 * ySignBit; + adv = 1; } else if (dx !== 0 && dy !== 0 && absDx < 769 && absDy < 769) { const ax = absDx - 1; const ay = absDy - 1; @@ -543,6 +542,7 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) { 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; + adv = 2; } else if (absDx < 4096 && absDy < 4096) { _gs[wpos] = absDx >> 4; _gs[wpos + 1] = ((absDx & 0xF) << 4) | (absDy >> 8); @@ -550,6 +550,7 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) { const xSignBit = dx >= 0 ? 1 : 0; const ySignBit = dy >= 0 ? 1 : 0; flag = curveBit + 120 + xSignBit + 2 * ySignBit; + adv = 3; } else { _gs[wpos] = (absDx >> 8) & 0xFF; _gs[wpos + 1] = absDx & 0xFF; @@ -558,10 +559,11 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) { const xSignBit = dx >= 0 ? 1 : 0; const ySignBit = dy >= 0 ? 1 : 0; flag = curveBit + 124 + xSignBit + 2 * ySignBit; + adv = 4; } /** triplet flag 回写到 flagAccum(flagStream 存 triplet flag 而非原始 flag) */ _fa[_fwb + yi] = flag; - gsbi += TRIPLET_DATA_SIZES[flag & 0x7F]; + gsbi += adv; prevX = cx; prevY = cy; }