{"version":3,"file":"HTMLTextSystem.mjs","sources":["../../../src/scene/text-html/HTMLTextSystem.ts"],"sourcesContent":["import { ExtensionType } from '../../extensions/Extensions';\nimport { TexturePool } from '../../rendering/renderers/shared/texture/TexturePool';\nimport { type Renderer, RendererType } from '../../rendering/renderers/types';\nimport { isSafari } from '../../utils/browser/isSafari';\nimport { warn } from '../../utils/logging/warn';\nimport { BigPool } from '../../utils/pool/PoolGroup';\nimport { getPo2TextureFromSource } from '../text/utils/getPo2TextureFromSource';\nimport { HTMLTextRenderData } from './HTMLTextRenderData';\nimport { HTMLTextStyle } from './HtmlTextStyle';\nimport { extractFontFamilies } from './utils/extractFontFamilies';\nimport { getFontCss } from './utils/getFontCss';\nimport { getSVGUrl } from './utils/getSVGUrl';\nimport { getTemporaryCanvasFromImage } from './utils/getTemporaryCanvasFromImage';\nimport { loadSVGImage } from './utils/loadSVGImage';\nimport { measureHtmlText } from './utils/measureHtmlText';\n\nimport type { System } from '../../rendering/renderers/shared/system/System';\nimport type { Texture } from '../../rendering/renderers/shared/texture/Texture';\nimport type { PoolItem } from '../../utils/pool/Pool';\nimport type { HTMLTextOptions } from './HTMLText';\nimport type { FontCSSStyleOptions } from './utils/loadFontCSS';\n\ninterface HTMLTextTexture\n{\n    texture: Texture,\n    usageCount: number,\n    promise: Promise<Texture>,\n}\n\n/**\n * System plugin to the renderer to manage HTMLText\n * @memberof rendering\n */\nexport class HTMLTextSystem implements System\n{\n    /** @ignore */\n    public static extension = {\n        type: [\n            ExtensionType.WebGLSystem,\n            ExtensionType.WebGPUSystem,\n            ExtensionType.CanvasSystem,\n        ],\n        name: 'htmlText',\n    } as const;\n\n    public static defaultFontOptions: FontCSSStyleOptions = {\n        fontFamily: 'Arial',\n        fontStyle: 'normal',\n        fontWeight: 'normal',\n    };\n\n    private _activeTextures: Record<string, HTMLTextTexture> = {};\n\n    /**\n     * WebGPU has a cors issue when uploading an image that is an SVGImage\n     * To get around this we need to create a canvas draw the image to it and upload that instead.\n     * Bit of a shame.. but no other work around just yet!\n     */\n    private readonly _createCanvas: boolean;\n    private readonly _renderer: Renderer;\n\n    constructor(renderer: Renderer)\n    {\n        this._renderer = renderer;\n        this._createCanvas = renderer.type === RendererType.WEBGPU;\n    }\n\n    public getTexture(options: HTMLTextOptions): Promise<Texture>\n    {\n        return this._buildTexturePromise(\n            options.text as string,\n            options.resolution,\n            options.style as HTMLTextStyle\n        );\n    }\n\n    public getManagedTexture(\n        text: string,\n        resolution: number,\n        style: HTMLTextStyle,\n        textKey: string\n    ): Promise<Texture>\n    {\n        if (this._activeTextures[textKey])\n        {\n            this._increaseReferenceCount(textKey);\n\n            return this._activeTextures[textKey].promise;\n        }\n\n        const promise = this._buildTexturePromise(text, resolution, style)\n            .then((texture) =>\n            {\n                this._activeTextures[textKey].texture = texture;\n\n                return texture;\n            });\n\n        this._activeTextures[textKey] = {\n            texture: null,\n            promise,\n            usageCount: 1,\n        };\n\n        return promise;\n    }\n\n    private async _buildTexturePromise(\n        text: string,\n        resolution: number,\n        style: HTMLTextStyle,\n    )\n    {\n        const htmlTextData = BigPool.get(HTMLTextRenderData);\n        const fontFamilies = extractFontFamilies(text, style);\n        const fontCSS = await getFontCss(\n            fontFamilies,\n            style,\n            HTMLTextStyle.defaultTextStyle as {fontWeight: string, fontStyle: string}\n        );\n        const measured = measureHtmlText(text, style, fontCSS, htmlTextData);\n\n        const width = Math.ceil(Math.ceil((Math.max(1, measured.width) + (style.padding * 2))) * resolution);\n        const height = Math.ceil(Math.ceil((Math.max(1, measured.height) + (style.padding * 2))) * resolution);\n\n        const image = htmlTextData.image;\n\n        // this off set will ensure we don't get any UV bleeding!\n        const uvSafeOffset = 2;\n\n        image.width = (width | 0) + uvSafeOffset;\n        image.height = (height | 0) + uvSafeOffset;\n\n        const svgURL = getSVGUrl(text, style, resolution, fontCSS, htmlTextData);\n\n        await loadSVGImage(image, svgURL, isSafari() && fontFamilies.length > 0);\n\n        let resource: HTMLImageElement | HTMLCanvasElement = image;\n\n        if (this._createCanvas)\n        {\n            // silly webGPU workaround..\n            resource = getTemporaryCanvasFromImage(image, resolution);\n        }\n\n        const texture = getPo2TextureFromSource(resource,\n            image.width - uvSafeOffset,\n            image.height - uvSafeOffset,\n            resolution\n        );\n\n        if (this._createCanvas)\n        {\n            this._renderer.texture.initSource(texture.source);\n        }\n\n        BigPool.return(htmlTextData as PoolItem);\n\n        return texture;\n    }\n\n    private _increaseReferenceCount(textKey: string)\n    {\n        this._activeTextures[textKey].usageCount++;\n    }\n\n    public decreaseReferenceCount(textKey: string)\n    {\n        const activeTexture = this._activeTextures[textKey];\n\n        // TODO SHOULD NOT BE NEEDED\n        if (!activeTexture) return;\n\n        activeTexture.usageCount--;\n\n        if (activeTexture.usageCount === 0)\n        {\n            if (activeTexture.texture)\n            {\n                this._cleanUp(activeTexture);\n            }\n            else\n            {\n                // we did not resolve...\n                activeTexture.promise.then((texture) =>\n                {\n                    activeTexture.texture = texture;\n\n                    this._cleanUp(activeTexture);\n                }).catch(() =>\n                {\n                    // #if _DEBUG\n                    warn('HTMLTextSystem: Failed to clean texture');\n                    // #endif\n                });\n            }\n\n            this._activeTextures[textKey] = null;\n        }\n    }\n\n    private _cleanUp(activeTexture: HTMLTextTexture)\n    {\n        TexturePool.returnTexture(activeTexture.texture);\n        activeTexture.texture.source.resource = null;\n        activeTexture.texture.source.uploadMethodId = 'unknown';\n    }\n\n    public getReferenceCount(textKey: string)\n    {\n        return this._activeTextures[textKey].usageCount;\n    }\n\n    public destroy(): void\n    {\n        this._activeTextures = null;\n    }\n}\n"],"names":[],"mappings":"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"}