import { MODULE } from '../pkg/justified-layout-wasm-module.js'; import { initSync, get_justified_layout } from '../pkg/justified-layout-wasm.js'; export interface LayoutOptions { rowHeight: number; rowWidth: number; spacing: number; heightTolerance: number; } /* * This is a wrapper class to interact with the layout generated by the Wasm function. * This design is used because: * - The layout is stored in a Float32Array for efficiency, which is not very user-friendly * - Creating objects from the Float32Array takes more time than the actual layout calculation * - Using getter methods avoids dynamic heap allocation beyond the initial layout calculation * - The class provides a static prototype that can be JIT-compiled efficiently, inlining all of its methods * - V8 does not box float32 values, unlike most other data types */ export class JustifiedLayout { layout: Float32Array; constructor(aspectRatios: Float32Array, { rowHeight, rowWidth, spacing, heightTolerance }: LayoutOptions) { initSync(MODULE); if (aspectRatios.length === 0) { this.layout = new Float32Array(4); } else { this.layout = get_justified_layout(aspectRatios, rowHeight, rowWidth, spacing, heightTolerance); } } get containerWidth() { return this.layout[0]; } get containerHeight() { return this.layout[1]; } getTop(boxIdx: number) { return this.layout[boxIdx * 4 + 4]; // the first 4 elements are containerWidth, containerHeight, padding, padding } getLeft(boxIdx: number) { return this.layout[boxIdx * 4 + 5]; } getWidth(boxIdx: number) { return this.layout[boxIdx * 4 + 6]; } getHeight(boxIdx: number) { return this.layout[boxIdx * 4 + 7]; } getPosition(boxIdx: number) { return { top: this.layout[boxIdx * 4 + 4], left: this.layout[boxIdx * 4 + 5], width: this.layout[boxIdx * 4 + 6], height: this.layout[boxIdx * 4 + 7] } } }