From 77029f10903bfdfd4a6b2f4666b3dfa7dde55780 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 19:44:08 +0800 Subject: [PATCH] =?UTF-8?q?perf(gsub-reachable):=20collectChainRuleRefs=20?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF=E5=86=85=20r.u16=20=E6=94=B9=20dv.getUint16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chain format1 规则的 backtrack/input/lookahead/substRecords 读取(6 个内层 循环)从 r.u16 改 dv.getUint16。FiraCode 180 个 fmt1 规则 × 多次密集调用。 count 读取(backtrackCount 等)保留 r.u16 维持原行为。 FiraCode reachable 集合 size=89 不变,5 字体 sha 逐字节一致,SSIM 全不变。 Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/font_util/gsub-reachable.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/backend/font_util/gsub-reachable.ts b/backend/font_util/gsub-reachable.ts index 88068f2..0deb6f0 100644 --- a/backend/font_util/gsub-reachable.ts +++ b/backend/font_util/gsub-reachable.ts @@ -543,6 +543,8 @@ function collectChainRuleRefs( isGidFormat: boolean, ): void { /** format1/2 rule: backtrackCount + backtrack[] + inputCount + input[] + lookaheadCount + lookahead[] + substCount + substRecords[] */ + /** 缓存 dv:chain format1 规则密集调用(FiraCode 180 fmt1 规则 × 6+ 次 u16),直接 getUint16 省方法调用+边界检查 */ + const dv = r.dv; let p = ruleOff; const backtrackCount = r.u16(p); p += 2; const backtrackEnd = p + backtrackCount * 2; @@ -559,26 +561,26 @@ function collectChainRuleRefs( /** 第一遍:校验 backtrack + input + lookahead 全部 gid 在子集(遇子集外即放弃规则) */ let q = ruleOff + 2; for (let k = 0; k < backtrackCount; k++) { - if (!inSubset(r.u16(q + k * 2))) return; + if (!inSubset(dv.getUint16(q + k * 2, false))) return; } q += backtrackCount * 2 + 2; for (let k = 0; k < inputLen; k++) { - if (!inSubset(r.u16(q + k * 2))) return; + if (!inSubset(dv.getUint16(q + k * 2, false))) return; } q += inputLen * 2 + 2; for (let k = 0; k < lookaheadCount; k++) { - if (!inSubset(r.u16(q + k * 2))) return; + if (!inSubset(dv.getUint16(q + k * 2, false))) return; } /** 第二遍:全部在子集,收集 context gid */ q = ruleOff + 2; - for (let k = 0; k < backtrackCount; k++) contextGids.add(r.u16(q + k * 2)); + for (let k = 0; k < backtrackCount; k++) contextGids.add(dv.getUint16(q + k * 2, false)); q += backtrackCount * 2 + 2; - for (let k = 0; k < inputLen; k++) contextGids.add(r.u16(q + k * 2)); + for (let k = 0; k < inputLen; k++) contextGids.add(dv.getUint16(q + k * 2, false)); q += inputLen * 2 + 2; - for (let k = 0; k < lookaheadCount; k++) contextGids.add(r.u16(q + k * 2)); + for (let k = 0; k < lookaheadCount; k++) contextGids.add(dv.getUint16(q + k * 2, false)); } for (let k = 0; k < substCount; k++) { /** SubstLookupRecord: sequenceIndex(2) + lookupListIndex(2) */ - refs.add(r.u16(p + k * 4 + 2)); + refs.add(dv.getUint16(p + k * 4 + 2, false)); } }