{"version":3,"file":"AnimatedGIF.mjs","sources":["../src/AnimatedGIF.ts"],"sourcesContent":["import { decompressFrames, ParsedFrame, parseGIF } from 'gifuct-js';\nimport { DOMAdapter, SCALE_MODE, Sprite, Texture, Ticker, UPDATE_PRIORITY } from 'pixi.js';\n\n/** Represents a single frame of a GIF. Includes image and timing data. */\ninterface FrameObject\n{\n    /** Image data for the current frame */\n    imageData: ImageData;\n    /** The start of the current frame, in milliseconds */\n    start: number;\n    /** The end of the current frame, in milliseconds */\n    end: number;\n}\n\n/** Default options for all AnimatedGIF objects. */\ninterface AnimatedGIFOptions\n{\n    /** Whether to start playing right away */\n    autoPlay: boolean;\n    /**\n     * Scale Mode to use for the texture\n     * @type {PIXI.SCALE_MODE}\n     */\n    scaleMode: SCALE_MODE;\n    /** To enable looping */\n    loop: boolean;\n    /** Speed of the animation */\n    animationSpeed: number;\n    /** Set to `false` to manage updates yourself */\n    autoUpdate: boolean;\n    /** The completed callback, optional */\n    onComplete: null | (() => void);\n    /** The loop callback, optional */\n    onLoop: null | (() => void);\n    /** The frame callback, optional */\n    onFrameChange: null | ((currentFrame: number) => void);\n    /** Fallback FPS if GIF contains no time information */\n    fps?: number;\n}\n\n/** Options for the AnimatedGIF constructor. */\ninterface AnimatedGIFSize\n{\n    /** Width of the GIF image */\n    width: number;\n    /** Height of the GIF image */\n    height: number;\n}\n\n/**\n * Runtime object to play animated GIFs. This object is similar to an AnimatedSprite.\n * It support playback (seek, play, stop) as well as animation speed and looping.\n * @see Thanks to {@link https://github.com/matt-way/gifuct-js/ gifuct-js}\n */\nclass AnimatedGIF extends Sprite\n{\n    /**\n     * Default options for all AnimatedGIF objects.\n     * @property {PIXI.SCALE_MODE} [scaleMode='linear'] - Scale mode to use for the texture.\n     * @property {boolean} [loop=true] - To enable looping.\n     * @property {number} [animationSpeed=1] - Speed of the animation.\n     * @property {boolean} [autoUpdate=true] - Set to `false` to manage updates yourself.\n     * @property {boolean} [autoPlay=true] - To start playing right away.\n     * @property {Function} [onComplete=null] - The completed callback, optional.\n     * @property {Function} [onLoop=null] - The loop callback, optional.\n     * @property {Function} [onFrameChange=null] - The frame callback, optional.\n     * @property {number} [fps=30] - Fallback FPS if GIF contains no time information.\n     */\n    public static defaultOptions: AnimatedGIFOptions = {\n        scaleMode: 'linear',\n        fps: 30,\n        loop: true,\n        animationSpeed: 1,\n        autoPlay: true,\n        autoUpdate: true,\n        onComplete: null,\n        onFrameChange: null,\n        onLoop: null,\n    };\n\n    /**\n     * The speed that the animation will play at. Higher is faster, lower is slower.\n     * @default 1\n     */\n    public animationSpeed = 1;\n\n    /**\n     * Whether or not the animate sprite repeats after playing.\n     * @default true\n     */\n    public loop = true;\n\n    /**\n     * User-assigned function to call when animation finishes playing. This only happens\n     * if loop is set to `false`.\n     *\n     * @example\n     * animation.onComplete = () => {\n     *   // finished!\n     * };\n     */\n    public onComplete?: () => void;\n\n    /**\n     * User-assigned function to call when animation changes which texture is being rendered.\n     *\n     * @example\n     * animation.onFrameChange = () => {\n     *   // updated!\n     * };\n     */\n    public onFrameChange?: (currentFrame: number) => void;\n\n    /**\n     * User-assigned function to call when `loop` is true, and animation is played and\n     * loops around to start again. This only happens if loop is set to `true`.\n     *\n     * @example\n     * animation.onLoop = () => {\n     *   // looped!\n     * };\n     */\n    public onLoop?: () => void;\n\n    /** The total duration of animation in milliseconds. */\n    public readonly duration: number = 0;\n\n    /** Whether to play the animation after constructing. */\n    public readonly autoPlay: boolean = true;\n\n    /** Collection of frame to render. */\n    private _frames: FrameObject[];\n\n    /** Drawing context reference. */\n    private _context: CanvasRenderingContext2D;\n\n    /** Dirty means the image needs to be redrawn. Set to `true` to force redraw. */\n    public dirty = false;\n\n    /** The current frame number (zero-based index). */\n    private _currentFrame = 0;\n\n    /** `true` uses PIXI.Ticker.shared to auto update animation time.*/\n    private _autoUpdate = false;\n\n    /** `true` if the instance is currently connected to PIXI.Ticker.shared to auto update animation time. */\n    private _isConnectedToTicker = false;\n\n    /** If animation is currently playing. */\n    private _playing = false;\n\n    /** Current playback position in milliseconds. */\n    private _currentTime = 0;\n\n    /**\n     * Create an animated GIF animation from a GIF image's ArrayBuffer. The easiest way to get\n     * the buffer is to use Assets.\n     * @example\n     * import { Assets } from 'pixi.js';\n     * import '@pixi/gif';\n     *\n     * const gif = await Assets.load('file.gif');\n     * @param buffer - GIF image arraybuffer from Assets.\n     * @param options - Options to use.\n     * @returns\n     */\n    static fromBuffer(buffer: ArrayBuffer, options?: Partial<AnimatedGIFOptions>): AnimatedGIF\n    {\n        if (!buffer || buffer.byteLength === 0)\n        {\n            throw new Error('Invalid buffer');\n        }\n\n        // fix https://github.com/matt-way/gifuct-js/issues/30\n        const validateAndFix = (gif: any): void =>\n        {\n            let currentGce = null;\n\n            for (const frame of gif.frames)\n            {\n                currentGce = frame.gce ?? currentGce;\n\n                // fix loosing graphic control extension for same frames\n                if ('image' in frame && !('gce' in frame))\n                {\n                    frame.gce = currentGce;\n                }\n            }\n        };\n\n        const gif = parseGIF(buffer);\n\n        validateAndFix(gif);\n        const gifFrames = decompressFrames(gif, true);\n        const frames: FrameObject[] = [];\n\n        // Temporary canvases required for compositing frames\n        const canvas = DOMAdapter.get().createCanvas(gif.lsd.width, gif.lsd.height) as HTMLCanvasElement;\n        const context = canvas.getContext('2d', {\n            willReadFrequently: true,\n        }) as CanvasRenderingContext2D;\n        const patchCanvas = DOMAdapter.get().createCanvas() as HTMLCanvasElement;\n        const patchContext = patchCanvas.getContext('2d') as CanvasRenderingContext2D;\n\n        let time = 0;\n        let previousFrame: ImageData | null = null;\n\n        // Some GIFs have a non-zero frame delay, so we need to calculate the fallback\n        const { fps } = Object.assign({}, AnimatedGIF.defaultOptions, options);\n        const defaultDelay = 1000 / (fps as number);\n\n        // Precompute each frame and store as ImageData\n        for (let i = 0; i < gifFrames.length; i++)\n        {\n            // Some GIF's omit the disposalType, so let's assume clear if missing\n            const {\n                disposalType = 2,\n                delay = defaultDelay,\n                patch,\n                dims: { width, height, left, top },\n            } = gifFrames[i] as ParsedFrame;\n\n            patchCanvas.width = width;\n            patchCanvas.height = height;\n            patchContext.clearRect(0, 0, width, height);\n            const patchData = patchContext.createImageData(width, height);\n\n            patchData.data.set(patch);\n            patchContext.putImageData(patchData, 0, 0);\n\n            if (disposalType === 3)\n            {\n                previousFrame = context.getImageData(0, 0, canvas.width, canvas.height);\n            }\n\n            context.drawImage(patchCanvas, left, top);\n            const imageData = context.getImageData(0, 0, canvas.width, canvas.height);\n\n            if (disposalType === 2)\n            {\n                context.clearRect(0, 0, canvas.width, canvas.height);\n            }\n            else if (disposalType === 3)\n            {\n                context.putImageData(previousFrame as ImageData, 0, 0);\n            }\n\n            frames.push({\n                start: time,\n                end: time + delay,\n                imageData,\n            });\n            time += delay;\n        }\n\n        // clear the canvases\n        canvas.width = canvas.height = 0;\n        patchCanvas.width = patchCanvas.height = 0;\n        const { width, height } = gif.lsd;\n\n        return new AnimatedGIF(frames, { width, height, ...options });\n    }\n\n    /**\n     * @param frames - Data of the GIF image.\n     * @param options - Options for the AnimatedGIF\n     */\n    constructor(frames: FrameObject[], options: Partial<AnimatedGIFOptions> & AnimatedGIFSize)\n    {\n        super(Texture.EMPTY);\n\n        // Handle rerenders\n        this.onRender = () => this.updateFrame();\n\n        // Get the options, apply defaults\n        const { scaleMode, width, height, ...rest } = Object.assign({},\n            AnimatedGIF.defaultOptions,\n            options\n        );\n\n        // Create the texture\n        const canvas = DOMAdapter.get().createCanvas(width, height) as HTMLCanvasElement;\n        const context = canvas.getContext('2d') as CanvasRenderingContext2D;\n\n        this.texture = Texture.from(canvas);\n        this.texture.source.scaleMode = scaleMode;\n\n        this.duration = (frames[frames.length - 1] as FrameObject).end;\n        this._frames = frames;\n        this._context = context;\n        this._playing = false;\n        this._currentTime = 0;\n        this._isConnectedToTicker = false;\n        Object.assign(this, rest);\n\n        // Draw the first frame\n        this.currentFrame = 0;\n        if (rest.autoPlay)\n        {\n            this.play();\n        }\n    }\n\n    /** Stops the animation. */\n    public stop(): void\n    {\n        if (!this._playing)\n        {\n            return;\n        }\n\n        this._playing = false;\n        if (this._autoUpdate && this._isConnectedToTicker)\n        {\n            Ticker.shared.remove(this.update, this);\n            this._isConnectedToTicker = false;\n        }\n    }\n\n    /** Plays the animation. */\n    public play(): void\n    {\n        if (this._playing)\n        {\n            return;\n        }\n\n        this._playing = true;\n        if (this._autoUpdate && !this._isConnectedToTicker)\n        {\n            Ticker.shared.add(this.update, this, UPDATE_PRIORITY.HIGH);\n            this._isConnectedToTicker = true;\n        }\n\n        // If were on the last frame and stopped, play should resume from beginning\n        if (!this.loop && this.currentFrame === this._frames.length - 1)\n        {\n            this._currentTime = 0;\n        }\n    }\n\n    /**\n     * Get the current progress of the animation from 0 to 1.\n     * @readonly\n     */\n    public get progress(): number\n    {\n        return this._currentTime / this.duration;\n    }\n\n    /** `true` if the current animation is playing */\n    public get playing(): boolean\n    {\n        return this._playing;\n    }\n\n    /**\n     * Updates the object transform for rendering. You only need to call this\n     * if the `autoUpdate` property is set to `false`.\n     *\n     * @param deltaTime - Time since last tick.\n     */\n    update(ticker: Ticker): void\n    {\n        if (!this._playing)\n        {\n            return;\n        }\n\n        const elapsed = this.animationSpeed * ticker.deltaTime / Ticker.targetFPMS;\n        const currentTime = this._currentTime + elapsed;\n        const localTime = currentTime % this.duration;\n\n        const localFrame = this._frames.findIndex((frame) =>\n            frame.start <= localTime && frame.end > localTime);\n\n        if (currentTime >= this.duration)\n        {\n            if (this.loop)\n            {\n                this._currentTime = localTime;\n                this.updateFrameIndex(localFrame);\n                this.onLoop?.();\n            }\n            else\n            {\n                this._currentTime = this.duration;\n                this.updateFrameIndex(this._frames.length - 1);\n                this.onComplete?.();\n                this.stop();\n            }\n        }\n        else\n        {\n            this._currentTime = localTime;\n            this.updateFrameIndex(localFrame);\n        }\n    }\n\n    /**\n     * Redraw the current frame, is necessary for the animation to work when\n     */\n    private updateFrame(): void\n    {\n        if (!this.dirty)\n        {\n            return;\n        }\n\n        // Update the current frame\n        const { imageData } = this._frames[this._currentFrame] as FrameObject;\n\n        this._context.putImageData(imageData, 0, 0);\n\n        // Workaround hack for Safari & iOS\n        // which fails to upload canvas after putImageData\n        // See: https://bugs.webkit.org/show_bug.cgi?id=229986\n        this._context.fillStyle = 'transparent';\n        this._context.fillRect(0, 0, 0, 1);\n        this.texture.source.update();\n\n        // Mark as clean\n        this.dirty = false;\n    }\n\n    /**\n     * Whether to use PIXI.Ticker.shared to auto update animation time.\n     * @default true\n     */\n    get autoUpdate(): boolean\n    {\n        return this._autoUpdate;\n    }\n\n    set autoUpdate(value: boolean)\n    {\n        if (value !== this._autoUpdate)\n        {\n            this._autoUpdate = value;\n\n            if (!this._autoUpdate && this._isConnectedToTicker)\n            {\n                Ticker.shared.remove(this.update, this);\n                this._isConnectedToTicker = false;\n            }\n            else if (this._autoUpdate && !this._isConnectedToTicker && this._playing)\n            {\n                Ticker.shared.add(this.update, this);\n                this._isConnectedToTicker = true;\n            }\n        }\n    }\n\n    /** Set the current frame number */\n    get currentFrame(): number\n    {\n        return this._currentFrame;\n    }\n    set currentFrame(value: number)\n    {\n        this.updateFrameIndex(value);\n        this._currentTime = (this._frames[value] as FrameObject).start;\n    }\n\n    /** Internally handle updating the frame index */\n    private updateFrameIndex(value: number): void\n    {\n        if (value < 0 || value >= this._frames.length)\n        {\n            throw new Error(`Frame index out of range, expecting 0 to ${this.totalFrames}, got ${value}`);\n        }\n        if (this._currentFrame !== value)\n        {\n            this._currentFrame = value;\n            this.dirty = true;\n            this.onFrameChange?.(value);\n        }\n    }\n\n    /**\n     * Get the total number of frame in the GIF.\n     */\n    get totalFrames(): number\n    {\n        return this._frames.length;\n    }\n\n    /** Destroy and don't use after this. */\n    destroy(): void\n    {\n        this.stop();\n        super.destroy(true);\n\n        const forceClear = null as any;\n\n        this._context = forceClear;\n        this._frames = forceClear;\n        this.onComplete = forceClear;\n        this.onFrameChange = forceClear;\n        this.onLoop = forceClear;\n    }\n\n    /**\n     * Cloning the animation is a useful way to create a duplicate animation.\n     * This maintains all the properties of the original animation but allows\n     * you to control playback independent of the original animation.\n     * If you want to create a simple copy, and not control independently,\n     * then you can simply create a new Sprite, e.g. `const sprite = new Sprite(animation.texture)`.\n     *\n     * The clone will be flagged as `dirty` to immediatly trigger an update\n     */\n    clone(): AnimatedGIF\n    {\n        const clone = new AnimatedGIF([...this._frames], {\n            autoUpdate: this._autoUpdate,\n            loop: this.loop,\n            autoPlay: this.autoPlay,\n            scaleMode: this.texture.source.scaleMode,\n            animationSpeed: this.animationSpeed,\n            width: this._context.canvas.width,\n            height: this._context.canvas.height,\n            onComplete: this.onComplete,\n            onFrameChange: this.onFrameChange,\n            onLoop: this.onLoop,\n        });\n\n        clone.dirty = true;\n\n        return clone;\n    }\n}\n\nexport { AnimatedGIF };\nexport type { AnimatedGIFOptions };\n"],"names":["gif","parseGIF","decompressFrames","width","height"],"mappings":"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"}