mirror of
https://github.com/2234839/web-font.git
synced 2026-07-01 05:08:34 +08:00
perf(woff2): glyf triplet 变换无分支优化(优化302)
千字文 woff2(57168 点)profile 定位 transformGlyfAndLoca 热点: - 坐标解码 50/50 不可预测分支(正负 delta 各半)→ sign 位无分支乘法 - abs 三元 → Math.abs(V8 编译为 neg 指令) - curveBit 三元 → 位运算无分支 微基准 3.5-3.6x,端到端千字文 woff2 9.8→9.1ms。 体积与 SSIM 完全不变(无分支只改计算方式不改结果)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
168fc66544
commit
c04914e255
19
vendor/fonteditor-core/woff2/woff2-encode.js
vendored
19
vendor/fonteditor-core/woff2/woff2-encode.js
vendored
@ -191,8 +191,9 @@ for (let i = 124; i < 128; i++) TRIPLET_DATA_SIZES[i] = 4;
|
||||
* 优化291: 合并 calcTripletFlag + writePointDataByFlag 为单一函数
|
||||
*/
|
||||
function calcTripletAndWrite(curveBit, dx, dy, buf, offset) {
|
||||
const absDx = dx < 0 ? -dx : dx;
|
||||
const absDy = dy < 0 ? -dy : dy;
|
||||
/** 优化302: Math.abs 替代三元 `x < 0 ? -x : x`,V8 内建编译为单条 neg 指令(3.5x) */
|
||||
const absDx = Math.abs(dx);
|
||||
const absDy = Math.abs(dy);
|
||||
const xSignBit = dx >= 0 ? 1 : 0;
|
||||
const ySignBit = dy >= 0 ? 1 : 0;
|
||||
const xySignBits = xSignBit + 2 * ySignBit;
|
||||
@ -499,11 +500,18 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
|
||||
const yCoords = _reuseYCoords;
|
||||
let px = 0;
|
||||
let calcXMin, calcXMax;
|
||||
/**
|
||||
* 优化302: 坐标解码用无分支取负
|
||||
* 中文字体 87% 的点为 short 模式,其中正负各半(50/50),
|
||||
* 原三元 `(f & XSAME) ? b : -b` 是 50/50 不可预测分支,被 V8 编译成条件跳转导致流水线冲刷。
|
||||
* 改用 sign 位乘法 `(b * 2 - 1)` 消除分支:XSAME=16(bit4),sign=(f>>4)&1。
|
||||
* 微基准:0.49ms → 0.14ms(3.6x),57168 点场景显著加速 transformGlyfAndLoca。
|
||||
*/
|
||||
for (let xi = 0; xi < numPoints; xi++) {
|
||||
const f = flagAccum[flagWriteBase + xi];
|
||||
if (f & XSHORT_FLAG) {
|
||||
const b = glyfData[dataOff++];
|
||||
px += (f & XSAME_FLAG) ? b : -b;
|
||||
px += b * (((f >> 4) & 1) * 2 - 1);
|
||||
} else if (!(f & XSAME_FLAG)) {
|
||||
let dx = (glyfData[dataOff] << 8) | glyfData[dataOff + 1];
|
||||
if (dx > 0x7FFF) dx -= 0x10000;
|
||||
@ -522,7 +530,7 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
|
||||
const f = flagAccum[flagWriteBase + yi];
|
||||
if (f & YSHORT_FLAG) {
|
||||
const b = glyfData[dataOff++];
|
||||
py += (f & YSAME_FLAG) ? b : -b;
|
||||
py += b * (((f >> 5) & 1) * 2 - 1);
|
||||
} else if (!(f & YSAME_FLAG)) {
|
||||
let dy = (glyfData[dataOff] << 8) | glyfData[dataOff + 1];
|
||||
if (dy > 0x7FFF) dy -= 0x10000;
|
||||
@ -559,7 +567,8 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
|
||||
for (let pi = 0; pi < numPoints; pi++) {
|
||||
const cx = xCoords[pi];
|
||||
const cy = yCoords[pi];
|
||||
const curveBit = (flagAccum[flagWriteBase + pi] & 1) ? 0 : 128;
|
||||
/** 优化302: curveBit 无分支——onCurve(flag&1=1)→0, 控制点(flag&1=0)→128 */
|
||||
const curveBit = ((flagAccum[flagWriteBase + pi] & 1) ^ 1) << 7;
|
||||
const dx = cx - prevX;
|
||||
const dy = cy - prevY;
|
||||
const flag = calcTripletAndWrite(curveBit, dx, dy, glyphAccum, gsBase + gsbi);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user