72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
import { init, Renderer } from "takumi-js/wasm/no-init";
|
|
import type { WorkerRequest, WorkerResult } from "./types";
|
|
import { renderExport } from "./render";
|
|
|
|
let rendererPromise: Promise<Renderer> | undefined;
|
|
async function getRenderer(origin: string) {
|
|
rendererPromise ??= (async () => {
|
|
const response = await fetch(new URL("/takumi.wasm", origin), {
|
|
signal: AbortSignal.timeout(15000),
|
|
});
|
|
if (!response.ok) throw new Error("Unable to load image renderer");
|
|
await init({ module_or_path: await response.arrayBuffer() });
|
|
const renderer = new Renderer();
|
|
try {
|
|
const fonts = await Promise.all(
|
|
[
|
|
{ name: "Anuphan", path: "/Anuphan.ttf" },
|
|
{ name: "Genshin Overview", path: "/zh-cn.ttf" },
|
|
{
|
|
name: "Kanit Overview",
|
|
path: "/Kanit-SemiBold.ttf",
|
|
weight: 600,
|
|
style: "normal" as const,
|
|
},
|
|
{
|
|
name: "Kanit Poster",
|
|
path: "/Kanit-ExtraBoldItalic.ttf",
|
|
weight: 800,
|
|
style: "italic" as const,
|
|
},
|
|
].map(async ({ path, ...descriptor }) => {
|
|
const font = await fetch(new URL(path, origin), {
|
|
signal: AbortSignal.timeout(15000),
|
|
});
|
|
if (!font.ok) throw new Error("Unable to load export fonts");
|
|
return {
|
|
...descriptor,
|
|
data: new Uint8Array(await font.arrayBuffer()),
|
|
};
|
|
}),
|
|
);
|
|
for (const font of fonts) await renderer.registerFont(font);
|
|
return renderer;
|
|
} catch (error) {
|
|
renderer.free();
|
|
throw error;
|
|
}
|
|
})().catch((error) => {
|
|
rendererPromise = undefined;
|
|
throw error;
|
|
});
|
|
return rendererPromise;
|
|
}
|
|
let queue = Promise.resolve();
|
|
self.onmessage = ({ data }: MessageEvent<WorkerRequest>) => {
|
|
queue = queue.then(async () => {
|
|
try {
|
|
const renderer = await getRenderer(data.origin);
|
|
const image = await renderExport(renderer, data.request, data.origin);
|
|
const bytes = image.buffer as ArrayBuffer;
|
|
self.postMessage({ id: data.id, bytes } satisfies WorkerResult, {
|
|
transfer: [bytes],
|
|
});
|
|
} catch (error) {
|
|
self.postMessage({
|
|
id: data.id,
|
|
error: error instanceof Error ? error.message : "Image export failed",
|
|
} satisfies WorkerResult);
|
|
}
|
|
});
|
|
};
|