mirror of
https://github.com/2234839/web-font.git
synced 2026-04-30 05:08:14 +08:00
name.js write 函数改用 view.setUint16 后未同步 writer.offset, 导致 name 字符串覆盖 header,name 表损坏。浏览器依赖 name 表 识别字体所以无法渲染,而 Node 端渲染不依赖 name 表所以基准 测试未检测到。 同时修复 cmap sizeof 动态计算记录头大小的问题。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
78 lines
3.0 KiB
TypeScript
78 lines
3.0 KiB
TypeScript
/**
|
||
* LLRT 字体裁剪 — 生成子集字体供 Node 渲染验证
|
||
* 运行: pnpm build_backend && ./llrt dist_backend/llrt_bench.lrt
|
||
*/
|
||
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
||
import { performance } from "node:perf_hooks";
|
||
import { Font } from "./vendor/fonteditor-core/lib/ttf/font.js";
|
||
|
||
const FONT_PATH = "font/令东齐伋复刻体.ttf";
|
||
const FONT_NAME = "令东齐伋复刻体";
|
||
const BENCHMARK_DIR = "benchmark_results";
|
||
|
||
const testCases = [
|
||
{ label: "8个汉字", text: "天地玄黄宇宙洪荒" },
|
||
{ label: "拉丁+数字", text: "Hello World 123" },
|
||
{ label: "千字文前段", text: "天地玄黄宇宙洪荒日月盈昃辰宿列张寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈剑号巨阙珠称夜光果珍李柰菜重芥姜海咸河淡鳞潜羽翔" },
|
||
];
|
||
|
||
const ROUNDS = 10;
|
||
|
||
async function main() {
|
||
const raw = await readFile(FONT_PATH);
|
||
const fontBuffer = new Uint8Array(raw).buffer;
|
||
|
||
await mkdir(BENCHMARK_DIR, { recursive: true });
|
||
|
||
console.log("\n=== LLRT 字体裁剪验证 ===\n");
|
||
console.log("[runtime]", globalThis.process?.release?.name ?? "unknown");
|
||
console.log("[font]", FONT_PATH, "size:", fontBuffer.byteLength, "bytes\n");
|
||
|
||
const summary: Array<{ label: string; text: string; avg: number; min: number; max: number; outputSize: number; fontFile: string }> = [];
|
||
|
||
for (const { label, text } of testCases) {
|
||
const subset = [...text].map((c) => c.codePointAt(0)!);
|
||
const times: number[] = [];
|
||
let lastOutput: Uint8Array | null = null;
|
||
|
||
for (let i = 0; i < ROUNDS; i++) {
|
||
const t0 = performance.now();
|
||
const font = Font.create(fontBuffer, { type: "ttf", subset });
|
||
const optimized = font.optimize().sort();
|
||
const result = optimized.write({ type: "ttf" });
|
||
const t1 = performance.now();
|
||
times.push(t1 - t0);
|
||
|
||
if (i === 0) {
|
||
lastOutput = typeof result === "string"
|
||
? new TextEncoder().encode(result)
|
||
: new Uint8Array(result);
|
||
}
|
||
}
|
||
|
||
const avg = times.reduce((a, b) => a + b, 0) / times.length;
|
||
const min = Math.min(...times);
|
||
const max = Math.max(...times);
|
||
const size = lastOutput?.length ?? 0;
|
||
|
||
/** 保存子集字体文件 */
|
||
const safeLabel = label.replace(/[^a-zA-Z0-9\u4e00-\u9fff]/g, "_");
|
||
const fontFile = `${BENCHMARK_DIR}/llrt_${safeLabel}.ttf`;
|
||
if (lastOutput) {
|
||
await writeFile(fontFile, lastOutput);
|
||
}
|
||
|
||
summary.push({ label, text, avg, min, max, outputSize: size, fontFile });
|
||
console.log(` ${label}: avg=${avg.toFixed(1)}ms min=${min.toFixed(1)}ms max=${max.toFixed(1)}ms 输出=${size.toLocaleString()} bytes`);
|
||
}
|
||
|
||
await writeFile(
|
||
`${BENCHMARK_DIR}/llrt_bench_meta.json`,
|
||
JSON.stringify({ runtime: globalThis.process?.release?.name, fontPath: FONT_PATH, fontName: FONT_NAME, rounds: ROUNDS, results: summary }, null, 2),
|
||
);
|
||
|
||
console.log("\n子集字体已保存,请运行: pnpm tsx 基准测试_verify.ts");
|
||
}
|
||
|
||
main();
|