@@ -547,6 +547,102 @@ class BoxArea {
547547}
548548` ` `
549549
550+ ## Environments
551+
552+ Dropflow is designed to support a flexible configuration of environments . In the browser , it loads fonts (soon , images too ) via ` fetch ` and registers font buffers to ` document.fonts ` . In Nodejs , dropflow can load fonts synchronously via ` fs.readFileSync ` .
553+
554+ When you use the canvas backend with dropflow and ` node-canvas ` is present , it will call node - canvas ' s `registerFont`. Node-canvas doesn' t support font buffers , so you have to use file :// URLs.
555+
556+ If you want to use ` @napi-rs/canvas ` or ` skia-canvas ` , you ' ll need just a few lines of code to wire `flow.environment.registerFont` to the appropriate font registration APIs.
557+
558+ ### Hooks
559+
560+ There are 4 hooks you can override , documented below . They have default implementations based on whether dropflow was built for the browser or node (" browser" export condition or " default" ) but may not be sufficient for your use case .
561+
562+ ` ` ` ts
563+ const environment: Environment;
564+
565+ interface Environment {
566+ /**
567+ * Must return a promise of a Uint8Array of dropflow.wasm. Typically this
568+ * just does a fetch() or fs.readFile.
569+ */
570+ wasmLocator(): Promise<Uint8Array>;
571+ /**
572+ * This will get called when a font in flow.fonts transitions to loaded or
573+ * when an already loaded font is added to flow.fonts. It's intended to be
574+ * used to add the font to the underlying paint target.
575+ *
576+ * Use ` face .getBuffer ` if the backend supports font buffers. You can use the
577+ * url property to access the file if it doesn't (node-canvas v2). The font
578+ * will be selected via ` face .uniqueFamily ` and nothing else.
579+ *
580+ * You can return an unregister function which will be called when the font
581+ * is no longer needed by dropflow (eg user called ` flow .fonts .delete ` ).
582+ */
583+ registerFont(face: LoadedFontFace): (() => void) | void;
584+ /**
585+ * Must return a promise of a buffer for the given URL. This used for fonts
586+ * and will be used for images.
587+ */
588+ resolveUrl(url: URL): Promise<ArrayBufferLike>
589+ /**
590+ * Same as ` resolveUrl ` , but synchronous if it's a file:// URL. This should
591+ * throw if URL is not a file:// URL, which would mean the user called
592+ * loadSync on a document with asynchronous-only URLs.
593+ */
594+ resolveUrlSync(url: URL): ArrayBufferLike;
595+ }
596+ ` ` `
597+
598+ ### Using ` @napi-rs/canvas `
599+
600+ ` ` ` ts
601+ import {GlobalFonts} from '@napi-rs/canvas';
602+ import * as flow from 'dropflow';
603+
604+ // Configure @napi-rs/canvas
605+ flow.environment.registerFont = face => {
606+ const key = GlobalFonts.register(face.getBuffer(), face.uniqueFamily);
607+ if (key) return () => GlobalFonts.remove(key);
608+ };
609+ ` ` `
610+
611+ ### Using ` skia-canvas `
612+
613+ ` ` ` ts
614+ import {FontLibrary} from 'skia-canvas';
615+ import * as flow from 'dropflow';
616+
617+ // Configure skia-canvas
618+ flow.environment.registerFont = face => {
619+ FontLibrary.use(face.uniqueFamily, fileURLToPath(face.url));
620+ };
621+ ` ` `
622+
623+ ### Overriding the WASM location
624+
625+ ` ` ` ts
626+ // This should usually go in a config.js file that is imported before dropflow,
627+ // because dropflow's own modules use top-level await to retrieve dropflow.wasm.
628+ // (Bundlers guarantee import order but only relative to other imports)
629+ import * as flow from 'dropflow';
630+ // This will be the path to wasm if you're using Bun. Vite (others?) need ?url
631+ import wasmUrl from 'dropflow/dropflow.wasm';
632+ // or you can get it some other way
633+ // const wasmUrl = 'the/path/to/dropflow.wasm';
634+
635+ flow.environment.wasmLocator = function () {
636+ return fetch(wasmUrl).then(res => {
637+ if (res.status === 200) {
638+ return res.arrayBuffer()
639+ } else {
640+ throw new Error(res.statusText);
641+ }
642+ });
643+ };
644+ ` ` `
645+
550646## Other
551647
552648### ` staticLayoutContribution `
0 commit comments