perf(ot-writer): 主 Writer 按原表大小预分配容量消除 grow 全拷贝

OTWriter 加可选 initialCapacity 构造参数(默认 2048)。subsetGPOS/subsetGSUB
主 Writer 按原表 byteLength 预分配,避免大表多次 2× 扩容的全拷贝。
初夏纯标点 GPOS 单次 fontSubset 原 5 次 grow(cap 2048→4096→8192→16384),
改后 5 字体(初夏/FiraCode/令东千字文/思源/霞鹜)grow 全部 0。

12 字体 woff2 sha 逐字节一致,SSIM 全不变。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-07-24 19:54:07 +08:00
parent 4ae7e05334
commit 791ea0c89e
3 changed files with 13 additions and 3 deletions

View File

@ -222,7 +222,10 @@ export function subsetGPOS(
/** ScriptList/FeatureList 解析失败(异常表)则整体降级返回 null调用方保留原始 GPOS 字节) */
if (!scriptListBytes || !featureListBytes) return null;
const w = new Writer();
/** Writer GPOS
* 2048 GPOS lookup[10] 283 subtable ~16KB 4+ grow
* */
const w = new Writer(gposBytes.byteLength);
/** Header偏移量最后回填 */
w.writeUint16(1);

View File

@ -1398,7 +1398,8 @@ export function subsetGSUB(
/** ScriptList/FeatureList 解析失败(异常表)则整体保留原始 GSUB 字节(安全降级) */
if (!scriptListBytes || !featureListBytes) return gsubBytes;
const w = new Writer();
/** 主 Writer 按原 GSUB 表大小预分配容量,避免大 GSUB令东千字文 GSUB 数十 KB多次 grow 全拷贝 */
const w = new Writer(gsubBytes.byteLength);
/** Header */
w.writeUint16(1);

View File

@ -33,10 +33,16 @@ export class OTWriter {
* subsetGPOS 207 /call ~58% private ensure()V8 class
* private method per-call
* grow */
private buf: Uint8Array = new Uint8Array(2048);
/** 初始容量:默认 2048subsetGPOS/subsetGSUB 主 Writer 按原表大小预分配避免多次 grow 全拷贝 */
private buf: Uint8Array;
private size: number = 0;
private patches: Array<{ pos: number; base: number; targetGetter: () => number }> = [];
/** 预估输出容量的 Writer省去从默认容量多次 2× 扩容的全拷贝。initialCapacity 为 0/省略时用默认 2048。 */
constructor(initialCapacity: number = 2048) {
this.buf = new Uint8Array(initialCapacity > 0 ? initialCapacity : 2048);
}
get length(): number {
return this.size;
}