mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -05:00
Implement BlendMode class.
This commit is contained in:
parent
d9b75a7232
commit
c9d04d33f8
8 changed files with 625 additions and 91 deletions
|
@ -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, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
494
src/item/BlendMode.js
Normal file
494
src/item/BlendMode.js
Normal file
|
@ -0,0 +1,494 @@
|
|||
/*
|
||||
* BlendMode code ported from Pixastic Lib - Blend - v0.1.1
|
||||
* Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
|
||||
* License: [http://www.pixastic.com/lib/license.txt]
|
||||
*/
|
||||
|
||||
BlendMode = {
|
||||
// TODO: Should we remove some of the blend modes?
|
||||
// TODO: Add missing blendmodes like hue / saturation.
|
||||
process: function(documentContext, item, param) {
|
||||
var itemBounds = item.bounds;
|
||||
var top = Math.floor(itemBounds.top);
|
||||
var left = Math.floor(itemBounds.left);
|
||||
var size = itemBounds.size.ceil();
|
||||
var width = size.width;
|
||||
var height = size.height;
|
||||
|
||||
var itemCanvas = CanvasProvider.getCanvas(size);
|
||||
var itemContext = itemCanvas.getContext('2d');
|
||||
itemContext.translate(-itemBounds.left, -itemBounds.top);
|
||||
param.ignoreBlendMode = true;
|
||||
item.draw(itemContext, param);
|
||||
|
||||
var data = documentContext.getImageData(
|
||||
left, top,
|
||||
width, height
|
||||
).data;
|
||||
|
||||
var dataDesc2 = itemContext.getImageData(
|
||||
0, 0,
|
||||
width, height
|
||||
);
|
||||
var data2 = dataDesc2.data;
|
||||
var p = size.width * size.height;
|
||||
var pix = p * 4;
|
||||
var pix1, pix2;
|
||||
var r1, g1, b1;
|
||||
var r2, g2, b2;
|
||||
var r3, g3, b3;
|
||||
var r4, g4, b4;
|
||||
|
||||
switch (item.blendMode) {
|
||||
case 'normal' :
|
||||
break;
|
||||
|
||||
case 'multiply' :
|
||||
while (p--) {
|
||||
data2[pix -= 4] = data[pix] * data2[pix] / 255;
|
||||
data2[pix1 = pix + 1] = data[pix1] * data2[pix1] / 255;
|
||||
data2[pix2 = pix + 2] = data[pix2] * data2[pix2] / 255;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'lighten' :
|
||||
while (p--) {
|
||||
if ((r1 = data[pix -= 4]) > data2[pix])
|
||||
data2[pix] = r1;
|
||||
if ((g1 = data[pix1 = pix + 1]) > data2[pix1])
|
||||
data2[pix1] = g1;
|
||||
if ((b1 = data[pix2 = pix + 2]) > data2[pix2])
|
||||
data2[pix2] = b1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'darken' :
|
||||
while (p--) {
|
||||
if ((r1 = data[pix -= 4]) < data2[pix])
|
||||
data2[pix] = r1;
|
||||
if ((g1 = data[pix1 = pix + 1]) < data2[pix1])
|
||||
data2[pix1] = g1;
|
||||
if ((b1 = data[pix2 = pix + 2]) < data2[pix2])
|
||||
data2[pix2] = b1;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'darker-color' :
|
||||
while (p--) {
|
||||
if (((r1 = data[pix -= 4]) * 0.3
|
||||
+ (g1 = data[pix1 = pix + 1]) * 0.59
|
||||
+ (b1 = data[pix2 = pix + 2]) * 0.11)
|
||||
<= (data2[pix] * 0.3 + data2[pix1] * 0.59
|
||||
+ data2[pix2] * 0.11)) {
|
||||
data2[pix] = r1;
|
||||
data2[pix1] = g1;
|
||||
data2[pix2] = b1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'lighter-color' :
|
||||
while (p--) {
|
||||
if (((r1 = data[pix -= 4]) * 0.3
|
||||
+ (g1 = data[pix1 = pix + 1])
|
||||
* 0.59 + (b1 = data[pix2 = pix + 2]) * 0.11)
|
||||
> (data2[pix] * 0.3 + data2[pix1] * 0.59
|
||||
+ data2[pix2] * 0.11)) {
|
||||
data2[pix] = r1;
|
||||
data2[pix1] = g1;
|
||||
data2[pix2] = b1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'linear-dodge' :
|
||||
/*
|
||||
otherdocumentContext.globalCompositeOperation = 'source-over';
|
||||
otherdocumentContext.drawImage(params.canvas, 0, 0);
|
||||
otherdocumentContext.globalCompositeOperation = 'lighter';
|
||||
otherdocumentContext.drawImage(image, 0, 0);
|
||||
*/
|
||||
|
||||
while (p--) {
|
||||
if ((r3 = data[pix -= 4] + data2[pix]) > 255)
|
||||
data2[pix] = 255;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
if ((g3 = data[pix1 = pix + 1] + data2[pix1]) > 255)
|
||||
data2[pix1] = 255;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
if ((b3 = data[pix2 = pix + 2] + data2[pix2]) > 255)
|
||||
data2[pix2] = 255;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'linear-burn' :
|
||||
while (p--) {
|
||||
if ((r3 = data[pix -= 4] + data2[pix]) < 255)
|
||||
data2[pix] = 0;
|
||||
else
|
||||
data2[pix] = (r3 - 255);
|
||||
if ((g3 = data[pix1 = pix + 1] + data2[pix1]) < 255)
|
||||
data2[pix1] = 0;
|
||||
else
|
||||
data2[pix1] = (g3 - 255);
|
||||
if ((b3 = data[pix2 = pix + 2] + data2[pix2]) < 255)
|
||||
data2[pix2] = 0;
|
||||
else
|
||||
data2[pix2] = (b3 - 255);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'difference' :
|
||||
while (p--) {
|
||||
if ((r3 = data[pix -= 4] - data2[pix]) < 0)
|
||||
data2[pix] = -r3;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
if ((g3 = data[pix1 = pix + 1] - data2[pix1]) < 0)
|
||||
data2[pix1] = -g3;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
if ((b3 = data[pix2 = pix + 2] - data2[pix2]) < 0)
|
||||
data2[pix2] = -b3;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'screen' :
|
||||
while (p--) {
|
||||
data2[pix -= 4] = (255 - (((255 - data2[pix])
|
||||
* (255 - data[pix])) >> 8));
|
||||
data2[pix1 = pix + 1] = (255 - (((255 - data2[pix1])
|
||||
* (255 - data[pix1])) >> 8));
|
||||
data2[pix2 = pix + 2] = (255 - (((255 - data2[pix2])
|
||||
* (255 - data[pix2])) >> 8));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'exclusion' :
|
||||
var div_2_255 = 2 / 255;
|
||||
while (p--) {
|
||||
data2[pix -= 4] = (r1 = data[pix])
|
||||
- (r1 * div_2_255 - 1) * data2[pix];
|
||||
data2[pix1 = pix + 1] = (g1 = data[pix1])
|
||||
- (g1 * div_2_255 - 1) * data2[pix1];
|
||||
data2[pix2 = pix + 2] = (b1 = data[pix2])
|
||||
- (b1 * div_2_255 - 1) * data2[pix2];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'overlay' :
|
||||
var div_2_255 = 2 / 255;
|
||||
while (p--) {
|
||||
if ((r1 = data[pix -= 4]) < 128)
|
||||
data2[pix] = data2[pix] * r1 * div_2_255;
|
||||
else
|
||||
data2[pix] = 255 - (255 - data2[pix]) * (255 - r1)
|
||||
* div_2_255;
|
||||
|
||||
if ((g1 = data[pix1 = pix + 1]) < 128)
|
||||
data2[pix1] = data2[pix1] * g1 * div_2_255;
|
||||
else
|
||||
data2[pix1] = 255 - (255 - data2[pix1]) * (255 - g1)
|
||||
* div_2_255;
|
||||
|
||||
if ((b1 = data[pix2 = pix + 2]) < 128)
|
||||
data2[pix2] = data2[pix2] * b1 * div_2_255;
|
||||
else
|
||||
data2[pix2] = 255 - (255 - data2[pix2]) * (255 - b1)
|
||||
* div_2_255;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'soft-light' :
|
||||
var div_2_255 = 2 / 255;
|
||||
while (p--) {
|
||||
if ((r1 = data[pix -= 4]) < 128)
|
||||
data2[pix] = ((data2[pix] >> 1) + 64) * r1 * div_2_255;
|
||||
else
|
||||
data2[pix] = 255 - (191 - (data2[pix] >> 1))
|
||||
* (255 - r1) * div_2_255;
|
||||
|
||||
if ((g1 = data[pix1 = pix + 1]) < 128)
|
||||
data2[pix1] = ((data2[pix1] >> 1) + 64) * g1 * div_2_255;
|
||||
else
|
||||
data2[pix1] = 255 - (191 - (data2[pix1] >> 1))
|
||||
* (255 - g1) * div_2_255;
|
||||
|
||||
if ((b1 = data[pix2 = pix + 2]) < 128)
|
||||
data2[pix2] = ((data2[pix2] >> 1) + 64) * b1 * div_2_255;
|
||||
else
|
||||
data2[pix2] = 255 - (191 - (data2[pix2] >> 1))
|
||||
* (255 - b1) * div_2_255;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'hard-light' :
|
||||
var div_2_255 = 2 / 255;
|
||||
while (p--) {
|
||||
if ((r2 = data2[pix -= 4]) < 128)
|
||||
data2[pix] = data[pix] * r2 * div_2_255;
|
||||
else
|
||||
data2[pix] = 255 - (255 - data[pix]) * (255 - r2)
|
||||
* div_2_255;
|
||||
|
||||
if ((g2 = data2[pix1 = pix + 1]) < 128)
|
||||
data2[pix1] = data[pix1] * g2 * div_2_255;
|
||||
else
|
||||
data2[pix1] = 255 - (255 - data[pix1]) * (255 - g2)
|
||||
* div_2_255;
|
||||
|
||||
if ((b2 = data2[pix2 = pix + 2]) < 128)
|
||||
data2[pix2] = data[pix2] * b2 * div_2_255;
|
||||
else
|
||||
data2[pix2] = 255 - (255 - data[pix2]) * (255 - b2)
|
||||
* div_2_255;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'color-dodge' :
|
||||
while (p--) {
|
||||
if ((r3 = (data[pix -= 4] << 8) / (255 - (r2 = data2[pix])))
|
||||
> 255 || r2 == 255)
|
||||
data2[pix] = 255;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
|
||||
if ((g3 = (data[pix1 = pix + 1] << 8) / (255
|
||||
- (g2 = data2[pix1]))) > 255 || g2 == 255)
|
||||
data2[pix1] = 255;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
|
||||
if ((b3 = (data[pix2 = pix + 2] << 8) / (255
|
||||
- (b2 = data2[pix2]))) > 255 || b2 == 255)
|
||||
data2[pix2] = 255;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'color-burn' :
|
||||
while (p--) {
|
||||
if ((r3 = 255 - ((255 - data[pix -= 4]) << 8) / data2[pix])
|
||||
< 0 || data2[pix] == 0)
|
||||
data2[pix] = 0;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
|
||||
if ((g3 = 255 - ((255 - data[pix1 = pix + 1]) << 8) /
|
||||
data2[pix1]) < 0 || data2[pix1] == 0)
|
||||
data2[pix1] = 0;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
|
||||
if ((b3 = 255 - ((255 - data[pix2 = pix + 2]) << 8) /
|
||||
data2[pix2]) < 0 || data2[pix2] == 0)
|
||||
data2[pix2] = 0;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'linear-light' :
|
||||
while (p--) {
|
||||
if (((r3 = 2 * (r2 = data2[pix -= 4]) + data[pix] - 256)
|
||||
< 0) || (r2 < 128 && r3 < 0)) {
|
||||
data2[pix] = 0;
|
||||
} else {
|
||||
if (r3 > 255)
|
||||
data2[pix] = 255;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
}
|
||||
if (((g3 = 2 * (g2 = data2[pix1 = pix + 1]) + data[pix1]
|
||||
- 256) < 0) || (g2 < 128 && g3 < 0)) {
|
||||
data2[pix1] = 0;
|
||||
} else {
|
||||
if (g3 > 255)
|
||||
data2[pix1] = 255;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
}
|
||||
if ( ((b3 = 2*(b2 = data2[pix2 = pix + 2])+ data[pix2]-256)
|
||||
< 0) || (b2 < 128 && b3 < 0)) {
|
||||
data2[pix2] = 0;
|
||||
} else {
|
||||
if (b3 > 255)
|
||||
data2[pix2] = 255;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'vivid-light' :
|
||||
while (p--) {
|
||||
if ((r2 = data2[pix -= 4]) < 128) {
|
||||
if (r2) {
|
||||
if ((r3 = 255 - ((255 - data[pix]) << 8) /
|
||||
(2 * r2)) < 0)
|
||||
data2[pix] = 0;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
} else {
|
||||
data2[pix] = 0;
|
||||
}
|
||||
} else if ((r3 = (r4 = 2 * r2 - 256)) < 255) {
|
||||
if ((r3 = (data[pix] << 8) / (255 - r4)) > 255)
|
||||
data2[pix] = 255;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
} else {
|
||||
if (r3 < 0)
|
||||
data2[pix] = 0;
|
||||
else
|
||||
data2[pix] = r3;
|
||||
}
|
||||
|
||||
if ((g2 = data2[pix1 = pix + 1]) < 128) {
|
||||
if (g2) {
|
||||
if ((g3 = 255 - ((255 - data[pix1]) << 8) /
|
||||
(2 * g2)) < 0)
|
||||
data2[pix1] = 0;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
} else {
|
||||
data2[pix1] = 0;
|
||||
}
|
||||
} else if ((g3 = (g4 = 2 * g2 - 256)) < 255) {
|
||||
if ((g3 = (data[pix1] << 8) / (255 - g4)) > 255)
|
||||
data2[pix1] = 255;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
} else {
|
||||
if (g3 < 0)
|
||||
data2[pix1] = 0;
|
||||
else
|
||||
data2[pix1] = g3;
|
||||
}
|
||||
|
||||
if ((b2 = data2[pix2 = pix + 2]) < 128) {
|
||||
if (b2) {
|
||||
if ((b3 = 255 - ((255 - data[pix2]) << 8) /
|
||||
(2 * b2)) < 0)
|
||||
data2[pix2] = 0;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
} else {
|
||||
data2[pix2] = 0;
|
||||
}
|
||||
} else if ((b3 = (b4 = 2 * b2 - 256)) < 255) {
|
||||
if ((b3 = (data[pix2] << 8) / (255 - b4)) > 255)
|
||||
data2[pix2] = 255;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
} else {
|
||||
if (b3 < 0)
|
||||
data2[pix2] = 0;
|
||||
else
|
||||
data2[pix2] = b3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'pin-light' :
|
||||
while (p--) {
|
||||
if ((r2 = data2[pix -= 4]) < 128)
|
||||
if ((r1 = data[pix]) < (r4 = 2 * r2))
|
||||
data2[pix] = r1;
|
||||
else
|
||||
data2[pix] = r4;
|
||||
else
|
||||
if ((r1 = data[pix]) > (r4 = 2 * r2 - 256))
|
||||
data2[pix] = r1;
|
||||
else
|
||||
data2[pix] = r4;
|
||||
|
||||
if ((g2 = data2[pix1 = pix + 1]) < 128)
|
||||
if ((g1 = data[pix1]) < (g4 = 2 * g2))
|
||||
data2[pix1] = g1;
|
||||
else
|
||||
data2[pix1] = g4;
|
||||
else
|
||||
if ((g1 = data[pix1]) > (g4 = 2 * g2 - 256))
|
||||
data2[pix1] = g1;
|
||||
else
|
||||
data2[pix1] = g4;
|
||||
|
||||
if ((r2 = data2[pix2 = pix + 2]) < 128)
|
||||
if ((r1 = data[pix2]) < (r4 = 2 * r2))
|
||||
data2[pix2] = r1;
|
||||
else
|
||||
data2[pix2] = r4;
|
||||
else
|
||||
if ((r1 = data[pix2]) > (r4 = 2 * r2 - 256))
|
||||
data2[pix2] = r1;
|
||||
else
|
||||
data2[pix2] = r4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'hard-mix' :
|
||||
while (p--) {
|
||||
if ((r2 = data2[pix -= 4]) < 128)
|
||||
if (255 - ((255 - data[pix]) << 8) / (2 * r2) < 128
|
||||
|| r2 == 0)
|
||||
data2[pix] = 0;
|
||||
else
|
||||
data2[pix] = 255;
|
||||
else if ((r4 = 2 * r2 - 256) < 255
|
||||
&& (data[pix] << 8) / (255 - r4) < 128)
|
||||
data2[pix] = 0;
|
||||
else
|
||||
data2[pix] = 255;
|
||||
|
||||
if ((g2 = data2[pix1 = pix + 1]) < 128)
|
||||
if (255 - ((255 - data[pix1]) << 8) / (2 * g2) < 128
|
||||
|| g2 == 0)
|
||||
data2[pix1] = 0;
|
||||
else
|
||||
data2[pix1] = 255;
|
||||
else if ((g4 = 2 * g2 - 256) < 255
|
||||
&& (data[pix1] << 8) / (255 - g4) < 128)
|
||||
data2[pix1] = 0;
|
||||
else
|
||||
data2[pix1] = 255;
|
||||
|
||||
if ((b2 = data2[pix2 = pix + 2]) < 128)
|
||||
if (255 - ((255 - data[pix2]) << 8) / (2 * b2) < 128
|
||||
|| b2 == 0)
|
||||
data2[pix2] = 0;
|
||||
else
|
||||
data2[pix2] = 255;
|
||||
else if ((b4 = 2 * b2 - 256) < 255
|
||||
&& (data[pix2] << 8) / (255 - b4) < 128)
|
||||
data2[pix2] = 0;
|
||||
else
|
||||
data2[pix2] = 255;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
itemContext.putImageData(dataDesc2, 0, 0);
|
||||
|
||||
documentContext.drawImage(
|
||||
itemCanvas,
|
||||
0, 0,
|
||||
width, height,
|
||||
left, top,
|
||||
width, height
|
||||
);
|
||||
CanvasProvider.returnCanvas(itemCanvas);
|
||||
}
|
||||
};
|
|
@ -11,30 +11,35 @@ 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.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);
|
||||
if (this.clipped & i == 0)
|
||||
ctx.clip();
|
||||
}
|
||||
if (tempCanvas) {
|
||||
originalCtx.save();
|
||||
originalCtx.globalAlpha = this.opacity;
|
||||
originalCtx.drawImage(tempCanvas, 0, 0);
|
||||
originalCtx.restore();
|
||||
// Return the canvas, so it can be reused
|
||||
CanvasProvider.returnCanvas(tempCanvas);
|
||||
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, param);
|
||||
if (this.clipped & i == 0)
|
||||
ctx.clip();
|
||||
}
|
||||
if (tempCanvas) {
|
||||
originalCtx.save();
|
||||
originalCtx.globalAlpha = this.opacity;
|
||||
originalCtx.drawImage(tempCanvas, 0, 0);
|
||||
originalCtx.restore();
|
||||
// Return the canvas, so it can be reused
|
||||
CanvasProvider.returnCanvas(tempCanvas);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -38,12 +38,17 @@ PlacedSymbol = Item.extend({
|
|||
return this._bounds;
|
||||
},
|
||||
|
||||
draw: function(ctx) {
|
||||
// TODO: we need to preserve strokewidth, but still transform the fill
|
||||
ctx.save();
|
||||
this.matrix.applyToContext(ctx);
|
||||
this.symbol.definition.draw(ctx);
|
||||
ctx.restore();
|
||||
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()
|
||||
|
|
|
@ -165,12 +165,17 @@ Raster = Item.extend({
|
|||
return this._bounds;
|
||||
},
|
||||
|
||||
draw: function(ctx) {
|
||||
ctx.save();
|
||||
this.matrix.applyToContext(ctx);
|
||||
ctx.drawImage(this._canvas || this._image,
|
||||
-this.size.width / 2, -this.size.height / 2);
|
||||
ctx.restore();
|
||||
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) {
|
||||
|
|
|
@ -19,24 +19,30 @@ CompoundPath = PathItem.extend(new function() {
|
|||
}
|
||||
},
|
||||
|
||||
draw: function(ctx) {
|
||||
draw: function(ctx, param) {
|
||||
if(!this.visible)
|
||||
return;
|
||||
if (this.children.length) {
|
||||
var firstChild = this.children[0];
|
||||
ctx.beginPath();
|
||||
for (var i = 0, l = this.children.length; i < l; i++) {
|
||||
var child = this.children[i];
|
||||
child.draw(ctx, true);
|
||||
}
|
||||
firstChild.setCtxStyles(ctx);
|
||||
if (firstChild.fillColor) {
|
||||
ctx.fillStyle = firstChild.fillColor.getCssString();
|
||||
ctx.fill();
|
||||
}
|
||||
if (firstChild.strokeColor) {
|
||||
ctx.strokeStyle = firstChild.strokeColor.getCssString();
|
||||
ctx.stroke();
|
||||
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, param);
|
||||
}
|
||||
param.compound = false;
|
||||
firstChild.setCtxStyles(ctx);
|
||||
if (firstChild.fillColor) {
|
||||
ctx.fillStyle = firstChild.fillColor.getCssString();
|
||||
ctx.fill();
|
||||
}
|
||||
if (firstChild.strokeColor) {
|
||||
ctx.strokeStyle = firstChild.strokeColor.getCssString();
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -352,57 +352,63 @@ Path = PathItem.extend({
|
|||
this.closed = ture;
|
||||
},
|
||||
|
||||
draw: function(ctx, compound) {
|
||||
draw: function(ctx, param) {
|
||||
if (!this.visible) return;
|
||||
if (!compound)
|
||||
ctx.beginPath();
|
||||
|
||||
var segments = this._segments;
|
||||
var length = segments.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
var segment = segments[i];
|
||||
var x = segment.point.x;
|
||||
var y = segment.point.y;
|
||||
var handleIn = segment.handleIn;
|
||||
if (i == 0) {
|
||||
ctx.moveTo(x, y);
|
||||
} else {
|
||||
if (handleOut.isZero() && handleIn.isZero()) {
|
||||
ctx.lineTo(x, y);
|
||||
if(this.blendMode != 'normal' && !param.ignoreBlendMode) {
|
||||
BlendMode.process(ctx, this, param);
|
||||
} else {
|
||||
param.ignoreBlendMode = false;
|
||||
if (!param.compound)
|
||||
ctx.beginPath();
|
||||
|
||||
var segments = this._segments;
|
||||
var length = segments.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
var segment = segments[i];
|
||||
var x = segment.point.x;
|
||||
var y = segment.point.y;
|
||||
var handleIn = segment.handleIn;
|
||||
if (i == 0) {
|
||||
ctx.moveTo(x, y);
|
||||
} else {
|
||||
ctx.bezierCurveTo(
|
||||
outX, outY,
|
||||
handleIn.x + x, handleIn.y + y,
|
||||
x, y
|
||||
);
|
||||
if (handleOut.isZero() && handleIn.isZero()) {
|
||||
ctx.lineTo(x, y);
|
||||
} else {
|
||||
ctx.bezierCurveTo(
|
||||
outX, outY,
|
||||
handleIn.x + x, handleIn.y + y,
|
||||
x, y
|
||||
);
|
||||
}
|
||||
}
|
||||
var handleOut = segment.handleOut;
|
||||
var outX = handleOut.x + x;
|
||||
var outY = handleOut.y + y;
|
||||
}
|
||||
var handleOut = segment.handleOut;
|
||||
var outX = handleOut.x + x;
|
||||
var outY = handleOut.y + y;
|
||||
}
|
||||
if (this.closed && length > 1) {
|
||||
var segment = segments[0];
|
||||
var x = segment.point.x;
|
||||
var y = segment.point.y;
|
||||
var handleIn = segment.handleIn;
|
||||
ctx.bezierCurveTo(outX, outY, handleIn.x + x, handleIn.y + y, x, y);
|
||||
ctx.closePath();
|
||||
}
|
||||
if (!compound) {
|
||||
this.setCtxStyles(ctx);
|
||||
ctx.save();
|
||||
ctx.globalAlpha = this.opacity;
|
||||
if (this.fillColor) {
|
||||
ctx.fillStyle = this.fillColor.getCanvasStyle(ctx);
|
||||
ctx.fill();
|
||||
if (this.closed && length > 1) {
|
||||
var segment = segments[0];
|
||||
var x = segment.point.x;
|
||||
var y = segment.point.y;
|
||||
var handleIn = segment.handleIn;
|
||||
ctx.bezierCurveTo(outX, outY, handleIn.x + x, handleIn.y + y, x, y);
|
||||
ctx.closePath();
|
||||
}
|
||||
if (this.strokeColor) {
|
||||
ctx.strokeStyle = this.strokeColor.getCanvasStyle(ctx);
|
||||
ctx.stroke();
|
||||
if (!param.compound) {
|
||||
this.setCtxStyles(ctx);
|
||||
ctx.save();
|
||||
ctx.globalAlpha = this.opacity;
|
||||
if (this.fillColor) {
|
||||
ctx.fillStyle = this.fillColor.getCanvasStyle(ctx);
|
||||
ctx.fill();
|
||||
}
|
||||
if (this.strokeColor) {
|
||||
ctx.strokeStyle = this.strokeColor.getCanvasStyle(ctx);
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
}
|
||||
}, new function() { // inject methods that require scoped privates
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue