Implement Item#blendMode.

This commit is contained in:
Jonathan Puckey 2011-02-25 12:46:45 +01:00
parent d9b75a7232
commit eddbc25171
7 changed files with 131 additions and 91 deletions

View file

@ -33,7 +33,7 @@ Doc = Base.extend({
// this.canvas.width = this.canvas.width might be faster..
this.ctx.clearRect(0, 0, this.size.width + 1, this.size.height);
for (var i = 0, l = this.layers.length; i < l; i++) {
this.layers[i].draw(this.ctx);
this.layers[i].draw(this.ctx, {});
}
}
}

View file

@ -11,20 +11,24 @@ Group = Item.extend({
this.clipped = false;
},
draw: function(ctx) {
draw: function(ctx, param) {
if (!this.visible)
return;
// If the group has an opacity of less then 1, draw its children on a
// temporary canvas, and then draw that canvas onto ctx afterwards
// with globalAlpha set.
var tempCanvas, originalCtx;
if(this.blendMode != 'normal' && !param.ignoreBlendMode) {
BlendMode.process(ctx, this, param);
} else {
param.ignoreBlendMode = false;
if (this.opacity < 1) {
var originalCtx = ctx;
tempCanvas = CanvasProvider.getCanvas(this.document.size);
ctx = tempCanvas.getContext('2d');
}
for (var i = 0, l = this.children.length; i < l; i++) {
this.children[i].draw(ctx);
this.children[i].draw(ctx, param);
if (this.clipped & i == 0)
ctx.clip();
}
@ -36,6 +40,7 @@ Group = Item.extend({
// Return the canvas, so it can be reused
CanvasProvider.returnCanvas(tempCanvas);
}
}
},
getBounds: function() {

View file

@ -87,6 +87,20 @@ Item = Base.extend({
opacity: 1,
/**
* The blend mode of the item.
*
* Sample code:
* <code>
* var circle = new Path.Circle(new Point(50, 50), 10);
* print(circle.blendMode); // normal
*
* // Change the blend mode of the path item:
* circle.blendMode = 'multiply';
* </code>
*/
blendMode: 'normal',
/**
* Specifies whether the item is hidden.
*
@ -137,7 +151,6 @@ Item = Base.extend({
}
},
// TODO: getBlendMode / setBlendMode
// TODO: getIsolated / setIsolated (print specific feature)
// TODO: get/setKnockout (print specific feature)
// TODO get/setAlphaIsShape

View file

@ -38,13 +38,18 @@ PlacedSymbol = Item.extend({
return this._bounds;
},
draw: function(ctx) {
draw: function(ctx, param) {
if(this.blendMode != 'normal' && !param.ignoreBlendMode) {
BlendMode.process(ctx, this, param);
} else {
param.ignoreBlendMode = false;
// TODO: we need to preserve strokewidth, but still transform the fill
ctx.save();
this.matrix.applyToContext(ctx);
this.symbol.definition.draw(ctx);
ctx.restore();
}
}
// TODO:
// embed()
});

View file

@ -165,13 +165,18 @@ Raster = Item.extend({
return this._bounds;
},
draw: function(ctx) {
draw: function(ctx, param) {
if(this.blendMode != 'normal' && !param.ignoreBlendMode) {
BlendMode.process(ctx, this, param);
} else {
param.ignoreBlendMode = false;
ctx.save();
this.matrix.applyToContext(ctx);
ctx.drawImage(this._canvas || this._image,
-this.size.width / 2, -this.size.height / 2);
ctx.restore();
}
}
}, new function() {
function getAverageColor(pixels) {
var channels = [0, 0, 0];

View file

@ -19,16 +19,21 @@ CompoundPath = PathItem.extend(new function() {
}
},
draw: function(ctx) {
draw: function(ctx, param) {
if(!this.visible)
return;
if (this.children.length) {
if(this.blendMode && !param.ignoreBlendMode) {
BlendMode.process(ctx, this, param);
} else {
var firstChild = this.children[0];
ctx.beginPath();
param.compound = true;
for (var i = 0, l = this.children.length; i < l; i++) {
var child = this.children[i];
child.draw(ctx, true);
child.draw(ctx, param);
}
param.compound = false;
firstChild.setCtxStyles(ctx);
if (firstChild.fillColor) {
ctx.fillStyle = firstChild.fillColor.getCssString();
@ -39,6 +44,7 @@ CompoundPath = PathItem.extend(new function() {
ctx.stroke();
}
}
}
},
// TODO: have getBounds of Group / Layer / CompoundPath use the same

View file

@ -352,9 +352,13 @@ Path = PathItem.extend({
this.closed = ture;
},
draw: function(ctx, compound) {
draw: function(ctx, param) {
if (!this.visible) return;
if (!compound)
if(this.blendMode != 'normal' && !param.ignoreBlendMode) {
BlendMode.process(ctx, this, param);
} else {
param.ignoreBlendMode = false;
if (!param.compound)
ctx.beginPath();
var segments = this._segments;
@ -389,7 +393,7 @@ Path = PathItem.extend({
ctx.bezierCurveTo(outX, outY, handleIn.x + x, handleIn.y + y, x, y);
ctx.closePath();
}
if (!compound) {
if (!param.compound) {
this.setCtxStyles(ctx);
ctx.save();
ctx.globalAlpha = this.opacity;
@ -404,6 +408,8 @@ Path = PathItem.extend({
ctx.restore();
}
}
}
}, new function() { // inject methods that require scoped privates
/**
* Solves a tri-diagonal system for one of coordinates (x or y) of first