perf(gsub): fmt3 预检改用 coverageAllOutOfSubset 内联快判,跳过 readCoverageRemapped

isSubtableSkipableByCoverage 的 ChainContext format3 分支原对每个 coverage 调
readCoverageRemapped(判全子集外)——它 new Array+sort+Map.set 填 covCache,但思源
fmt3 预检 281 个 coverage 全子集外且 avg 仅 1.3 gid:数组分配/sort/cache 操作是纯固定开销,
且这些 skipable coverage 的 cache entry 永不被命中(skipable subtable 不深度解析)。

改用 coverageAllOutOfSubset 内联遍历字节判「全子集外」(不分配数组、不读写 covCache),
预检只判 skipable 不再填 cache;非 skipable subtable 深度解析时 readCoverageRemapped
自行首次填 cache(命中率不变,无双重遍历)。同时从 isSubtableSkipableByCoverage 移除
不再使用的 covCache 参数。

一致性([[gsub-subset-fmt3-prefetch-consistency]]):对齐 coverageAllOutOfSubset 的
COV_RANGE 分支与 readCoverageRemapped——end clamp 到 numGlyphs-1、start>=numGlyphs
的越界 range 计 origNonEmpty 不展开 gid。两者「全子集外」判定完全等价,故预检 skipable
⟺ 深度解析 coverage 失效,输出逐字节一致。

A/B:6 字体 × ttf/woff2 共 12 产物逐字节 IDENTICAL(含 FiraCode calt)。
性能(best-of-min,两轮一致):otf-思源 -12%、思源ttf -6%、FiraCode -2%、初夏 -3%。
基准测试全通过,SSIM 维持。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-07-25 03:32:15 +08:00
parent 49337c72bc
commit 1bc87763ad

View File

@ -1171,7 +1171,6 @@ function isSubtableSkipableByCoverage(
off: number,
type: number,
gidLookup: GidLookup,
covCache: CoverageCache,
): boolean {
const dv = r.dv;
const len = dv.byteLength;
@ -1202,7 +1201,15 @@ function isSubtableSkipableByCoverage(
for (let k = 0; k < cnt; k++) {
if (p + 2 > len) return false;
const covOff = off + dv.getUint16(p + k * 2, false);
if (readCoverageRemapped(r, covOff, gidLookup, covCache) === null) return true;
/** coverageAllOutOfSubset covCache
* fmt3 281 coverage avg 1.3 gidreadCoverageRemapped
* new Array+sort+Map.set skipable coverage cache entry
* skipable subtable skipable cache
* skipable subtable readCoverageRemapped cache
* [[gsub-subset-fmt3-prefetch-consistency]]coverageAllOutOfSubset
* readCoverageRemapped COV_RANGE clamp numGlyphs range origNonEmpty
* skipable coverage */
if (coverageAllOutOfSubset(dv, covOff, len, gidLookup)) return true;
}
p += cnt * 2;
}
@ -1246,6 +1253,10 @@ function coverageAllOutOfSubset(
}
if (format === COV_RANGE) {
const rangeCount = dv.getUint16(covOff + 2, false);
/** readCoverageRemapped end clamp numGlyphs-1start>=numGlyphs range gid
* gidLookup[g] g>=numGlyphs gid fmt3
* readCoverageRemapped [[gsub-subset-fmt3-prefetch-consistency]] */
const numGlyphs = gidLookup.length;
let p = covOff + 4;
let origNonEmpty = false;
for (let i = 0; i < rangeCount; i++) {
@ -1253,9 +1264,15 @@ function coverageAllOutOfSubset(
const start = dv.getUint16(p, false);
const end = dv.getUint16(p + 2, false);
if (end >= start && end - start < COVERAGE_MAX_EXPAND) {
for (let g = start; g <= end; g++) {
if (start >= numGlyphs) {
/** 整 range 越界gid 全不在子集,但 range 非空origNonEmpty不短路 return false */
origNonEmpty = true;
if (gidLookup[g] >= 0) return false;
} else {
const e = end < numGlyphs ? end : numGlyphs - 1;
for (let g = start; g <= e; g++) {
origNonEmpty = true;
if (gidLookup[g] >= 0) return false;
}
}
}
p += 6;
@ -1283,7 +1300,7 @@ function serializeSubtable(
* FiraCode 403 lookup ~330 type1-4 + fmt1 + fmt3
* format2 class coverage
* */
if (preCheckedSkipable !== undefined ? preCheckedSkipable : isSubtableSkipableByCoverage(r, off, type, gidLookup, covCache)) return false;
if (preCheckedSkipable !== undefined ? preCheckedSkipable : isSubtableSkipableByCoverage(r, off, type, gidLookup)) return false;
let ok: boolean;
switch (type) {
case LT_SINGLE:
@ -1430,7 +1447,7 @@ export function subsetGSUB(
const skipable = new Array<boolean>(subs.length);
let allEmpty = subs.length > 0;
for (let j = 0; j < subs.length; j++) {
const sk = isSubtableSkipableByCoverage(r, subs[j], lk.effectiveType, gidLookup, covCache);
const sk = isSubtableSkipableByCoverage(r, subs[j], lk.effectiveType, gidLookup);
skipable[j] = sk;
if (!sk) allEmpty = false;
}