mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
Merge remote branch 'origin/master'
This commit is contained in:
commit
884446f606
11 changed files with 140 additions and 140 deletions
|
@ -19,8 +19,8 @@ var Gradient = this.Gradient = Base.extend({
|
|||
|
||||
beans: true,
|
||||
|
||||
// TODO: Should type here be called 'radial' and have it
|
||||
// receive a boolean value?
|
||||
// TODO: Should type here be called 'radial' and have it receive a
|
||||
// boolean value?
|
||||
/**
|
||||
* Creates a gradient object
|
||||
*
|
||||
|
|
|
@ -1051,8 +1051,8 @@ var Item = this.Item = Base.extend({
|
|||
*/
|
||||
transform: function(matrix, flags) {
|
||||
// TODO: Handle flags, add TransformFlag class and convert to bit mask
|
||||
// for quicker checking
|
||||
// TODO: Call transform on chidren only if 'children' flag is provided
|
||||
// for quicker checking.
|
||||
// TODO: Call transform on chidren only if 'children' flag is provided.
|
||||
if (this._transform)
|
||||
this._transform(matrix, flags);
|
||||
// Transform position as well. Do not modify _position directly,
|
||||
|
@ -1093,7 +1093,7 @@ var Item = this.Item = Base.extend({
|
|||
}
|
||||
},
|
||||
|
||||
// TODO: Implement View into the drawing
|
||||
// TODO: Implement View into the drawing.
|
||||
// TODO: Optimize temporary canvas drawing to ignore parts that are
|
||||
// outside of the visible view.
|
||||
draw: function(item, ctx, param) {
|
||||
|
@ -1249,8 +1249,6 @@ var Item = this.Item = Base.extend({
|
|||
moveBelow: move(false)
|
||||
};
|
||||
}, new function() {
|
||||
//DOCS: document removeOn(param)
|
||||
|
||||
/**
|
||||
* {@grouptitle Remove On Event}
|
||||
* Removes the item when the next {@link Tool#onMouseMove} event is fired.
|
||||
|
|
|
@ -19,9 +19,9 @@ var Raster = this.Raster = Item.extend({
|
|||
|
||||
beans: true,
|
||||
|
||||
// TODO: implement url / type, width, height
|
||||
// TODO: have PlacedSymbol & Raster inherit from a shared class?
|
||||
// DOCS: document Raster constructor
|
||||
// TODO: Implement url / type, width, height.
|
||||
// TODO: Have PlacedSymbol & Raster inherit from a shared class?
|
||||
// DOCS: Document Raster constructor.
|
||||
/**
|
||||
* Creates a new raster item and places it in the active layer.
|
||||
*
|
||||
|
@ -163,12 +163,12 @@ var Raster = this.Raster = Item.extend({
|
|||
return this._image || this.getCanvas();
|
||||
},
|
||||
|
||||
// TODO: support string id of image element
|
||||
// TODO: Support string id of image element.
|
||||
setImage: function(image) {
|
||||
if (this._canvas)
|
||||
CanvasProvider.returnCanvas(this._canvas);
|
||||
this._image = image;
|
||||
// TODO: cross browser compatible?
|
||||
// TODO: Cross browser compatible?
|
||||
this._size = new Size(image.naturalWidth, image.naturalHeight);
|
||||
this._canvas = null;
|
||||
this._context = null;
|
||||
|
@ -216,8 +216,8 @@ var Raster = this.Raster = Item.extend({
|
|||
object = this.getBounds();
|
||||
var bounds, path;
|
||||
if (object instanceof PathItem) {
|
||||
// TODO: what if the path is smaller than 1 px?
|
||||
// TODO: how about rounding of bounds.size?
|
||||
// TODO: What if the path is smaller than 1 px?
|
||||
// TODO: How about rounding of bounds.size?
|
||||
path = object;
|
||||
bounds = object.getBounds();
|
||||
} else if (object.width) {
|
||||
|
|
|
@ -54,7 +54,7 @@ var CompoundPath = this.CompoundPath = PathItem.extend({
|
|||
// clockwise orientation when creating a compound path, so that they
|
||||
// appear as holes, but only if their orientation was not already
|
||||
// specified before (= _clockwise is defined).
|
||||
// TODO: This should really be handled in appendTop / Bottom, right?
|
||||
// TODO: Should this be handled in appendTop / Bottom instead?
|
||||
if (path._clockwise === undefined)
|
||||
path.setClockwise(i < l - 1);
|
||||
this.appendTop(path);
|
||||
|
|
|
@ -20,7 +20,7 @@ var Project = this.Project = Base.extend({
|
|||
beans: true,
|
||||
|
||||
// TODO: Add arguments to define pages
|
||||
// DOCS: document Project constructor and class
|
||||
// DOCS: Document Project constructor and class
|
||||
/**
|
||||
* Creates a Paper.js project
|
||||
*
|
||||
|
@ -90,7 +90,7 @@ var Project = this.Project = Base.extend({
|
|||
},
|
||||
|
||||
setCurrentStyle: function(style) {
|
||||
// TODO: style selected items with the style:
|
||||
// TODO: Style selected items with the style:
|
||||
this._currentStyle.initialize(style);
|
||||
},
|
||||
|
||||
|
@ -129,9 +129,9 @@ var Project = this.Project = Base.extend({
|
|||
* @bean
|
||||
*/
|
||||
getSelectedItems: function() {
|
||||
// TODO: return groups if their children are all selected,
|
||||
// TODO: Return groups if their children are all selected,
|
||||
// and filter out their children from the list.
|
||||
// TODO: the order of these items should be that of their
|
||||
// TODO: The order of these items should be that of their
|
||||
// drawing order.
|
||||
var items = [];
|
||||
Base.each(this._selectedItems, function(item) {
|
||||
|
@ -140,7 +140,7 @@ var Project = this.Project = Base.extend({
|
|||
return items;
|
||||
},
|
||||
|
||||
// TODO: implement setSelectedItems?
|
||||
// TODO: Implement setSelectedItems?
|
||||
|
||||
_selectItem: function(item, select) {
|
||||
if (select) {
|
||||
|
|
|
@ -57,7 +57,7 @@ var Symbol = this.Symbol = Base.extend({
|
|||
},
|
||||
|
||||
// TODO: Symbol#remove()
|
||||
// TODO: Size#name (accessible by name through project#symbols)
|
||||
// TODO: Symbol#name (accessible by name through project#symbols)
|
||||
|
||||
/**
|
||||
* The project that this symbol belongs to.
|
||||
|
|
|
@ -69,8 +69,8 @@ var PointText = this.PointText = TextItem.extend({
|
|||
Point.read(arguments).subtract(this._point)));
|
||||
},
|
||||
|
||||
// TODO: position should be the center point of the bounds
|
||||
// but we currently don't support bounds for PointText.
|
||||
// TODO: Position should be the center point of the bounds but we currently
|
||||
// don't support bounds for PointText.
|
||||
getPosition: function() {
|
||||
return this._point;
|
||||
},
|
||||
|
|
|
@ -172,7 +172,7 @@ var ToolEvent = this.ToolEvent = Base.extend({
|
|||
return Key.modifiers;
|
||||
},
|
||||
|
||||
// TODO: implement hitTest first
|
||||
// TODO: Implement hitTest first
|
||||
// getItem: function() {
|
||||
// if (this.item == null) {
|
||||
// var result = Project.getActiveProject().hitTest(this.getPoint());
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* @name Key
|
||||
*/
|
||||
var Key = this.Key = new function() {
|
||||
// TODO: make sure the keys are called the same as in Scriptographer
|
||||
// TODO: Make sure the keys are called the same as in Scriptographer
|
||||
// Missing: tab, cancel, clear, page-down, page-up, comma, minus, period,
|
||||
// slash, etc etc etc.
|
||||
|
||||
|
|
|
@ -39,133 +39,135 @@
|
|||
*/
|
||||
|
||||
var BlendMode = {
|
||||
// TODO: Should we remove the blend modes that are not in Scriptographer?
|
||||
// TODO: Add missing blendmodes like hue / saturation / color / luminosity
|
||||
// TODO: Clean up codespacing of original code, or keep it as is, so
|
||||
// we can easily encorporate changes?
|
||||
process: function(blendMode, sourceContext, destContext, opacity, offset) {
|
||||
var sourceCanvas = sourceContext.canvas,
|
||||
dstD = destContext.getImageData(offset.x, offset.y,
|
||||
dstData = destContext.getImageData(offset.x, offset.y,
|
||||
sourceCanvas.width, sourceCanvas.height),
|
||||
srcD = sourceContext.getImageData(0, 0,
|
||||
sourceCanvas.width, sourceCanvas.height),
|
||||
src = srcD.data,
|
||||
dst = dstD.data,
|
||||
sA, dA, len = dst.length,
|
||||
sRA, sGA, sBA, dRA, dGA, dBA, dA2,
|
||||
demultiply,
|
||||
min = Math.min;
|
||||
dst = dstData.data,
|
||||
src = sourceContext.getImageData(0, 0,
|
||||
sourceCanvas.width, sourceCanvas.height).data,
|
||||
min = Math.min,
|
||||
max = Math.max,
|
||||
sA, dA, rA, sM, dM, rM, sRA, sGA, sBA, dRA, dGA, dBA;
|
||||
|
||||
for (var i = 0; i < len; i += 4) {
|
||||
sA = src[i + 3] / 255 * opacity;
|
||||
dA = dst[i + 3] / 255;
|
||||
dA2 = sA + dA - sA * dA;
|
||||
dst[i + 3] = dA2 * 255;
|
||||
// TODO: Some blend modes seem broken at the moment, e.g. dodge, burn
|
||||
var modes = {
|
||||
normal: function(i) {
|
||||
var sA1 = 1 - sA;
|
||||
dst[i] = (sRA + dRA * sA1) * rM;
|
||||
dst[i + 1] = (sGA + dGA * sA1) * rM;
|
||||
dst[i + 2] = (sBA + dRA * sA1) * rM;
|
||||
},
|
||||
|
||||
sRA = src[i] / 255 * sA;
|
||||
dRA = dst[i] / 255 * dA;
|
||||
sGA = src[i + 1] / 255 * sA;
|
||||
dGA = dst[i + 1] / 255 * dA;
|
||||
sBA = src[i + 2] / 255 * sA;
|
||||
dBA = dst[i + 2] / 255 * dA;
|
||||
multiply: function(i) {
|
||||
var sA1 = 1 - sA, dA1 = 1 - dA;
|
||||
dst[i] = (sRA * dRA + sRA * dA1 + dRA * sA1) * rM;
|
||||
dst[i + 1] = (sGA * dGA + sGA * dA1 + dGA * sA1) * rM;
|
||||
dst[i + 2] = (sBA * dBA + sBA * dA1 + dBA * sA1) * rM;
|
||||
},
|
||||
|
||||
demultiply = 255 / dA2;
|
||||
screen: function(i) {
|
||||
dst[i] = (sRA + dRA - sRA * dRA) * rM;
|
||||
dst[i + 1] = (sGA + dGA - sGA * dGA) * rM;
|
||||
dst[i + 2] = (sBA + dBA - sBA * dBA) * rM;
|
||||
},
|
||||
|
||||
// TODO: Some blend modes seem broken at the moment, e.g.
|
||||
// dodge, burn
|
||||
// TODO: This could be optimised by not diving everything by 255 and
|
||||
// keeping it integer instead, with one divide at the end.
|
||||
|
||||
switch (blendMode) {
|
||||
// Very close match to Photoshop
|
||||
case 'normal':
|
||||
case 'src-over':
|
||||
dst[i] = (sRA + dRA - dRA * sA) * demultiply;
|
||||
dst[i + 1] = (sGA + dGA - dGA * sA) * demultiply;
|
||||
dst[i + 2] = (sBA + dBA - dBA * sA) * demultiply;
|
||||
break;
|
||||
case 'screen':
|
||||
dst[i] = (sRA + dRA - sRA * dRA) * demultiply;
|
||||
dst[i + 1] = (sGA + dGA - sGA * dGA) * demultiply;
|
||||
dst[i + 2] = (sBA + dBA - sBA * dBA) * demultiply;
|
||||
break;
|
||||
case 'multiply':
|
||||
dst[i] = (sRA * dRA + sRA * (1 - dA) + dRA * (1 - sA)) * demultiply;
|
||||
dst[i + 1] = (sGA * dGA + sGA * (1 - dA) + dGA * (1 - sA)) * demultiply;
|
||||
dst[i + 2] = (sBA * dBA + sBA * (1 - dA) + dBA * (1 - sA)) * demultiply;
|
||||
break;
|
||||
case 'difference':
|
||||
dst[i] = (sRA + dRA - 2 * min(sRA * dA, dRA * sA)) * demultiply;
|
||||
dst[i + 1] = (sGA + dGA - 2 * min(sGA * dA, dGA * sA)) * demultiply;
|
||||
dst[i + 2] = (sBA + dBA - 2 * min(sBA * dA, dBA * sA)) * demultiply;
|
||||
break;
|
||||
// Slightly different from Photoshop, where alpha is concerned
|
||||
case 'src-in':
|
||||
// Only differs from Photoshop in low - opacity areas
|
||||
dA2 = sA * dA;
|
||||
demultiply = 255 / dA2;
|
||||
dst[i + 3] = dA2 * 255;
|
||||
dst[i] = sRA * dA * demultiply;
|
||||
dst[i + 1] = sGA * dA * demultiply;
|
||||
dst[i + 2] = sBA * dA * demultiply;
|
||||
break;
|
||||
case 'plus':
|
||||
case 'add':
|
||||
// Photoshop doesn't simply add the alpha channels; this might be correct wrt SVG 1.2
|
||||
dA2 = min(1, sA + dA);
|
||||
dst[i + 3] = dA2 * 255;
|
||||
demultiply = 255 / dA2;
|
||||
dst[i] = min(sRA + dRA, 1) * demultiply;
|
||||
dst[i + 1] = min(sGA + dGA, 1) * demultiply;
|
||||
dst[i + 2] = min(sBA + dBA, 1) * demultiply;
|
||||
break;
|
||||
case 'overlay':
|
||||
overlay: function(i) {
|
||||
// = Reverse of hard-light
|
||||
// Correct for 100% opacity case; colors get clipped as opacity falls
|
||||
dst[i] = dRA <= 0.5 ? (2 * src[i] * dRA / dA) : 255 - (2 - 2 * dRA / dA) * (255 - src[i]);
|
||||
dst[i + 1] = dGA <= 0.5 ? (2 * src[i + 1] * dGA / dA) : 255 - (2 - 2 * dGA / dA) * (255 - src[i + 1]);
|
||||
dst[i + 2] = dBA <= 0.5 ? (2 * src[i + 2] * dBA / dA) : 255 - (2 - 2 * dBA / dA) * (255 - src[i + 2]);
|
||||
break;
|
||||
case 'hard-light':
|
||||
dst[i] = sRA <= 0.5 ? (2 * dst[i] * sRA / dA) : 255 - (2 - 2 * sRA / sA) * (255 - dst[i]);
|
||||
},
|
||||
|
||||
// TODO: Missing: soft-light
|
||||
|
||||
'hard-light': function(i) {
|
||||
dst[i] = sRA <= 0.5 ? (2 * dst[i] * sRA / dA) : 255 - (2 - 2 * sRA / sA) * (255 - dst[i]);
|
||||
dst[i + 1] = sGA <= 0.5 ? (2 * dst[i + 1] * sGA / dA) : 255 - (2 - 2 * sGA / sA) * (255 - dst[i + 1]);
|
||||
dst[i + 2] = sBA <= 0.5 ? (2 * dst[i + 2] * sBA / dA) : 255 - (2 - 2 * sBA / sA) * (255 - dst[i + 2]);
|
||||
break;
|
||||
case 'color-dodge':
|
||||
case 'dodge':
|
||||
dst[i] = src[i] == 255 && dRA == 0 ? 255 : min(255, dst[i] / (255 - src[i] )) * demultiply;
|
||||
dst[i + 1] = src[i + 1] == 255 && dGA == 0 ? 255 : min(255, dst[i + 1] / (255 - src[i + 1])) * demultiply;
|
||||
dst[i + 2] = src[i + 2] == 255 && dBA == 0 ? 255 : min(255, dst[i + 2] / (255 - src[i + 2])) * demultiply;
|
||||
break;
|
||||
case 'color-burn':
|
||||
case 'burn':
|
||||
dst[i] = src[i] == 0 && dRA == 0 ? 0 : (1 - min(1, (1 - dRA) / sRA)) * demultiply;
|
||||
dst[i + 1] = src[i + 1] == 0 && dGA == 0 ? 0 : (1 - min(1, (1 - dGA) / sGA)) * demultiply;
|
||||
dst[i + 2] = src[i + 2] == 0 && dBA == 0 ? 0 : (1 - min(1, (1 - dBA) / sBA)) * demultiply;
|
||||
break;
|
||||
case 'darken':
|
||||
case 'darker':
|
||||
dst[i] = (sRA > dRA ? dRA : sRA) * demultiply;
|
||||
dst[i + 1] = (sGA > dGA ? dGA : sGA) * demultiply;
|
||||
dst[i + 2] = (sBA > dBA ? dBA : sBA) * demultiply;
|
||||
break;
|
||||
case 'lighten':
|
||||
case 'lighter':
|
||||
dst[i] = (sRA < dRA ? dRA : sRA) * demultiply;
|
||||
dst[i + 1] = (sGA < dGA ? dGA : sGA) * demultiply;
|
||||
dst[i + 2] = (sBA < dBA ? dBA : sBA) * demultiply;
|
||||
break;
|
||||
case 'exclusion':
|
||||
dst[i] = (dRA + sRA - 2 * dRA * sRA) * demultiply;
|
||||
dst[i + 1] = (dGA + sGA - 2 * dGA * sGA) * demultiply;
|
||||
dst[i + 2] = (dBA + sBA - 2 * dBA * sBA) * demultiply;
|
||||
break;
|
||||
// Unsupported
|
||||
default:
|
||||
dst[i] = dst[i + 3] = 255;
|
||||
dst[i + 1] = i % 8 == 0 ? 255 : 0;
|
||||
dst[i + 2] = i % 8 == 0 ? 0 : 255;
|
||||
},
|
||||
|
||||
'color-dodge': function(i) {
|
||||
dst[i] = src[i] == 255 && dRA == 0 ? 255 : min(255, dst[i] / (255 - src[i] )) * rM;
|
||||
dst[i + 1] = src[i + 1] == 255 && dGA == 0 ? 255 : min(255, dst[i + 1] / (255 - src[i + 1])) * rM;
|
||||
dst[i + 2] = src[i + 2] == 255 && dBA == 0 ? 255 : min(255, dst[i + 2] / (255 - src[i + 2])) * rM;
|
||||
},
|
||||
|
||||
'color-burn': function(i) {
|
||||
dst[i] = src[i] == 0 && dRA == 0 ? 0 : (1 - min(1, (1 - dRA) / sRA)) * rM;
|
||||
dst[i + 1] = src[i + 1] == 0 && dGA == 0 ? 0 : (1 - min(1, (1 - dGA) / sGA)) * rM;
|
||||
dst[i + 2] = src[i + 2] == 0 && dBA == 0 ? 0 : (1 - min(1, (1 - dBA) / sBA)) * rM;
|
||||
},
|
||||
|
||||
darken: function(i) {
|
||||
dst[i] = min(sRA, dRA) * rM;
|
||||
dst[i + 1] = min(sGA, dGA) * rM;
|
||||
dst[i + 2] = min(sBA, dBA) * rM;
|
||||
},
|
||||
|
||||
lighten: function(i) {
|
||||
dst[i] = max(sRA, dRA) * rM;
|
||||
dst[i + 1] = max(sGA, dGA) * rM;
|
||||
dst[i + 2] = max(sBA, dBA) * rM;
|
||||
},
|
||||
|
||||
difference: function(i) {
|
||||
dst[i] = (sRA + dRA - 2 * min(sRA * dA, dRA * sA)) * rM;
|
||||
dst[i + 1] = (sGA + dGA - 2 * min(sGA * dA, dGA * sA)) * rM;
|
||||
dst[i + 2] = (sBA + dBA - 2 * min(sBA * dA, dBA * sA)) * rM;
|
||||
},
|
||||
|
||||
exclusion: function(i) {
|
||||
dst[i] = (dRA + sRA - 2 * dRA * sRA) * rM;
|
||||
dst[i + 1] = (dGA + sGA - 2 * dGA * sGA) * rM;
|
||||
dst[i + 2] = (dBA + sBA - 2 * dBA * sBA) * rM;
|
||||
},
|
||||
|
||||
// TODO: Missing: hue, saturation, color, luminosity
|
||||
|
||||
// Not in Illustrator:
|
||||
|
||||
'src-in': function(i) {
|
||||
// Only differs from Photoshop in low - opacity areas
|
||||
rA = sA * dA;
|
||||
rM = 255 / rA;
|
||||
dst[i] = sRA * dA * rM;
|
||||
dst[i + 1] = sGA * dA * rM;
|
||||
dst[i + 2] = sBA * dA * rM;
|
||||
},
|
||||
|
||||
add: function(i) {
|
||||
// Photoshop doesn't simply add the alpha channels,
|
||||
// this might be correct wrt SVG 1.2
|
||||
rA = min(1, sA + dA);
|
||||
rM = 255 / rA;
|
||||
dst[i] = min(sRA + dRA, 1) * rM;
|
||||
dst[i + 1] = min(sGA + dGA, 1) * rM;
|
||||
dst[i + 2] = min(sBA + dBA, 1) * rM;
|
||||
}
|
||||
};
|
||||
|
||||
var process = modes[blendMode];
|
||||
if (!process)
|
||||
return;
|
||||
opacity /= 255;
|
||||
for (var i = 0, l = dst.length; i < l; i += 4) {
|
||||
sA = src[i + 3] * opacity;
|
||||
dA = dst[i + 3] / 255;
|
||||
rA = sA + dA - sA * dA;
|
||||
sM = sA / 255;
|
||||
dM = dA / 255;
|
||||
sRA = src[i] * sM;
|
||||
dRA = dst[i] * dM;
|
||||
sGA = src[i + 1] * sM;
|
||||
dGA = dst[i + 1] * dM;
|
||||
sBA = src[i + 2] * sM;
|
||||
dBA = dst[i + 2] * dM;
|
||||
rM = 255 / rA;
|
||||
process(i);
|
||||
dst[i + 3] = rA * 255;
|
||||
}
|
||||
destContext.putImageData(dstD, offset.x, offset.y);
|
||||
destContext.putImageData(dstData, offset.x, offset.y);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* All rights reserved.
|
||||
*/
|
||||
|
||||
// TODO: it might be better to make a ContextProvider class, since you
|
||||
// can always find the canvas through context.canvas. This saves code and
|
||||
// TODO: It might be better to make a ContextProvider class, since you
|
||||
// can always find the canvas through context.canvas. This saves code and
|
||||
// speed by not having to do canvas.getContext('2d')
|
||||
// TODO: Run through the canvas array to find a canvas with the requested
|
||||
// width / height, so we don't need to resize it?
|
||||
|
|
Loading…
Reference in a new issue