/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* @class CanvasTinter
* @constructor
* @static
*/
PIXI.CanvasTinter = function()
{
};
/**
* Basically this method just needs a sprite and a color and tints the sprite with the given color.
*
* @method getTintedTexture
* @param sprite {Sprite} the sprite to tint
* @param color {Number} the color to use to tint the sprite with
* @return {HTMLCanvasElement} The tinted canvas
*/
PIXI.CanvasTinter.getTintedTexture = function(sprite, color)
{
var texture = sprite.texture;
color = PIXI.CanvasTinter.roundColor(color);
var stringColor = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
texture.tintCache = texture.tintCache || {};
if(texture.tintCache[stringColor]) return texture.tintCache[stringColor];
// clone texture..
var canvas = PIXI.CanvasTinter.canvas || document.createElement("canvas");
//PIXI.CanvasTinter.tintWithPerPixel(texture, stringColor, canvas);
PIXI.CanvasTinter.tintMethod(texture, color, canvas);
if(PIXI.CanvasTinter.convertTintToImage)
{
// is this better?
var tintImage = new Image();
tintImage.src = canvas.toDataURL();
texture.tintCache[stringColor] = tintImage;
}
else
{
texture.tintCache[stringColor] = canvas;
// if we are not converting the texture to an image then we need to lose the reference to the canvas
PIXI.CanvasTinter.canvas = null;
}
return canvas;
};
/**
* Tint a texture using the "multiply" operation.
*
* @method tintWithMultiply
* @param texture {Texture} the texture to tint
* @param color {Number} the color to use to tint the sprite with
* @param canvas {HTMLCanvasElement} the current canvas
*/
PIXI.CanvasTinter.tintWithMultiply = function(texture, color, canvas)
{
var context = canvas.getContext( "2d" );
var crop = texture.crop;
canvas.width = crop.width;
canvas.height = crop.height;
context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
context.fillRect(0, 0, crop.width, crop.height);
context.globalCompositeOperation = "multiply";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
context.globalCompositeOperation = "destination-atop";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
};
/**
* Tint a texture using the "overlay" operation.
*
* @method tintWithOverlay
* @param texture {Texture} the texture to tint
* @param color {Number} the color to use to tint the sprite with
* @param canvas {HTMLCanvasElement} the current canvas
*/
PIXI.CanvasTinter.tintWithOverlay = function(texture, color, canvas)
{
var context = canvas.getContext( "2d" );
var crop = texture.crop;
canvas.width = crop.width;
canvas.height = crop.height;
context.globalCompositeOperation = "copy";
context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
context.fillRect(0, 0, crop.width, crop.height);
context.globalCompositeOperation = "destination-atop";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
//context.globalCompositeOperation = "copy";
};
/**
* Tint a texture pixel per pixel.
*
* @method tintPerPixel
* @param texture {Texture} the texture to tint
* @param color {Number} the color to use to tint the sprite with
* @param canvas {HTMLCanvasElement} the current canvas
*/
PIXI.CanvasTinter.tintWithPerPixel = function(texture, color, canvas)
{
var context = canvas.getContext( "2d" );
var crop = texture.crop;
canvas.width = crop.width;
canvas.height = crop.height;
context.globalCompositeOperation = "copy";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
var rgbValues = PIXI.hex2rgb(color);
var r = rgbValues[0], g = rgbValues[1], b = rgbValues[2];
var pixelData = context.getImageData(0, 0, crop.width, crop.height);
var pixels = pixelData.data;
for (var i = 0; i < pixels.length; i += 4)
{
pixels[i+0] *= r;
pixels[i+1] *= g;
pixels[i+2] *= b;
}
context.putImageData(pixelData, 0, 0);
};
/**
* Rounds the specified color according to the PIXI.CanvasTinter.cacheStepsPerColorChannel.
*
* @method roundColor
* @param color {number} the color to round, should be a hex color
*/
PIXI.CanvasTinter.roundColor = function(color)
{
var step = PIXI.CanvasTinter.cacheStepsPerColorChannel;
var rgbValues = PIXI.hex2rgb(color);
rgbValues[0] = Math.min(255, (rgbValues[0] / step) * step);
rgbValues[1] = Math.min(255, (rgbValues[1] / step) * step);
rgbValues[2] = Math.min(255, (rgbValues[2] / step) * step);
return PIXI.rgb2hex(rgbValues);
};
/**
* Number of steps which will be used as a cap when rounding colors.
*
* @property cacheStepsPerColorChannel
* @type Number
*/
PIXI.CanvasTinter.cacheStepsPerColorChannel = 8;
/**
* Tint cache boolean flag.
*
* @property convertTintToImage
* @type Boolean
*/
PIXI.CanvasTinter.convertTintToImage = false;
/**
* Whether or not the Canvas BlendModes are supported, consequently the ability to tint using the multiply method.
*
* @property canUseMultiply
* @type Boolean
*/
PIXI.CanvasTinter.canUseMultiply = PIXI.canUseNewCanvasBlendModes();
/**
* The tinting method that will be used.
*
* @method tintMethod
*/
PIXI.CanvasTinter.tintMethod = PIXI.CanvasTinter.canUseMultiply ? PIXI.CanvasTinter.tintWithMultiply : PIXI.CanvasTinter.tintWithPerPixel;