{"version":3,"file":"AbstractTextSystem.mjs","sources":["../../../../src/scene/text/shared/AbstractTextSystem.ts"],"sourcesContent":["import { type ICanvas } from '../../../environment/canvas/ICanvas';\nimport { type Filter } from '../../../filters/Filter';\nimport { TexturePool } from '../../../rendering/renderers/shared/texture/TexturePool';\nimport { TextureStyle } from '../../../rendering/renderers/shared/texture/TextureStyle';\nimport { deprecation } from '../../../utils/logging/deprecation';\nimport { CanvasTextGenerator } from '../canvas/CanvasTextGenerator';\nimport { type CanvasTextOptions, type Text } from '../Text';\nimport { TextStyle } from '../TextStyle';\nimport { getPo2TextureFromSource } from '../utils/getPo2TextureFromSource';\n\nimport type { System } from '../../../rendering/renderers/shared/system/System';\nimport type { Texture } from '../../../rendering/renderers/shared/texture/Texture';\nimport type { Renderer } from '../../../rendering/renderers/types';\n\n/**\n * Base system plugin to the renderer to manage canvas text.\n * @category rendering\n * @advanced\n */\nexport abstract class AbstractTextSystem implements System\n{\n    protected readonly _renderer: Renderer;\n    private readonly _retainCanvasContext: boolean;\n\n    private readonly _activeTextures: Record<string, {\n        texture: Texture,\n        usageCount: number,\n    }> = {};\n\n    constructor(renderer: Renderer, retainCanvasContext: boolean)\n    {\n        this._renderer = renderer;\n        this._retainCanvasContext = retainCanvasContext;\n    }\n\n    /** @deprecated since 8.0.0 */\n    public getTexture(text: string, resolution: number, style: TextStyle, textKey: string): Texture;\n    /**\n     * This is a function that will create a texture from a text string, style and resolution.\n     * Useful if you want to make a texture of your text and use if for various pixi things!\n     * @param options - The options of the text that will be used to generate the texture.\n     * @param options.text - the text to render\n     * @param options.style - the style of the text\n     * @param options.resolution - the resolution of the texture\n     * @returns the newly created texture\n     */\n    public getTexture(options: CanvasTextOptions): Texture;\n    public getTexture(\n        options: CanvasTextOptions | string,\n        _resolution?: number,\n        _style?: TextStyle,\n        _textKey?: string\n    ): Texture\n    {\n        if (typeof options === 'string')\n        {\n            // #if _DEBUG\n            deprecation('8.0.0', 'CanvasTextSystem.getTexture: Use object TextOptions instead of separate arguments');\n            // #endif\n\n            options = {\n                text: options,\n                style: _style,\n                resolution: _resolution,\n            };\n        }\n\n        if (!(options.style instanceof TextStyle))\n        {\n            options.style = new TextStyle(options.style);\n        }\n\n        if (!(options.textureStyle instanceof TextureStyle))\n        {\n            options.textureStyle = new TextureStyle(options.textureStyle);\n        }\n\n        if (typeof options.text !== 'string')\n        {\n            options.text = options.text.toString();\n        }\n\n        const { text, style, textureStyle, autoGenerateMipmaps } = options;\n\n        const resolution = options.resolution ?? this._renderer.resolution;\n\n        const { frame, canvasAndContext } = CanvasTextGenerator.getCanvasAndContext({\n            text: text as string,\n            style: style as TextStyle,\n            resolution,\n        });\n\n        const texture = getPo2TextureFromSource(\n            canvasAndContext.canvas,\n            frame.width,\n            frame.height,\n            resolution,\n            autoGenerateMipmaps\n        );\n\n        if (textureStyle) texture.source.style = textureStyle as TextureStyle;\n\n        if (style.trim)\n        {\n            // reapply the padding to the frame\n            frame.pad(style.padding);\n            texture.frame.copyFrom(frame);\n\n            // We initially increased the frame size by a resolution factor to achieve a crisper display.\n            // Now we need to scale down the already trimmed frame to render the texture in the expected size.\n            texture.frame.scale(1 / resolution);\n            texture.updateUvs();\n        }\n\n        if (style.filters)\n        {\n            // apply the filters to the texture if required..\n            // this returns a new texture with the filters applied\n            const filteredTexture = this._applyFilters(texture, style.filters as Filter[]);\n\n            // return the original texture to the pool so we can reuse the next frame\n            this.returnTexture(texture);\n\n            CanvasTextGenerator.returnCanvasAndContext(canvasAndContext);\n\n            // return the new texture with the filters applied\n            return filteredTexture;\n        }\n\n        this._renderer.texture.initSource(texture._source);\n\n        if (!this._retainCanvasContext)\n        {\n            CanvasTextGenerator.returnCanvasAndContext(canvasAndContext);\n        }\n\n        return texture;\n    }\n\n    /**\n     * Returns a texture that was created wit the above `getTexture` function.\n     * Handy if you are done with a texture and want to return it to the pool.\n     * @param texture - The texture to be returned.\n     */\n    public returnTexture(texture: Texture)\n    {\n        const source = texture.source;\n        const resource = source.resource as ICanvas | null;\n\n        if (this._retainCanvasContext && resource?.getContext)\n        {\n            const context = resource.getContext('2d');\n\n            if (context)\n            {\n                CanvasTextGenerator.returnCanvasAndContext({ canvas: resource, context });\n            }\n        }\n\n        source.resource = null;\n        source.uploadMethodId = 'unknown';\n        source.alphaMode = 'no-premultiply-alpha';\n\n        TexturePool.returnTexture(texture, true);\n    }\n\n    /**\n     * Renders text to its canvas, and updates its texture.\n     * @deprecated since 8.10.0\n     */\n    public renderTextToCanvas(): void\n    {\n        // #if _DEBUG\n        deprecation(\n            '8.10.0',\n            'CanvasTextSystem.renderTextToCanvas: no longer supported, use CanvasTextSystem.getTexture instead'\n        );\n        // #endif\n    }\n\n    /**\n     * Gets or creates a managed texture for a Text object. This method handles texture reuse and reference counting.\n     * @param text - The Text object that needs a texture\n     * @returns A Texture instance that represents the rendered text\n     * @remarks\n     * This method performs the following:\n     * 1. Sets the appropriate resolution based on auto-resolution settings\n     * 2. Checks if a texture already exists for the text's style\n     * 3. Creates a new texture if needed or returns an existing one\n     * 4. Manages reference counting for texture reuse\n     */\n    public getManagedTexture(text: Text)\n    {\n        text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;\n        const textKey = text.styleKey;\n\n        if (this._activeTextures[textKey])\n        {\n            this._increaseReferenceCount(textKey);\n\n            return this._activeTextures[textKey].texture;\n        }\n\n        const texture = this.getTexture({\n            text: text.text,\n            style: text.style,\n            resolution: text._resolution,\n            textureStyle: text.textureStyle,\n            autoGenerateMipmaps: text.autoGenerateMipmaps,\n        });\n\n        this._activeTextures[textKey] = {\n            texture,\n            usageCount: 1,\n        };\n\n        return texture;\n    }\n\n    /**\n     * Decreases the reference count for a texture associated with a text key.\n     * When the reference count reaches zero, the texture is returned to the pool.\n     * @param textKey - The unique key identifying the text style configuration\n     * @remarks\n     * This method is crucial for memory management, ensuring textures are properly\n     * cleaned up when they are no longer needed by any Text instances.\n     */\n    public decreaseReferenceCount(textKey: string)\n    {\n        const activeTexture = this._activeTextures[textKey];\n\n        if (!activeTexture) return;\n\n        activeTexture.usageCount--;\n\n        if (activeTexture.usageCount === 0)\n        {\n            this.returnTexture(activeTexture.texture);\n            this._activeTextures[textKey] = null;\n        }\n    }\n\n    /**\n     * Gets the current reference count for a texture associated with a text key.\n     * @param textKey - The unique key identifying the text style configuration\n     * @returns The number of Text instances currently using this texture\n     */\n    public getReferenceCount(textKey: string)\n    {\n        return this._activeTextures[textKey]?.usageCount ?? 0;\n    }\n\n    private _increaseReferenceCount(textKey: string)\n    {\n        this._activeTextures[textKey].usageCount++;\n    }\n\n    /**\n     * Applies the specified filters to the given texture.\n     *\n     * This method takes a texture and a list of filters, applies the filters to the texture,\n     * and returns the resulting texture. It also ensures that the alpha mode of the resulting\n     * texture is set to 'premultiplied-alpha'.\n     * @param {Texture} texture - The texture to which the filters will be applied.\n     * @param {Filter[]} filters - The filters to apply to the texture.\n     * @returns {Texture} The resulting texture after all filters have been applied.\n     */\n    private _applyFilters(texture: Texture, filters: Filter[]): Texture\n    {\n        // Save the current render target so it can be restored later\n        const currentRenderTarget = this._renderer.renderTarget.renderTarget;\n\n        // Apply the filters to the texture and get the resulting texture\n        const resultTexture = this._renderer.filter.generateFilteredTexture({\n            texture,\n            filters,\n        });\n\n        // Restore the previous render target\n        this._renderer.renderTarget.bind(currentRenderTarget, false);\n\n        // Return the resulting texture with the filters applied\n        return resultTexture;\n    }\n\n    public destroy(): void\n    {\n        (this._renderer as null) = null;\n        // Clean up active textures\n        for (const key in this._activeTextures)\n        {\n            if (this._activeTextures[key]) this.returnTexture(this._activeTextures[key].texture);\n        }\n        (this._activeTextures as null) = null;\n    }\n}\n"],"names":[],"mappings":"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"}