{"version":3,"file":"BitmapTextPipe.mjs","sources":["../../../src/scene/text-bitmap/BitmapTextPipe.ts"],"sourcesContent":["import { Cache } from '../../assets/cache/Cache';\nimport { ExtensionType } from '../../extensions/Extensions';\nimport { BigPool } from '../../utils/pool/PoolGroup';\nimport { Graphics } from '../graphics/shared/Graphics';\nimport { SdfShader } from '../text/sdfShader/SdfShader';\nimport { BitmapFontManager } from './BitmapFontManager';\nimport { getBitmapTextLayout } from './utils/getBitmapTextLayout';\n\nimport type { InstructionSet } from '../../rendering/renderers/shared/instructions/InstructionSet';\nimport type { RenderPipe } from '../../rendering/renderers/shared/instructions/RenderPipe';\nimport type { Renderable } from '../../rendering/renderers/shared/Renderable';\nimport type { Renderer } from '../../rendering/renderers/types';\nimport type { PoolItem } from '../../utils/pool/Pool';\nimport type { Container } from '../container/Container';\nimport type { BitmapText } from './BitmapText';\n\nexport class BitmapTextPipe implements RenderPipe<BitmapText>\n{\n    /** @ignore */\n    public static extension = {\n        type: [\n            ExtensionType.WebGLPipes,\n            ExtensionType.WebGPUPipes,\n            ExtensionType.CanvasPipes,\n        ],\n        name: 'bitmapText',\n    } as const;\n\n    private _renderer: Renderer;\n    private _gpuBitmapText: Record<number, Graphics> = {};\n    private readonly _destroyRenderableBound = this.destroyRenderable.bind(this) as (renderable: Container) => void;\n\n    constructor(renderer: Renderer)\n    {\n        this._renderer = renderer;\n    }\n\n    public validateRenderable(bitmapText: BitmapText): boolean\n    {\n        const graphicsRenderable = this._getGpuBitmapText(bitmapText);\n\n        if (bitmapText._didTextUpdate)\n        {\n            bitmapText._didTextUpdate = false;\n\n            this._updateContext(bitmapText, graphicsRenderable);\n        }\n\n        return this._renderer.renderPipes.graphics.validateRenderable(graphicsRenderable);\n\n        // TODO - need to shift all the verts in the graphicsData to the new anchor\n\n        // update the anchor...\n    }\n\n    public addRenderable(bitmapText: BitmapText, instructionSet: InstructionSet)\n    {\n        const graphicsRenderable = this._getGpuBitmapText(bitmapText);\n\n        // sync..\n        syncWithProxy(bitmapText, graphicsRenderable);\n\n        if (bitmapText._didTextUpdate)\n        {\n            bitmapText._didTextUpdate = false;\n\n            this._updateContext(bitmapText, graphicsRenderable);\n        }\n\n        this._renderer.renderPipes.graphics.addRenderable(graphicsRenderable, instructionSet);\n\n        if (graphicsRenderable.context.customShader)\n        {\n            this._updateDistanceField(bitmapText);\n        }\n    }\n\n    public destroyRenderable(bitmapText: BitmapText)\n    {\n        bitmapText.off('destroyed', this._destroyRenderableBound);\n\n        this._destroyRenderableByUid(bitmapText.uid);\n    }\n\n    private _destroyRenderableByUid(renderableUid: number)\n    {\n        const context = this._gpuBitmapText[renderableUid].context;\n\n        if (context.customShader)\n        {\n            BigPool.return(context.customShader as PoolItem);\n\n            context.customShader = null;\n        }\n\n        BigPool.return(this._gpuBitmapText[renderableUid] as PoolItem);\n        this._gpuBitmapText[renderableUid] = null;\n    }\n\n    public updateRenderable(bitmapText: BitmapText)\n    {\n        const graphicsRenderable = this._getGpuBitmapText(bitmapText);\n\n        // sync..\n        syncWithProxy(bitmapText, graphicsRenderable);\n\n        this._renderer.renderPipes.graphics.updateRenderable(graphicsRenderable);\n\n        if (graphicsRenderable.context.customShader)\n        {\n            this._updateDistanceField(bitmapText);\n        }\n    }\n\n    private _updateContext(bitmapText: BitmapText, proxyGraphics: Graphics)\n    {\n        const { context } = proxyGraphics;\n\n        const bitmapFont = BitmapFontManager.getFont(bitmapText.text, bitmapText._style);\n\n        context.clear();\n\n        if (bitmapFont.distanceField.type !== 'none')\n        {\n            if (!context.customShader)\n            {\n                context.customShader = BigPool.get(SdfShader);\n            }\n        }\n\n        const chars = Array.from(bitmapText.text);\n        const style = bitmapText._style;\n\n        let currentY = bitmapFont.baseLineOffset;\n\n        // measure our text...\n        const bitmapTextLayout = getBitmapTextLayout(chars, style, bitmapFont);\n\n        let index = 0;\n\n        const padding = style.padding;\n        const scale = bitmapTextLayout.scale;\n\n        let tx = bitmapTextLayout.width;\n        let ty = bitmapTextLayout.height + bitmapTextLayout.offsetY;\n\n        if (style._stroke)\n        {\n            tx += style._stroke.width / scale;\n            ty += style._stroke.width / scale;\n        }\n\n        context\n            .translate((-bitmapText._anchor._x * tx) - padding, (-bitmapText._anchor._y * ty) - padding)\n            .scale(scale, scale);\n\n        const tint = bitmapFont.applyFillAsTint ? style._fill.color : 0xFFFFFF;\n\n        for (let i = 0; i < bitmapTextLayout.lines.length; i++)\n        {\n            const line = bitmapTextLayout.lines[i];\n\n            for (let j = 0; j < line.charPositions.length; j++)\n            {\n                const char = chars[index++];\n\n                const charData = bitmapFont.chars[char];\n\n                if (charData?.texture)\n                {\n                    context.texture(\n                        charData.texture,\n                        tint ? tint : 'black',\n                        Math.round(line.charPositions[j] + charData.xOffset),\n                        Math.round(currentY + charData.yOffset),\n                    );\n                }\n            }\n\n            currentY += bitmapFont.lineHeight;\n        }\n    }\n\n    private _getGpuBitmapText(bitmapText: BitmapText)\n    {\n        return this._gpuBitmapText[bitmapText.uid] || this.initGpuText(bitmapText);\n    }\n\n    public initGpuText(bitmapText: BitmapText)\n    {\n        // TODO we could keep a bunch of contexts around and reuse one that has the same style!\n        const proxyRenderable = BigPool.get(Graphics);\n\n        this._gpuBitmapText[bitmapText.uid] = proxyRenderable;\n\n        this._updateContext(bitmapText, proxyRenderable);\n\n        bitmapText.on('destroyed', this._destroyRenderableBound);\n\n        return this._gpuBitmapText[bitmapText.uid];\n    }\n\n    private _updateDistanceField(bitmapText: BitmapText)\n    {\n        const context = this._getGpuBitmapText(bitmapText).context;\n\n        const fontFamily = bitmapText._style.fontFamily as string;\n        const dynamicFont = Cache.get(`${fontFamily as string}-bitmap`);\n\n        // Inject the shader code with the correct value\n        const { a, b, c, d } = bitmapText.groupTransform;\n\n        const dx = Math.sqrt((a * a) + (b * b));\n        const dy = Math.sqrt((c * c) + (d * d));\n        const worldScale = (Math.abs(dx) + Math.abs(dy)) / 2;\n\n        const fontScale = dynamicFont.baseRenderedFontSize / bitmapText._style.fontSize;\n\n        const distance = worldScale * dynamicFont.distanceField.range * (1 / fontScale);\n\n        context.customShader.resources.localUniforms.uniforms.uDistance = distance;\n    }\n\n    public destroy()\n    {\n        for (const uid in this._gpuBitmapText)\n        {\n            this._destroyRenderableByUid(uid as unknown as number);\n        }\n\n        this._gpuBitmapText = null;\n\n        this._renderer = null;\n    }\n}\n\nfunction syncWithProxy(container: Renderable, proxy: Renderable)\n{\n    proxy.groupTransform = container.groupTransform;\n    proxy.groupColorAlpha = container.groupColorAlpha;\n    proxy.groupColor = container.groupColor;\n    proxy.groupBlendMode = container.groupBlendMode;\n    proxy.globalDisplayStatus = container.globalDisplayStatus;\n    proxy.groupTransform = container.groupTransform;\n    proxy.localDisplayStatus = container.localDisplayStatus;\n    proxy.groupAlpha = container.groupAlpha;\n    proxy._roundPixels = container._roundPixels;\n}\n"],"names":[],"mappings":"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"}