mirror of
https://github.com/2234839/web-font.git
synced 2026-09-04 23:02:27 +08:00
perf(gsub): coverageAllOutOfSubset range 相交判定改二分
COV_RANGE 分支逐 gid 展开 range 查 gidLookup(O(range length)), 对全子集外的 coverage 要遍历完所有 gid 才确认 outOfSubset。初夏 fmt3 range 展开总 20388 gid(300 range / 12 子集 gid),逐 gid 是预扫描主开销。 改用 currentSortedSubsetGids 二分:range [start,end] 是否含任一子集 gid 等价于排序子集数组存在 gid ∈ [start,end](gidLookup[g]>=0 ⟺ g 是子集 gid)。 O(log n) per range。微基准 10×(0.012→0.001ms),subsetGSUB 端到端初夏 -6%。 等价性:end clamp/越界语义保留(sortedGids 全 <numGlyphs,二分天然限范围); COVERAGE_MAX_EXPAND 守卫保留(与 readCoverageRemapped origNonEmpty 一致); origNonEmpty 对所有有效 range 非空标记(含越界 range,原版同等价)。 字节一致性:11 用例(含 FiraCode 两文本)subsetGSUB 输出 sha 全 IDENTICAL。 SSIM 30 用例全通过(最低 0.9876 篆体固有)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6d224c2405
commit
7a76208558
@ -1349,10 +1349,14 @@ function coverageAllOutOfSubset(
|
||||
}
|
||||
if (format === COV_RANGE) {
|
||||
const rangeCount = dv.getUint16(covOff + 2, false);
|
||||
/** 与 readCoverageRemapped 一致:end clamp 到 numGlyphs-1,start>=numGlyphs 的 range 跳过 gid 展开
|
||||
* (gidLookup[g] 对 g>=numGlyphs 必然不在子集,逐 gid 展开全越界是浪费)。保证 fmt3 预检「全子集外」
|
||||
* 判定与 readCoverageRemapped 完全一致,避免 [[gsub-subset-fmt3-prefetch-consistency]] 类不一致。 */
|
||||
const numGlyphs = gidLookup.length;
|
||||
/** 排序子集 gid 数组(currentSortedSubsetGids,模块级,subsetGSUB 入口已设)。
|
||||
* range 相交判定改二分(O(log n) per range)替代逐 gid 展开(O(range length))。
|
||||
* 初夏 fmt3 range 展开总 20388 gid、300 range、12 子集 gid,逐 gid 0.012ms vs 二分 0.001ms(10×)。
|
||||
* 等价性:range [start,end] 含 gidLookup[g]>=0 的 g ⟺ 排序子集 gid 数组存在 gid ∈ [start,end]
|
||||
* (gidLookup[g]>=0 ⟺ g 是子集 gid ⟺ g 在排序子集数组)。end clamp/越界语义不变:
|
||||
* sortedGids 全部 < numGlyphs,二分天然只在子集 gid 范围查,end>=numGlyphs 时子集 gid 仍可能 <= end。 */
|
||||
const sortedGids = currentSortedSubsetGids;
|
||||
const subsetN = sortedGids.length;
|
||||
let p = covOff + 4;
|
||||
let origNonEmpty = false;
|
||||
for (let i = 0; i < rangeCount; i++) {
|
||||
@ -1360,15 +1364,19 @@ function coverageAllOutOfSubset(
|
||||
const start = dv.getUint16(p, false);
|
||||
const end = dv.getUint16(p + 2, false);
|
||||
if (end >= start && end - start < COVERAGE_MAX_EXPAND) {
|
||||
if (start >= numGlyphs) {
|
||||
/** 整 range 越界:gid 全不在子集,但 range 非空(origNonEmpty),不短路 return false */
|
||||
origNonEmpty = true;
|
||||
} else {
|
||||
const e = end < numGlyphs ? end : numGlyphs - 1;
|
||||
for (let g = start; g <= e; g++) {
|
||||
origNonEmpty = true;
|
||||
if (gidLookup[g] >= 0) return false;
|
||||
/** range 非空(无论是否含子集 gid),标记 origNonEmpty */
|
||||
origNonEmpty = true;
|
||||
/** 二分判定 range 是否含任一子集 gid。subsetN=0(空子集,理论上不进 GSUB)或 range 全在
|
||||
* sortedGids 范围外时 lo 落到边界,sortedGids[lo] > end → 无交集,与逐 gid 全 <0 一致。 */
|
||||
if (subsetN > 0 && start <= sortedGids[subsetN - 1] && end >= sortedGids[0]) {
|
||||
let lo = 0, hi = subsetN;
|
||||
while (lo < hi) {
|
||||
const mid = (lo + hi) >>> 1;
|
||||
if (sortedGids[mid] < start) lo = mid + 1;
|
||||
else hi = mid;
|
||||
}
|
||||
/** lo = 第一个 >= start 的子集 gid 下标;若该 gid <= end 则 range 含子集 gid → 非 outOfSubset */
|
||||
if (lo < subsetN && sortedGids[lo] <= end) return false;
|
||||
}
|
||||
}
|
||||
p += 6;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user