perf(otf): assembleSfnt wholeSum 复用各表 checksum,消除全文件二次遍历

head.checkSumAdjustment 原先两遍遍历 ~750KB 输出:
1. calcTableChecksum 对每表(CFF 742KB 最大)算 checksum
2. wholeSum 再次遍历整个 out 文件 4 字节步进算全文件 sum

数学等价:全文件 sum = 目录区 sum + Σ 各表数据段 checksum,
而各表数据段 padded sum 正是写表记录时已算的 calcTableChecksum。
故 wholeSum 改为「dirSize(156B) 目录区 sum + 累加的 tablesDataSum」,
消除数百 KB 大表的第二次整段遍历。

思源 otf 8字 subsetOTF:min 1.836→1.321ms(-28%)、p50 2.433→1.720ms(-29%);
字节级零回归(cmp 优化前后输出逐字节一致,含 checkSumAdjustment);
基准测试全字体 SSIM 与优化前完全一致。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-07-24 23:12:05 +08:00
parent e37593a552
commit 98b56b4f35

View File

@ -404,9 +404,11 @@ function assembleSfnt(tables: { tag: string; bytes: Uint8Array }[]): Uint8Array
dv.setUint16(8, entrySelector, false);
dv.setUint16(10, rangeShift, false);
/** 表记录 + 数据 */
/** 表记录 + 数据;各表 checksum 同时累加进 wholeSum数据段 sum 等于表 checksum */
let dataOff = dirSize;
const headIdx = tables.findIndex((t) => t.tag === "head");
/** wholeSum = Σ 各表数据段 checksum。head.checkSumAdjustment 此刻为 0passthroughHead 已清零),目录区稍后补算 */
let tablesDataSum = 0;
for (let i = 0; i < numTables; i++) {
const r = 12 + i * 16;
out[r] = tables[i].tag.charCodeAt(0);
@ -414,6 +416,7 @@ function assembleSfnt(tables: { tag: string; bytes: Uint8Array }[]): Uint8Array
out[r + 2] = tables[i].tag.charCodeAt(2);
out[r + 3] = tables[i].tag.charCodeAt(3);
const checksum = calcTableChecksum(tables[i].bytes);
tablesDataSum = (tablesDataSum + checksum) >>> 0;
dv.setUint32(r + 4, checksum, false);
dv.setUint32(r + 8, dataOff, false);
dv.setUint32(r + 12, tables[i].bytes.length, false);
@ -421,20 +424,18 @@ function assembleSfnt(tables: { tag: string; bytes: Uint8Array }[]): Uint8Array
dataOff += paddedLens[i];
}
/** head.checkSumAdjustment = 0xB1B0AFBA - 全文件 sum */
/** head.checkSumAdjustment = 0xB1B0AFBA - sum
* sum = sum + Σ checksum
* sum = checksum dirSize sfnt +
* KB CFF */
if (headIdx >= 0) {
const headRecOff = 12 + headIdx * 16;
const headDataOff = dv.getUint32(headRecOff + 8, false);
/** 先算全文件 checksumhead.checkSumAdjustment 此时为 0 */
let wholeSum = 0;
const wholePadded = (out.length + 3) & ~3;
for (let i = 0; i < wholePadded; i += 4) {
const b0 = out[i] || 0;
const b1 = out[i + 1] || 0;
const b2 = out[i + 2] || 0;
const b3 = out[i + 3] || 0;
wholeSum = (wholeSum + ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)) >>> 0;
let dirSum = 0;
for (let i = 0; i < dirSize; i += 4) {
dirSum = (dirSum + ((out[i] << 24) | (out[i + 1] << 16) | (out[i + 2] << 8) | out[i + 3])) >>> 0;
}
const wholeSum = (dirSum + tablesDataSum) >>> 0;
const adjustment = (0xb1b0afba - wholeSum) >>> 0;
dv.setUint32(headDataOff + 8, adjustment, false);
}