{"version":3,"file":"canvasUtils.mjs","sources":["../src/canvasUtils.ts"],"sourcesContent":["import { Color, settings, utils } from '@pixi/core';\nimport { canUseNewCanvasBlendModes } from './utils/canUseNewCanvasBlendModes';\n\nimport type { ICanvas, Texture } from '@pixi/core';\n\n/**\n * Utility methods for Sprite/Texture tinting.\n *\n * Tinting with the CanvasRenderer involves creating a new canvas to use as a texture,\n * so be aware of the performance implications.\n * @namespace PIXI.canvasUtils\n * @memberof PIXI\n */\nexport const canvasUtils = {\n    canvas: null as ICanvas,\n\n    /**\n     * Basically this method just needs a sprite and a color and tints the sprite with the given color.\n     * @memberof PIXI.canvasUtils\n     * @param {PIXI.Sprite} sprite - the sprite to tint\n     * @param sprite.texture\n     * @param {number} color - the color to use to tint the sprite with\n     * @returns {ICanvas|HTMLImageElement} The tinted canvas\n     */\n    getTintedCanvas: (sprite: { texture: Texture }, color: number): ICanvas | HTMLImageElement =>\n    {\n        const texture = sprite.texture;\n        const stringColor = Color.shared.setValue(color).toHex();\n\n        texture.tintCache = texture.tintCache || {};\n\n        const cachedCanvas = texture.tintCache[stringColor];\n\n        let canvas: ICanvas;\n\n        if (cachedCanvas)\n        {\n            if (cachedCanvas.tintId === texture._updateID)\n            {\n                return texture.tintCache[stringColor];\n            }\n\n            canvas = texture.tintCache[stringColor] as ICanvas;\n        }\n        else\n        {\n            canvas = settings.ADAPTER.createCanvas();\n        }\n\n        canvasUtils.tintMethod(texture, color, canvas);\n\n        canvas.tintId = texture._updateID;\n\n        // Convert tint to image only if ICanvas.toDataURL exists (e.g. OffscreenCanvas don't have toDataURL)\n        if (canvasUtils.convertTintToImage && canvas.toDataURL !== undefined)\n        {\n            // is this better?\n            const tintImage = new Image();\n\n            tintImage.src = canvas.toDataURL();\n\n            texture.tintCache[stringColor] = tintImage;\n        }\n        else\n        {\n            texture.tintCache[stringColor] = canvas;\n        }\n\n        return canvas;\n    },\n\n    /**\n     * Basically this method just needs a sprite and a color and tints the sprite with the given color.\n     * @memberof PIXI.canvasUtils\n     * @param {PIXI.Texture} texture - the sprite to tint\n     * @param {number} color - the color to use to tint the sprite with\n     * @returns {CanvasPattern} The tinted canvas\n     */\n    getTintedPattern: (texture: Texture, color: number): CanvasPattern =>\n    {\n        const stringColor = Color.shared.setValue(color).toHex();\n\n        texture.patternCache = texture.patternCache || {};\n\n        let pattern = texture.patternCache[stringColor];\n\n        if (pattern?.tintId === texture._updateID)\n        {\n            return pattern;\n        }\n        if (!canvasUtils.canvas)\n        {\n            canvasUtils.canvas = settings.ADAPTER.createCanvas();\n        }\n        canvasUtils.tintMethod(texture, color, canvasUtils.canvas);\n        pattern = canvasUtils.canvas.getContext('2d').createPattern(canvasUtils.canvas, 'repeat');\n        pattern.tintId = texture._updateID;\n        texture.patternCache[stringColor] = pattern;\n\n        return pattern;\n    },\n\n    /**\n     * Tint a texture using the 'multiply' operation.\n     * @memberof PIXI.canvasUtils\n     * @param {PIXI.Texture} texture - the texture to tint\n     * @param {number} color - the color to use to tint the sprite with\n     * @param {PIXI.ICanvas} canvas - the current canvas\n     */\n    tintWithMultiply: (texture: Texture, color: number, canvas: ICanvas): void =>\n    {\n        const context = canvas.getContext('2d');\n        const crop = texture._frame.clone();\n        const resolution = texture.baseTexture.resolution;\n\n        crop.x *= resolution;\n        crop.y *= resolution;\n        crop.width *= resolution;\n        crop.height *= resolution;\n\n        canvas.width = Math.ceil(crop.width);\n        canvas.height = Math.ceil(crop.height);\n\n        context.save();\n        context.fillStyle = Color.shared.setValue(color).toHex();\n\n        context.fillRect(0, 0, crop.width, crop.height);\n\n        context.globalCompositeOperation = 'multiply';\n\n        const source = texture.baseTexture.getDrawableSource();\n\n        context.drawImage(\n            source,\n            crop.x,\n            crop.y,\n            crop.width,\n            crop.height,\n            0,\n            0,\n            crop.width,\n            crop.height\n        );\n\n        context.globalCompositeOperation = 'destination-atop';\n\n        context.drawImage(\n            source,\n            crop.x,\n            crop.y,\n            crop.width,\n            crop.height,\n            0,\n            0,\n            crop.width,\n            crop.height\n        );\n        context.restore();\n    },\n\n    /**\n     * Tint a texture using the 'overlay' operation.\n     * @memberof PIXI.canvasUtils\n     * @param {PIXI.Texture} texture - the texture to tint\n     * @param {number} color - the color to use to tint the sprite with\n     * @param {PIXI.ICanvas} canvas - the current canvas\n     */\n    tintWithOverlay: (texture: Texture, color: number, canvas: ICanvas): void =>\n    {\n        const context = canvas.getContext('2d');\n        const crop = texture._frame.clone();\n        const resolution = texture.baseTexture.resolution;\n\n        crop.x *= resolution;\n        crop.y *= resolution;\n        crop.width *= resolution;\n        crop.height *= resolution;\n\n        canvas.width = Math.ceil(crop.width);\n        canvas.height = Math.ceil(crop.height);\n\n        context.save();\n        context.globalCompositeOperation = 'copy';\n        context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).slice(-6)}`;\n        context.fillRect(0, 0, crop.width, crop.height);\n\n        context.globalCompositeOperation = 'destination-atop';\n        context.drawImage(\n            texture.baseTexture.getDrawableSource(),\n            crop.x,\n            crop.y,\n            crop.width,\n            crop.height,\n            0,\n            0,\n            crop.width,\n            crop.height\n        );\n\n        // context.globalCompositeOperation = 'copy';\n        context.restore();\n    },\n\n    /**\n     * Tint a texture pixel per pixel.\n     * @memberof PIXI.canvasUtils\n     * @param {PIXI.Texture} texture - the texture to tint\n     * @param {number} color - the color to use to tint the sprite with\n     * @param {PIXI.ICanvas} canvas - the current canvas\n     */\n    tintWithPerPixel: (texture: Texture, color: number, canvas: ICanvas): void =>\n    {\n        const context = canvas.getContext('2d');\n        const crop = texture._frame.clone();\n        const resolution = texture.baseTexture.resolution;\n\n        crop.x *= resolution;\n        crop.y *= resolution;\n        crop.width *= resolution;\n        crop.height *= resolution;\n\n        canvas.width = Math.ceil(crop.width);\n        canvas.height = Math.ceil(crop.height);\n\n        context.save();\n        context.globalCompositeOperation = 'copy';\n        context.drawImage(\n            texture.baseTexture.getDrawableSource(),\n            crop.x,\n            crop.y,\n            crop.width,\n            crop.height,\n            0,\n            0,\n            crop.width,\n            crop.height\n        );\n        context.restore();\n\n        const [r, g, b] = Color.shared.setValue(color).toArray();\n        const pixelData = context.getImageData(0, 0, crop.width, crop.height);\n\n        const pixels = pixelData.data;\n\n        for (let i = 0; i < pixels.length; i += 4)\n        {\n            pixels[i + 0] *= r;\n            pixels[i + 1] *= g;\n            pixels[i + 2] *= b;\n        }\n\n        context.putImageData(pixelData, 0, 0);\n    },\n\n    /**\n     * Rounds the specified color according to the canvasUtils.cacheStepsPerColorChannel.\n     * @memberof PIXI.canvasUtils\n     * @deprecated since 7.3.0\n     * @see PIXI.Color.round\n     * @param {number} color - the color to round, should be a hex color\n     * @returns {number} The rounded color.\n     */\n    roundColor: (color: number): number =>\n    {\n        if (process.env.DEBUG)\n        {\n            utils.deprecation('7.3.0', 'PIXI.canvasUtils.roundColor is deprecated');\n        }\n\n        return Color.shared\n            .setValue(color)\n            .round(canvasUtils.cacheStepsPerColorChannel)\n            .toNumber();\n    },\n\n    /**\n     * Number of steps which will be used as a cap when rounding colors.\n     * @memberof PIXI.canvasUtils\n     * @deprecated since 7.3.0\n     * @type {number}\n     */\n    cacheStepsPerColorChannel: 8,\n\n    /**\n     * Tint cache boolean flag.\n     * @memberof PIXI.canvasUtils\n     * @type {boolean}\n     */\n    convertTintToImage: false,\n\n    /**\n     * Whether or not the Canvas BlendModes are supported, consequently the ability to tint using the multiply method.\n     * @memberof PIXI.canvasUtils\n     * @type {boolean}\n     */\n    canUseMultiply: canUseNewCanvasBlendModes(),\n\n    /**\n     * The tinting method that will be used.\n     * @memberof PIXI.canvasUtils\n     * @type {Function}\n     */\n    tintMethod: null as (texture: Texture, color: number, canvas: ICanvas) => void,\n};\n\ncanvasUtils.tintMethod = canvasUtils.canUseMultiply ? canvasUtils.tintWithMultiply : canvasUtils.tintWithPerPixel;\n"],"names":[],"mappings":";;AAaO,MAAM,cAAc;AAAA,EACvB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUR,iBAAiB,CAAC,QAA8B,UAChD;AACU,UAAA,UAAU,OAAO,SACjB,cAAc,MAAM,OAAO,SAAS,KAAK,EAAE;AAEzC,YAAA,YAAY,QAAQ,aAAa,CAAA;AAEnC,UAAA,eAAe,QAAQ,UAAU,WAAW;AAE9C,QAAA;AAEJ,QAAI,cACJ;AACQ,UAAA,aAAa,WAAW,QAAQ;AAEzB,eAAA,QAAQ,UAAU,WAAW;AAG/B,eAAA,QAAQ,UAAU,WAAW;AAAA,IAC1C;AAGa,eAAA,SAAS,QAAQ;AAQ9B,QALA,YAAY,WAAW,SAAS,OAAO,MAAM,GAE7C,OAAO,SAAS,QAAQ,WAGpB,YAAY,sBAAsB,OAAO,cAAc,QAC3D;AAEU,YAAA,YAAY,IAAI;AAEtB,gBAAU,MAAM,OAAO,UAAA,GAEvB,QAAQ,UAAU,WAAW,IAAI;AAAA,IACrC;AAGY,cAAA,UAAU,WAAW,IAAI;AAG9B,WAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAkB,CAAC,SAAkB,UACrC;AACI,UAAM,cAAc,MAAM,OAAO,SAAS,KAAK,EAAE;AAEzC,YAAA,eAAe,QAAQ,gBAAgB,CAAA;AAE3C,QAAA,UAAU,QAAQ,aAAa,WAAW;AAE9C,WAAI,SAAS,WAAW,QAAQ,cAI3B,YAAY,WAEb,YAAY,SAAS,SAAS,QAAQ,iBAE1C,YAAY,WAAW,SAAS,OAAO,YAAY,MAAM,GACzD,UAAU,YAAY,OAAO,WAAW,IAAI,EAAE,cAAc,YAAY,QAAQ,QAAQ,GACxF,QAAQ,SAAS,QAAQ,WACzB,QAAQ,aAAa,WAAW,IAAI,UAE7B;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAkB,CAAC,SAAkB,OAAe,WACpD;AACI,UAAM,UAAU,OAAO,WAAW,IAAI,GAChC,OAAO,QAAQ,OAAO,MAAM,GAC5B,aAAa,QAAQ,YAAY;AAElC,SAAA,KAAK,YACV,KAAK,KAAK,YACV,KAAK,SAAS,YACd,KAAK,UAAU,YAEf,OAAO,QAAQ,KAAK,KAAK,KAAK,KAAK,GACnC,OAAO,SAAS,KAAK,KAAK,KAAK,MAAM,GAErC,QAAQ,KACR,GAAA,QAAQ,YAAY,MAAM,OAAO,SAAS,KAAK,EAAE,MAAA,GAEjD,QAAQ,SAAS,GAAG,GAAG,KAAK,OAAO,KAAK,MAAM,GAE9C,QAAQ,2BAA2B;AAE7B,UAAA,SAAS,QAAQ,YAAY,kBAAkB;AAE7C,YAAA;AAAA,MACJ;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IAGT,GAAA,QAAQ,2BAA2B,oBAEnC,QAAQ;AAAA,MACJ;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IAAA,GAET,QAAQ;EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAAiB,CAAC,SAAkB,OAAe,WACnD;AACI,UAAM,UAAU,OAAO,WAAW,IAAI,GAChC,OAAO,QAAQ,OAAO,MAAM,GAC5B,aAAa,QAAQ,YAAY;AAElC,SAAA,KAAK,YACV,KAAK,KAAK,YACV,KAAK,SAAS,YACd,KAAK,UAAU,YAEf,OAAO,QAAQ,KAAK,KAAK,KAAK,KAAK,GACnC,OAAO,SAAS,KAAK,KAAK,KAAK,MAAM,GAErC,QAAQ,KAAK,GACb,QAAQ,2BAA2B,QACnC,QAAQ,YAAY,IAAK,SAAS,QAAQ,GAAG,SAAS,EAAE,CAAC,GAAI,MAAM,EAAE,CAAC,IACtE,QAAQ,SAAS,GAAG,GAAG,KAAK,OAAO,KAAK,MAAM,GAE9C,QAAQ,2BAA2B,oBACnC,QAAQ;AAAA,MACJ,QAAQ,YAAY,kBAAkB;AAAA,MACtC,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IAAA,GAIT,QAAQ;EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAkB,CAAC,SAAkB,OAAe,WACpD;AACI,UAAM,UAAU,OAAO,WAAW,IAAI,GAChC,OAAO,QAAQ,OAAO,MAAM,GAC5B,aAAa,QAAQ,YAAY;AAEvC,SAAK,KAAK,YACV,KAAK,KAAK,YACV,KAAK,SAAS,YACd,KAAK,UAAU,YAEf,OAAO,QAAQ,KAAK,KAAK,KAAK,KAAK,GACnC,OAAO,SAAS,KAAK,KAAK,KAAK,MAAM,GAErC,QAAQ,KAAK,GACb,QAAQ,2BAA2B,QACnC,QAAQ;AAAA,MACJ,QAAQ,YAAY,kBAAkB;AAAA,MACtC,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IAAA,GAET,QAAQ;AAEF,UAAA,CAAC,GAAG,GAAG,CAAC,IAAI,MAAM,OAAO,SAAS,KAAK,EAAE,WACzC,YAAY,QAAQ,aAAa,GAAG,GAAG,KAAK,OAAO,KAAK,MAAM,GAE9D,SAAS,UAAU;AAEzB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AAEpC,aAAO,IAAI,CAAC,KAAK,GACjB,OAAO,IAAI,CAAC,KAAK,GACjB,OAAO,IAAI,CAAC,KAAK;AAGb,YAAA,aAAa,WAAW,GAAG,CAAC;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,YAAY,CAAC,WAIL,MAAM,YAAY,SAAS,2CAA2C,GAGnE,MAAM,OACR,SAAS,KAAK,EACd,MAAM,YAAY,yBAAyB,EAC3C;;;;;;;EAST,2BAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO3B,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpB,gBAAgB,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1C,YAAY;AAChB;AAEA,YAAY,aAAa,YAAY,iBAAiB,YAAY,mBAAmB,YAAY;"}