perf(gsub): subtable 偏移槽 writeUint16 占位回填替代 reserveOffset16 闭包

subsetGSUB 的 serialize 循环里,每个 lookup 的 subtable 偏移槽原先用
reserveOffset16(per-slot 闭包 + patch push)。思源 GSUB 56 lookup × 323
subtable,分配 323 次闭包。

移植 subsetGPOS 的优化329:writeUint16(0) 占位 + 记录 subtableSlotsStart,
序列化后统一 writeInt16At(subtableSlotsStart+j*2, pos-lookupStart) 回填。
rollback 失败回退后 pos=before(两种路径 subtable 起点一致)。

收益:思源 subsetGSUB 0.2145→0.2021ms (-5.8%),FiraCode 持平(387→378μs 噪声内)。
输出字节完全一致(otf-思源 19188/10664 等),所有字体 SSIM 不变。

与 subsetGPOS 的优化329 同构,统一两处 serialize 实现。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-07-25 01:35:50 +08:00
parent 2834c4d4ab
commit 58fc647880

View File

@ -1443,9 +1443,14 @@ export function subsetGSUB(
w.writeUint16(lk.subtableAbsOffs.length);
const lookupStart = w.length - 6;
const subtableAbsPositions: number[] = new Array(lk.subtableAbsOffs.length);
/**
* 329 subsetGPOS subtable writeUint16(0) + slot
* writeInt16At reserveOffset16 per-slot + patch push
* GSUB 56 lookup × 323 subtable 323
*/
const subtableSlotsStart = w.length;
for (let j = 0; j < lk.subtableAbsOffs.length; j++) {
const slotIdx = j;
w.reserveOffset16(lookupStart, () => subtableAbsPositions[slotIdx]);
w.writeUint16(0);
}
if (useMarkFilteringSet) {
w.writeUint16(r.u16(lk.origLookupOff + 6 + lk.subtableAbsOffs.length * 2));
@ -1457,10 +1462,10 @@ export function subsetGSUB(
for (let j = 0; j < lk.subtableAbsOffs.length; j++) {
subtableAbsPositions[j] = w.length;
writeEmptySubtable(w, lk.effectiveType);
w.writeInt16At(subtableSlotsStart + j * 2, subtableAbsPositions[j] - lookupStart);
}
} else {
for (let j = 0; j < lk.subtableAbsOffs.length; j++) {
subtableAbsPositions[j] = w.length;
/** 单个 subtable 重映射失败coverage gid 全不在子集 /
* 退 subtable coverage
* copyBytesBlock subtable lookup
@ -1471,6 +1476,9 @@ export function subsetGSUB(
w.rollback(before);
writeEmptySubtable(w, lk.effectiveType);
}
/** 记录实际 subtable 起点(成功=before失败回退后=before 同值)并回填偏移槽 */
subtableAbsPositions[j] = before;
w.writeInt16At(subtableSlotsStart + j * 2, before - lookupStart);
}
}
} else {