import createWorkerInterface from '../../util/createWorkerInterface'; import { CancellableCallback } from '../../util/WorkerConnector'; declare const Module: any; declare function allocate(...args: any[]): string; declare function intArrayFromString(str: String): string; declare const self: WorkerGlobalScope; self.importScripts('rlottie-wasm.js'); let rLottieApi: Record; const rLottieApiPromise = new Promise((resolve) => { Module.onRuntimeInitialized = () => { rLottieApi = { init: Module.cwrap('lottie_init', '', []), destroy: Module.cwrap('lottie_destroy', '', ['number']), resize: Module.cwrap('lottie_resize', '', ['number', 'number', 'number']), buffer: Module.cwrap('lottie_buffer', 'number', ['number']), render: Module.cwrap('lottie_render', '', ['number', 'number']), loadFromData: Module.cwrap('lottie_load_from_data', 'number', ['number', 'number']), }; resolve(); }; }); const renderers = new Map(); async function init( key: string, animationData: AnyLiteral, imgSize: number, isLowPriority: boolean, reduceFactor: number, onInit: CancellableCallback, ) { if (!rLottieApi) { await rLottieApiPromise; } const json = JSON.stringify(animationData); const stringOnWasmHeap = allocate(intArrayFromString(json), 'i8', 0); const handle = rLottieApi.init(); const framesCount = rLottieApi.loadFromData(handle, stringOnWasmHeap); rLottieApi.resize(handle, imgSize, imgSize); renderers.set(key, { imgSize, reduceFactor, handle }); onInit(Math.ceil(framesCount / reduceFactor)); } async function renderFrames( key: string, fromIndex: number, toIndex: number, onProgress: CancellableCallback, ) { if (!rLottieApi) { await rLottieApiPromise; } const { imgSize, reduceFactor, handle } = renderers.get(key)!; for (let i = fromIndex; i <= toIndex; i++) { const realIndex = i * reduceFactor; rLottieApi.render(handle, realIndex); const bufferPointer = rLottieApi.buffer(handle); const data = Module.HEAPU8.subarray(bufferPointer, bufferPointer + (imgSize * imgSize * 4)); const arrayBuffer = new Uint8ClampedArray(data).buffer; onProgress(i, arrayBuffer); } } function destroy(key: string) { const renderer = renderers.get(key)!; rLottieApi.destroy(renderer.handle); renderers.delete(key); } createWorkerInterface({ init, renderFrames, destroy, });