{"version":3,"file":"CanvasContextSystem.mjs","sources":["../../../../src/rendering/renderers/canvas/CanvasContextSystem.ts"],"sourcesContent":["import { Color } from '../../../color/Color';\nimport { ExtensionType } from '../../../extensions/Extensions';\nimport { Matrix } from '../../../maths/matrix/Matrix';\nimport { mapCanvasBlendModesToPixi } from './utils/mapCanvasBlendModesToPixi';\n\nimport type { ICanvasRenderingContext2D } from '../../../environment/canvas/ICanvasRenderingContext2D';\nimport type { BLEND_MODES } from '../shared/state/const';\nimport type { System } from '../shared/system/System';\nimport type { CanvasRenderer } from './CanvasRenderer';\n\nconst tempMatrix = new Matrix();\n\n/**\n * Canvas 2D context with vendor image smoothing flags.\n * @internal\n */\nexport interface CrossPlatformCanvasRenderingContext2D extends ICanvasRenderingContext2D\n{\n    /** WebKit-specific image smoothing flag. */\n    webkitImageSmoothingEnabled: boolean;\n    /** Mozilla-specific image smoothing flag. */\n    mozImageSmoothingEnabled: boolean;\n    /** Opera-specific image smoothing flag. */\n    oImageSmoothingEnabled: boolean;\n    /** Microsoft-specific image smoothing flag. */\n    msImageSmoothingEnabled: boolean;\n}\n\n/**\n * Available image smoothing flags for the current context.\n * @internal\n */\nexport type SmoothingEnabledProperties =\n    'imageSmoothingEnabled' |\n    'webkitImageSmoothingEnabled' |\n    'mozImageSmoothingEnabled' |\n    'oImageSmoothingEnabled' |\n    'msImageSmoothingEnabled';\n\n/**\n * Canvas 2D context system for the CanvasRenderer.\n * @category rendering\n * @advanced\n */\nexport class CanvasContextSystem implements System\n{\n    /** @ignore */\n    public static extension = {\n        type: [\n            ExtensionType.CanvasSystem,\n        ],\n        name: 'canvasContext',\n    } as const;\n\n    private readonly _renderer: CanvasRenderer;\n\n    /** Root 2D context tied to the renderer's canvas. */\n    public rootContext: CrossPlatformCanvasRenderingContext2D;\n    /** Active 2D context for rendering (root or render target). */\n    public activeContext: CrossPlatformCanvasRenderingContext2D;\n    /** Resolution of the active context. */\n    public activeResolution = 1;\n\n    /** The image smoothing property to toggle for this browser. */\n    public smoothProperty: SmoothingEnabledProperties = 'imageSmoothingEnabled';\n    /** Map of Pixi blend modes to canvas composite operations. */\n    public readonly blendModes = mapCanvasBlendModesToPixi();\n\n    /** Current canvas blend mode. */\n    public _activeBlendMode: BLEND_MODES = 'normal';\n    /** Optional projection transform for render targets. */\n    public _projTransform: Matrix = null;\n    /** True when external blend mode control is in use. */\n    public _outerBlend = false;\n    /** Tracks unsupported blend mode warnings to avoid spam. */\n    private readonly _warnedBlendModes = new Set<BLEND_MODES>();\n\n    /**\n     * @param renderer - The owning CanvasRenderer.\n     */\n    constructor(renderer: CanvasRenderer)\n    {\n        this._renderer = renderer;\n    }\n\n    protected resolutionChange(resolution: number): void\n    {\n        this.activeResolution = resolution;\n    }\n\n    /** Initializes the root context and smoothing flag selection. */\n    public init(): void\n    {\n        const alpha = this._renderer.background.alpha < 1;\n\n        this.rootContext = this._renderer.canvas.getContext(\n            '2d',\n            { alpha }\n        ) as unknown as CrossPlatformCanvasRenderingContext2D;\n        this.activeContext = this.rootContext;\n        this.activeResolution = this._renderer.resolution;\n\n        if (!this.rootContext.imageSmoothingEnabled)\n        {\n            const rc = this.rootContext;\n\n            if (rc.webkitImageSmoothingEnabled)\n            {\n                this.smoothProperty = 'webkitImageSmoothingEnabled';\n            }\n            else if (rc.mozImageSmoothingEnabled)\n            {\n                this.smoothProperty = 'mozImageSmoothingEnabled';\n            }\n            else if (rc.oImageSmoothingEnabled)\n            {\n                this.smoothProperty = 'oImageSmoothingEnabled';\n            }\n            else if (rc.msImageSmoothingEnabled)\n            {\n                this.smoothProperty = 'msImageSmoothingEnabled';\n            }\n        }\n    }\n\n    /**\n     * Sets the current transform on the active context.\n     * @param transform - Transform to apply.\n     * @param roundPixels - Whether to round translation to integers.\n     * @param localResolution - Optional local resolution multiplier.\n     * @param skipGlobalTransform - If true, skip applying the global world transform matrix.\n     */\n    public setContextTransform(\n        transform: Matrix,\n        roundPixels?: boolean,\n        localResolution?: number,\n        skipGlobalTransform?: boolean\n    ): void\n    {\n        const globalTransform = skipGlobalTransform\n            ? Matrix.IDENTITY\n            : (this._renderer.globalUniforms.globalUniformData?.worldTransformMatrix || Matrix.IDENTITY);\n\n        let mat = tempMatrix;\n\n        mat.copyFrom(globalTransform);\n        mat.append(transform);\n\n        const proj = this._projTransform;\n        const contextResolution = this.activeResolution;\n\n        localResolution = localResolution || contextResolution;\n\n        if (proj)\n        {\n            const finalMat = Matrix.shared;\n\n            finalMat.copyFrom(mat);\n            finalMat.prepend(proj);\n            mat = finalMat;\n        }\n\n        if (roundPixels)\n        {\n            this.activeContext.setTransform(\n                mat.a * localResolution,\n                mat.b * localResolution,\n                mat.c * localResolution,\n                mat.d * localResolution,\n                (mat.tx * contextResolution) | 0,\n                (mat.ty * contextResolution) | 0\n            );\n        }\n        else\n        {\n            this.activeContext.setTransform(\n                mat.a * localResolution,\n                mat.b * localResolution,\n                mat.c * localResolution,\n                mat.d * localResolution,\n                mat.tx * contextResolution,\n                mat.ty * contextResolution\n            );\n        }\n    }\n\n    /**\n     * Clears the current render target, optionally filling with a color.\n     * @param clearColor - Color to fill after clearing.\n     * @param alpha - Alpha override for the clear color.\n     */\n    public clear(clearColor?: number[] | string | number, alpha?: number): void\n    {\n        const context = this.activeContext;\n        const renderer = this._renderer;\n\n        context.clearRect(0, 0, renderer.width, renderer.height);\n\n        if (clearColor)\n        {\n            const color = Color.shared.setValue(clearColor);\n\n            context.globalAlpha = alpha ?? color.alpha;\n            context.fillStyle = color.toHex();\n            context.fillRect(0, 0, renderer.width, renderer.height);\n            context.globalAlpha = 1;\n        }\n    }\n\n    /**\n     * Sets the active blend mode.\n     * @param blendMode - Pixi blend mode.\n     */\n    public setBlendMode(blendMode: BLEND_MODES): void\n    {\n        if (this._activeBlendMode === blendMode) return;\n\n        this._activeBlendMode = blendMode;\n        this._outerBlend = false;\n\n        const mappedBlend = this.blendModes[blendMode];\n\n        if (!mappedBlend)\n        {\n            if (!this._warnedBlendModes.has(blendMode))\n            {\n                console.warn(\n                    `CanvasRenderer: blend mode \"${blendMode}\" is not supported in Canvas2D; falling back to \"source-over\".`\n                );\n                this._warnedBlendModes.add(blendMode);\n            }\n\n            this.activeContext.globalCompositeOperation = 'source-over';\n\n            return;\n        }\n\n        this.activeContext.globalCompositeOperation = mappedBlend;\n    }\n\n    /** Releases context references. */\n    public destroy(): void\n    {\n        this.rootContext = null;\n        this.activeContext = null;\n        this._warnedBlendModes.clear();\n    }\n}\n"],"names":[],"mappings":"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"}