mirror of
https://github.com/2234839/web-font.git
synced 2026-09-16 22:26:03 +08:00
perf(loca): subset 模式 Proxy 按需读,跳过全量 30907 项解析
subset 模式下 glyf.read 只访问 subsetGids 相关的 ~40 个 loca 项(含 compound 展开),原全量读 numGlyphs 项(思源 30907)+ 分配 Uint32Array(30907)=124KB 是纯浪费。 loca 表读取顺序在 glyf 之前,subsetGids 尚未构建,无法像 hmtx 那样按已知 gid 列表读。 改用 Proxy 拦截 glyf.read 的 loca[index] 访问,首次访问某 gid 时按需从 view 读并缓存。 实测 loca.read 从 profile 12.2% 降至 0%(思源标点),千字文 fontSubset -6.5%。 非 subset 路径保持原 TypedArray(全量访问下 Proxy trap 反慢)。基准 SSIM/ink/字节全无回归。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
055425e852
commit
d3d96d1735
31
vendor/fonteditor-core/lib/ttf/table/loca.js
vendored
31
vendor/fonteditor-core/lib/ttf/table/loca.js
vendored
@ -16,6 +16,37 @@ var _default = exports.default = _table.default.create('loca', [], {
|
||||
var offset = this.offset;
|
||||
var indexToLocFormat = ttf.head.indexToLocFormat;
|
||||
var numGlyphs = ttf.maxp.numGlyphs;
|
||||
/* 优化(subset Proxy 按需读):subset 模式下 glyf.read(在 loca 之后读取)只访问
|
||||
* subsetGids 相关的 ~20~40 个 loca 项(含 compound 展开后的 gid),而原全量读
|
||||
* numGlyphs 项(思源 30907)+ 分配 Uint32Array(30907)=124KB 是纯浪费。
|
||||
* loca 表读取顺序在 glyf 之前,subsetGids 尚未构建,故无法像 hmtx 那样按已知 gid 列表读——
|
||||
* 改用 Proxy 拦截 glyf.read 的 `loca[index]` 访问,首次访问某 gid 时按需从 view 读并缓存。
|
||||
* 实测思源 8 字:全量读 33μs → Proxy 按需 2μs(15×)。Proxy 仅在 subset 模式启用:
|
||||
* 非 subset(全量字体读取)glyf 访问所有 gid,Proxy trap 开销反而比 TypedArray 慢。 */
|
||||
var subset = ttf.readOptions && ttf.readOptions.subset && ttf.readOptions.subset.length > 0;
|
||||
if (subset) {
|
||||
var viewSub = reader.view;
|
||||
var dvOff = viewSub.byteOffset + offset;
|
||||
/** gid → 字节偏移缓存,避免 compound 多轮重复读同一 gid */
|
||||
var cache = new Map();
|
||||
/** format0: u16×2(偏移以 2 字节为单位存储);format1: u32 */
|
||||
var getLoca = function (gid) {
|
||||
var v = cache.get(gid);
|
||||
if (v !== undefined) return v;
|
||||
v = indexToLocFormat === 0 ? viewSub.getUint16(dvOff + gid * 2, false) * 2 : viewSub.getUint32(dvOff + gid * 4, false);
|
||||
cache.set(gid, v);
|
||||
return v;
|
||||
};
|
||||
reader.offset = offset + (indexToLocFormat === 0 ? numGlyphs * 2 : numGlyphs * 4);
|
||||
/** Proxy 拦截 `loca[index]`:glyf.read 只读访问,无需 set/iterate。
|
||||
* target 用空对象,get trap 对整数键按需读 view,其余(如 symbol)返回 undefined。 */
|
||||
return new Proxy({}, {
|
||||
get: function (_t, key) {
|
||||
var g = typeof key === 'string' ? +key : key;
|
||||
return typeof g === 'number' && g >= 0 && g < numGlyphs ? getLoca(g) : undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
/* 优化(TypedArray 批量读+内联翻转):loca 偏移是大端,原 DataView.getUint16/32 逐次
|
||||
* 调用有边界检查开销。改用 Uint16/32Array 直接 view 共享 buffer + 内联字节翻转,
|
||||
* 实测 format0 快 46%、format1 快 39%(思源 30907 条 157→84μs / 152→93μs)。
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user