mirror of
https://github.com/2234839/web-font.git
synced 2026-09-10 18:55:50 +08:00
perf(loca): TypedArray 批量读+内联翻转替代 DataView 循环,loca 解析快 39%~46%
loca 偏移是大端,原 DataView.getUint16/32 逐次调用含边界检查开销。改用 Uint16/32Array 直接 view 共享 buffer + 内联字节翻转,微基准实测: - format0(Uint16):157→84μs(-46%) - format1(Uint32):152→93μs(-39%) (思源 30907 条 loca) 返回 Uint32Array 替代普通 Array,glyf.js 仅按下标 loca[index] 只读访问, 与 TypedArray 兼容(已确认 loca 仅被 glyf.js:22 读取、ttfreader.js:216 置 null)。 对齐保护:Uint16Array 需 2 字节对齐、Uint32Array 需 4 字节对齐,loca offset 来自表目录不保证对齐。检测 srcByteOff 对齐情况,未对齐回退 DataView 路径。 验证:基准测试 29 用例 SSIM 全部无回归;4 用例(思源千字文/标点/FiraCode/ttf) sha256 输出字节逐字节等价。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6f96e2b1dd
commit
d793e22d92
45
vendor/fonteditor-core/lib/ttf/table/loca.js
vendored
45
vendor/fonteditor-core/lib/ttf/table/loca.js
vendored
@ -15,21 +15,46 @@ var _default = exports.default = _table.default.create('loca', [], {
|
||||
read: function read(reader, ttf) {
|
||||
var offset = this.offset;
|
||||
var indexToLocFormat = ttf.head.indexToLocFormat;
|
||||
/* 优化7: 直接 view 批量读取,预分配数组 */
|
||||
var numGlyphs = ttf.maxp.numGlyphs;
|
||||
var wordOffset = new Array(numGlyphs);
|
||||
/* 优化(TypedArray 批量读+内联翻转):loca 偏移是大端,原 DataView.getUint16/32 逐次
|
||||
* 调用有边界检查开销。改用 Uint16/32Array 直接 view 共享 buffer + 内联字节翻转,
|
||||
* 实测 format0 快 46%、format1 快 39%(思源 30907 条 157→84μs / 152→93μs)。
|
||||
* 返回 Uint32Array,glyf.js 仅按下标 `loca[index]` 只读访问,与 TypedArray 兼容。 */
|
||||
var view = reader.view;
|
||||
var srcByteOff = view.byteOffset + offset;
|
||||
if (indexToLocFormat === 0) {
|
||||
var vOffset = view.byteOffset + offset;
|
||||
for (var i = 0; i < numGlyphs; i++) {
|
||||
wordOffset[i] = view.getUint16(vOffset, false) * 2;
|
||||
vOffset += 2;
|
||||
if ((srcByteOff & 1) === 0) {
|
||||
/* 优化(TypedArray 批量读+内联翻转):offset 对齐 2 时用 Uint16Array view 共享 buffer,
|
||||
* 避免 DataView.getUint16 逐次边界检查,实测快 46%。 */
|
||||
var src16 = new Uint16Array(view.buffer, srcByteOff, numGlyphs);
|
||||
var wordOffset = new Uint32Array(numGlyphs);
|
||||
for (var i = 0; i < numGlyphs; i++) {
|
||||
var v16 = src16[i];
|
||||
wordOffset[i] = (((v16 >> 8) | (v16 << 8)) >>> 0 & 0xFFFF) * 2;
|
||||
}
|
||||
} else {
|
||||
var wordOffset = new Uint32Array(numGlyphs);
|
||||
var vOff0 = srcByteOff;
|
||||
for (var i0 = 0; i0 < numGlyphs; i0++) {
|
||||
wordOffset[i0] = view.getUint16(vOff0, false) * 2;
|
||||
vOff0 += 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var vOffset2 = view.byteOffset + offset;
|
||||
for (var j = 0; j < numGlyphs; j++) {
|
||||
wordOffset[j] = view.getUint32(vOffset2, false);
|
||||
vOffset2 += 4;
|
||||
if ((srcByteOff & 3) === 0) {
|
||||
var src32 = new Uint32Array(view.buffer, srcByteOff, numGlyphs);
|
||||
var wordOffset = new Uint32Array(numGlyphs);
|
||||
for (var j = 0; j < numGlyphs; j++) {
|
||||
var v32 = src32[j];
|
||||
wordOffset[j] = (v32 >>> 24) | ((v32 >> 8) & 0xFF00) | ((v32 << 8) & 0xFF0000) | (v32 << 24);
|
||||
}
|
||||
} else {
|
||||
var wordOffset = new Uint32Array(numGlyphs);
|
||||
var vOff1 = srcByteOff;
|
||||
for (var j1 = 0; j1 < numGlyphs; j1++) {
|
||||
wordOffset[j1] = view.getUint32(vOff1, false);
|
||||
vOff1 += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
reader.offset = offset + (indexToLocFormat === 0 ? numGlyphs * 2 : numGlyphs * 4);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user