Add support for native blend-modes.

Already works on Firefox 21.0 and will soon land on other major browsers!
This commit is contained in:
Jürg Lehni 2013-06-18 11:17:15 -07:00
parent 8cf09c08d9
commit c48ab03050

View file

@ -215,15 +215,41 @@ var BlendMode = new function() {
} }
}; };
// Build a lookup table for natively supported blend-modes (on browsers)
// where the CSS blend-modes are supported. Just check for
// globalCompositeOperation to actually be sticky is not enough, since
// Chome 27 pretends for them to work, but does not apply the modes.
var ctx = CanvasProvider.getContext(1, 1);
// Multiply #300 (51) and #a00 (170) and see if we get #200 (34)
ctx.fillStyle = '#300';
ctx.fillRect(0, 0, 1, 1);
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = '#a00';
ctx.fillRect(0, 0, 1, 1);
var data = ctx.getImageData(0, 0, 1, 1).data;
// If data[0] is 34, the mode has worked. Now feature detect all modes that
// the browser claims to support.
this.nativeModes = data[0] === 34 && Base.each(modes, function(func, mode) {
ctx.globalCompositeOperation = mode;
this[mode] = ctx.globalCompositeOperation === mode;
}, {});
CanvasProvider.release(ctx);
this.process = function(blendMode, srcContext, dstContext, alpha, offset) { this.process = function(blendMode, srcContext, dstContext, alpha, offset) {
var srcCanvas = srcContext.canvas, var srcCanvas = srcContext.canvas;
dstData = dstContext.getImageData(offset.x, offset.y, // Use native blend-modes if supported, and fall back to emulation.
if (this.nativeModes[blendMode]) {
dstContext.save();
dstContext.globalCompositeOperation = blendMode;
dstContext.drawImage(srcCanvas, offset.x, offset.y);
dstContext.restore();
} else {
var dstData = dstContext.getImageData(offset.x, offset.y,
srcCanvas.width, srcCanvas.height), srcCanvas.width, srcCanvas.height),
dst = dstData.data, dst = dstData.data,
src = srcContext.getImageData(0, 0, src = srcContext.getImageData(0, 0,
srcCanvas.width, srcCanvas.height).data; srcCanvas.width, srcCanvas.height).data;
var process = modes[blendMode]; var process = modes[blendMode];
if (!process) if (!process)
return; return;
@ -246,5 +272,6 @@ var BlendMode = new function() {
dst[i + 3] = sa * alpha + a2 * ba; dst[i + 3] = sa * alpha + a2 * ba;
} }
dstContext.putImageData(dstData, offset.x, offset.y); dstContext.putImageData(dstData, offset.x, offset.y);
}
}; };
}; };