mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 04:28:11 +08:00
* Add node graph frame tool * Add a brighten * Use the node graph * Fix topological_sort * Update UI * Add icons for the tool and layer type * Avoid serde & use bitmaps to improve performance * Allow serialising a node graph * Fix missing ..Default::default() * Fix incorrect comments * Cache node graph output image * Suppress no-cycle import warning Co-authored-by: Keavon Chambers <keavon@keavon.com>
65 lines
3.1 KiB
TypeScript
65 lines
3.1 KiB
TypeScript
import type WasmBindgenPackage from "@/../wasm/pkg";
|
|
import { panicProxy } from "@/utility-functions/panic-proxy";
|
|
import { type JsMessageType } from "@/wasm-communication/messages";
|
|
import { createSubscriptionRouter, type SubscriptionRouter } from "@/wasm-communication/subscription-router";
|
|
|
|
export type WasmRawInstance = typeof WasmBindgenPackage;
|
|
export type WasmEditorInstance = InstanceType<WasmRawInstance["JsEditorHandle"]>;
|
|
export type Editor = Readonly<ReturnType<typeof createEditor>>;
|
|
|
|
// `wasmImport` starts uninitialized because its initialization needs to occur asynchronously, and thus needs to occur by manually calling and awaiting `initWasm()`
|
|
let wasmImport: WasmRawInstance | undefined;
|
|
let editorInstance: WasmEditorInstance | undefined;
|
|
|
|
export async function updateImage(path: BigUint64Array, mime: string, imageData: Uint8Array, documentId: bigint): Promise<void> {
|
|
const blob = new Blob([imageData], { type: mime });
|
|
|
|
const blobURL = URL.createObjectURL(blob);
|
|
|
|
// Pre-decode the image so it is ready to be drawn instantly once it's placed into the viewport SVG
|
|
const image = new Image();
|
|
image.src = blobURL;
|
|
await image.decode();
|
|
|
|
editorInstance?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight);
|
|
}
|
|
|
|
// Should be called asynchronously before `createEditor()`
|
|
export async function initWasm(): Promise<void> {
|
|
// Skip if the WASM module is already initialized
|
|
if (wasmImport !== undefined) return;
|
|
|
|
// Import the WASM module JS bindings and wrap them in the panic proxy
|
|
// eslint-disable-next-line import/no-cycle
|
|
wasmImport = await import("@/../wasm/pkg").then(panicProxy);
|
|
|
|
// Provide a random starter seed which must occur after initializing the WASM module, since WASM can't generate its own random numbers
|
|
const randomSeed = BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
|
|
wasmImport?.setRandomSeed(randomSeed);
|
|
}
|
|
|
|
// Should be called after running `initWasm()` and its promise resolving
|
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
export function createEditor() {
|
|
// Raw: Object containing several callable functions from `editor_api.rs` defined directly on the WASM module, not the editor instance (generated by wasm-bindgen)
|
|
if (!wasmImport) throw new Error("Editor WASM backend was not initialized at application startup");
|
|
const raw: WasmRawInstance = wasmImport;
|
|
|
|
// Instance: Object containing many functions from `editor_api.rs` that are part of the editor instance (generated by wasm-bindgen)
|
|
const instance: WasmEditorInstance = new raw.JsEditorHandle((messageType: JsMessageType, messageData: Record<string, unknown>): void => {
|
|
// This callback is called by WASM when a FrontendMessage is received from the WASM wrapper editor instance
|
|
// We pass along the first two arguments then add our own `raw` and `instance` context for the last two arguments
|
|
subscriptions.handleJsMessage(messageType, messageData, raw, instance);
|
|
});
|
|
editorInstance = instance;
|
|
|
|
// Subscriptions: Allows subscribing to messages in JS that are sent from the WASM backend
|
|
const subscriptions: SubscriptionRouter = createSubscriptionRouter();
|
|
|
|
return {
|
|
raw,
|
|
instance,
|
|
subscriptions,
|
|
};
|
|
}
|