mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-06 04:42:15 -05:00
Merge branch 'develop'
This commit is contained in:
commit
48c8eacf0b
27 changed files with 1670 additions and 1429 deletions
|
@ -41,4 +41,4 @@ script:
|
||||||
- gulp minify
|
- gulp minify
|
||||||
- gulp test
|
- gulp test
|
||||||
- gulp zip
|
- gulp zip
|
||||||
- '[ "${TRAVIS_BRANCH}" = "develop" ] && [ "${TRAVIS_NODE_VERSION}" = "stable" ] && travis/deploy-prebuilt.sh'
|
- '[ "${TRAVIS_BRANCH}" = "develop" ] && [ "${TRAVIS_NODE_VERSION}" = "stable" ] && travis/deploy-prebuilt.sh || true'
|
||||||
|
|
16
README.md
16
README.md
|
@ -51,17 +51,17 @@ generally not recommended to install Node.js through OS-supplied package
|
||||||
managers, as the its development cycles move fast and these versions are often
|
managers, as the its development cycles move fast and these versions are often
|
||||||
out-of-date.
|
out-of-date.
|
||||||
|
|
||||||
|
On macOS, [Homebrew](http://brew.sh/) is a good option if one version of
|
||||||
|
Node.js that is kept up to date with `brew upgrade` is enough:
|
||||||
|
<http://treehouse.github.io/installation-guides/mac/node-mac.html>
|
||||||
|
|
||||||
[NVM](https://github.com/creationix/nvm) can be used instead to install and
|
[NVM](https://github.com/creationix/nvm) can be used instead to install and
|
||||||
maintain multiple versions of Node.js on the same platform, as often required by
|
maintain multiple versions of Node.js on the same platform, as often required by
|
||||||
different projects:
|
different projects:
|
||||||
<https://nodesource.com/blog/installing-node-js-tutorial-using-nvm-on-mac-os-x-and-ubuntu/>
|
<https://nodesource.com/blog/installing-node-js-tutorial-using-nvm-on-mac-os-x-and-ubuntu/>
|
||||||
|
|
||||||
on OSX, [Homebrew](http://brew.sh/) is also a good option if one version of
|
Homebrew is recommended on macOS also if you intend to install Paper.js with
|
||||||
Node.js that is kept up to date with `brew update` is enough:
|
rendering to the Canvas on Node.js, as described in the next paragraph.
|
||||||
<http://treehouse.github.io/installation-guides/mac/node-mac.html>
|
|
||||||
|
|
||||||
Homebrew is recommended on OSX also if you intend to install Paper.js for
|
|
||||||
Node.js, as described in the next paragraph.
|
|
||||||
|
|
||||||
For Linux, see <http://nodejs.org/download/> to locate 32-bit and 64-bit Node.js
|
For Linux, see <http://nodejs.org/download/> to locate 32-bit and 64-bit Node.js
|
||||||
binaries as well as sources, or use NVM, as described in the paragraph above.
|
binaries as well as sources, or use NVM, as described in the paragraph above.
|
||||||
|
@ -83,14 +83,14 @@ different one:
|
||||||
In order to install `paper-jsdom-canvas`, you need the [Cairo Graphics
|
In order to install `paper-jsdom-canvas`, you need the [Cairo Graphics
|
||||||
library](http://cairographics.org/) installed in your system:
|
library](http://cairographics.org/) installed in your system:
|
||||||
|
|
||||||
##### Installing Cairo and Pango on OSX:
|
##### Installing Cairo and Pango on macOS:
|
||||||
|
|
||||||
The easiest way to install Cairo is through [Homebrew](http://brew.sh/), by
|
The easiest way to install Cairo is through [Homebrew](http://brew.sh/), by
|
||||||
issuing the command:
|
issuing the command:
|
||||||
|
|
||||||
brew install cairo pango
|
brew install cairo pango
|
||||||
|
|
||||||
Note that currently there is an issue on OSX with Cairo. If the above causes
|
Note that currently there is an issue on macOS with Cairo. If the above causes
|
||||||
errors, the following will most likely fix it:
|
errors, the following will most likely fix it:
|
||||||
|
|
||||||
PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig/ npm install paper
|
PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig/ npm install paper
|
||||||
|
|
223
dist/paper-core.js
vendored
223
dist/paper-core.js
vendored
|
@ -1,5 +1,5 @@
|
||||||
/*!
|
/*!
|
||||||
* Paper.js v0.11.2 - The Swiss Army Knife of Vector Graphics Scripting.
|
* Paper.js v0.11.3 - The Swiss Army Knife of Vector Graphics Scripting.
|
||||||
* http://paperjs.org/
|
* http://paperjs.org/
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
|
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Date: Thu Apr 20 19:14:30 2017 +0200
|
* Date: Sat Apr 22 20:01:34 2017 +0200
|
||||||
*
|
*
|
||||||
***
|
***
|
||||||
*
|
*
|
||||||
|
@ -98,12 +98,13 @@ var Base = new function() {
|
||||||
&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
|
&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
|
||||||
beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
|
beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
|
||||||
if (!res || isFunc || !res.get || typeof res.get !== 'function'
|
if (!res || isFunc || !res.get || typeof res.get !== 'function'
|
||||||
|| !Base.isPlainObject(res))
|
|| !Base.isPlainObject(res)) {
|
||||||
res = { value: res, writable: true };
|
res = { value: res, writable: true };
|
||||||
|
}
|
||||||
if ((describe(dest, name)
|
if ((describe(dest, name)
|
||||||
|| { configurable: true }).configurable) {
|
|| { configurable: true }).configurable) {
|
||||||
res.configurable = true;
|
res.configurable = true;
|
||||||
res.enumerable = enumerable;
|
res.enumerable = enumerable != null ? enumerable : !bean;
|
||||||
}
|
}
|
||||||
define(dest, name, res);
|
define(dest, name, res);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,7 @@ var Base = new function() {
|
||||||
preserve = src.preserve;
|
preserve = src.preserve;
|
||||||
if (statics !== src)
|
if (statics !== src)
|
||||||
inject(this.prototype, src, src.enumerable, beans, preserve);
|
inject(this.prototype, src, src.enumerable, beans, preserve);
|
||||||
inject(this, statics, true, beans, preserve);
|
inject(this, statics, null, beans, preserve);
|
||||||
}
|
}
|
||||||
for (var i = 1, l = arguments.length; i < l; i++)
|
for (var i = 1, l = arguments.length; i < l; i++)
|
||||||
this.inject(arguments[i]);
|
this.inject(arguments[i]);
|
||||||
|
@ -164,13 +165,15 @@ var Base = new function() {
|
||||||
proto = ctor.prototype = proto || create(this.prototype);
|
proto = ctor.prototype = proto || create(this.prototype);
|
||||||
define(proto, 'constructor',
|
define(proto, 'constructor',
|
||||||
{ value: ctor, writable: true, configurable: true });
|
{ value: ctor, writable: true, configurable: true });
|
||||||
inject(ctor, this, true);
|
inject(ctor, this);
|
||||||
if (arguments.length)
|
if (arguments.length)
|
||||||
this.inject.apply(ctor, arguments);
|
this.inject.apply(ctor, arguments);
|
||||||
ctor.base = base;
|
ctor.base = base;
|
||||||
return ctor;
|
return ctor;
|
||||||
}
|
}
|
||||||
}, true).inject({
|
}).inject({
|
||||||
|
enumerable: false,
|
||||||
|
|
||||||
initialize: Base,
|
initialize: Base,
|
||||||
|
|
||||||
set: Base,
|
set: Base,
|
||||||
|
@ -230,6 +233,8 @@ if (typeof module !== 'undefined')
|
||||||
module.exports = Base;
|
module.exports = Base;
|
||||||
|
|
||||||
Base.inject({
|
Base.inject({
|
||||||
|
enumerable: false,
|
||||||
|
|
||||||
toString: function() {
|
toString: function() {
|
||||||
return this._id != null
|
return this._id != null
|
||||||
? (this._class || 'Object') + (this._name
|
? (this._class || 'Object') + (this._name
|
||||||
|
@ -265,13 +270,12 @@ Base.inject({
|
||||||
if (props)
|
if (props)
|
||||||
Base.filter(this, props, exclude, this._prioritize);
|
Base.filter(this, props, exclude, this._prioritize);
|
||||||
return this;
|
return this;
|
||||||
},
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
statics: {
|
beans: false,
|
||||||
|
statics: {
|
||||||
exports: {
|
exports: {},
|
||||||
enumerable: true
|
|
||||||
},
|
|
||||||
|
|
||||||
extend: function extend() {
|
extend: function extend() {
|
||||||
var res = extend.base.apply(this, arguments),
|
var res = extend.base.apply(this, arguments),
|
||||||
|
@ -341,6 +345,11 @@ Base.inject({
|
||||||
: list) || obj;
|
: list) || obj;
|
||||||
if (readIndex) {
|
if (readIndex) {
|
||||||
list.__index = begin + obj.__read;
|
list.__index = begin + obj.__read;
|
||||||
|
var filtered = obj.__filtered;
|
||||||
|
if (filtered) {
|
||||||
|
list.__filtered = filtered;
|
||||||
|
obj.__filtered = undefined;
|
||||||
|
}
|
||||||
obj.__read = undefined;
|
obj.__read = undefined;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -371,14 +380,16 @@ Base.inject({
|
||||||
var value = this.getNamed(list, name),
|
var value = this.getNamed(list, name),
|
||||||
hasObject = value !== undefined;
|
hasObject = value !== undefined;
|
||||||
if (hasObject) {
|
if (hasObject) {
|
||||||
var filtered = list._filtered;
|
var filtered = list.__filtered;
|
||||||
if (!filtered) {
|
if (!filtered) {
|
||||||
filtered = list._filtered = Base.create(list[0]);
|
filtered = list.__filtered = Base.create(list[0]);
|
||||||
filtered._unfiltered = list[0];
|
filtered.__unfiltered = list[0];
|
||||||
}
|
}
|
||||||
filtered[name] = undefined;
|
filtered[name] = undefined;
|
||||||
}
|
}
|
||||||
return this.read(hasObject ? [value] : list, start, options, amount);
|
var l = hasObject ? [value] : list,
|
||||||
|
res = this.read(l, start, options, amount);
|
||||||
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
getNamed: function(list, name) {
|
getNamed: function(list, name) {
|
||||||
|
@ -386,7 +397,7 @@ Base.inject({
|
||||||
if (list._hasObject === undefined)
|
if (list._hasObject === undefined)
|
||||||
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
|
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
|
||||||
if (list._hasObject)
|
if (list._hasObject)
|
||||||
return name ? arg[name] : list._filtered || arg;
|
return name ? arg[name] : list.__filtered || arg;
|
||||||
},
|
},
|
||||||
|
|
||||||
hasNamed: function(list, name) {
|
hasNamed: function(list, name) {
|
||||||
|
@ -416,7 +427,7 @@ Base.inject({
|
||||||
processed = keys;
|
processed = keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(source._unfiltered || source).forEach(handleKey);
|
Object.keys(source.__unfiltered || source).forEach(handleKey);
|
||||||
return dest;
|
return dest;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -462,8 +473,7 @@ Base.inject({
|
||||||
} else if (Array.isArray(obj)) {
|
} else if (Array.isArray(obj)) {
|
||||||
res = [];
|
res = [];
|
||||||
for (var i = 0, l = obj.length; i < l; i++)
|
for (var i = 0, l = obj.length; i < l; i++)
|
||||||
res[i] = Base.serialize(obj[i], options, compact,
|
res[i] = Base.serialize(obj[i], options, compact, dictionary);
|
||||||
dictionary);
|
|
||||||
} else if (Base.isPlainObject(obj)) {
|
} else if (Base.isPlainObject(obj)) {
|
||||||
res = {};
|
res = {};
|
||||||
var keys = Object.keys(obj);
|
var keys = Object.keys(obj);
|
||||||
|
@ -586,8 +596,7 @@ Base.inject({
|
||||||
hyphenate: function(str) {
|
hyphenate: function(str) {
|
||||||
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}});
|
||||||
});
|
|
||||||
|
|
||||||
var Emitter = {
|
var Emitter = {
|
||||||
on: function(type, func) {
|
on: function(type, func) {
|
||||||
|
@ -769,7 +778,7 @@ var PaperScope = Base.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
version: "0.11.2",
|
version: "0.11.3",
|
||||||
|
|
||||||
getView: function() {
|
getView: function() {
|
||||||
var project = this.project;
|
var project = this.project;
|
||||||
|
@ -1739,6 +1748,9 @@ var Rectangle = Base.extend({
|
||||||
}
|
}
|
||||||
this._set(x, y, width, height);
|
this._set(x, y, width, height);
|
||||||
read = arguments.__index;
|
read = arguments.__index;
|
||||||
|
var filtered = arguments.__filtered;
|
||||||
|
if (filtered)
|
||||||
|
this.__filtered = filtered;
|
||||||
}
|
}
|
||||||
if (this.__read)
|
if (this.__read)
|
||||||
this.__read = read;
|
this.__read = read;
|
||||||
|
@ -2262,7 +2274,7 @@ var Matrix = Base.extend({
|
||||||
return this.shear(shear, center);
|
return this.shear(shear, center);
|
||||||
},
|
},
|
||||||
|
|
||||||
append: function(mx) {
|
append: function(mx, _dontNotify) {
|
||||||
if (mx) {
|
if (mx) {
|
||||||
var a1 = this._a,
|
var a1 = this._a,
|
||||||
b1 = this._b,
|
b1 = this._b,
|
||||||
|
@ -2280,12 +2292,13 @@ var Matrix = Base.extend({
|
||||||
this._d = b2 * b1 + d2 * d1;
|
this._d = b2 * b1 + d2 * d1;
|
||||||
this._tx += tx2 * a1 + ty2 * c1;
|
this._tx += tx2 * a1 + ty2 * c1;
|
||||||
this._ty += tx2 * b1 + ty2 * d1;
|
this._ty += tx2 * b1 + ty2 * d1;
|
||||||
|
if (!_dontNotify)
|
||||||
this._changed();
|
this._changed();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
prepend: function(mx) {
|
prepend: function(mx, _dontNotify) {
|
||||||
if (mx) {
|
if (mx) {
|
||||||
var a1 = this._a,
|
var a1 = this._a,
|
||||||
b1 = this._b,
|
b1 = this._b,
|
||||||
|
@ -2305,6 +2318,7 @@ var Matrix = Base.extend({
|
||||||
this._d = c2 * c1 + d2 * d1;
|
this._d = c2 * c1 + d2 * d1;
|
||||||
this._tx = a2 * tx1 + b2 * ty1 + tx2;
|
this._tx = a2 * tx1 + b2 * ty1 + tx2;
|
||||||
this._ty = c2 * tx1 + d2 * ty1 + ty2;
|
this._ty = c2 * tx1 + d2 * ty1 + ty2;
|
||||||
|
if (!_dontNotify)
|
||||||
this._changed();
|
this._changed();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -3236,11 +3250,11 @@ new function() {
|
||||||
this._boundsOptions);
|
this._boundsOptions);
|
||||||
if (!opts.stroke || this.getStrokeScaling())
|
if (!opts.stroke || this.getStrokeScaling())
|
||||||
opts.cacheItem = this;
|
opts.cacheItem = this;
|
||||||
var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
|
var rect = this._getCachedBounds(hasMatrix && matrix, opts).rect;
|
||||||
return !arguments.length
|
return !arguments.length
|
||||||
? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
|
? new LinkedRectangle(rect.x, rect.y, rect.width, rect.height,
|
||||||
bounds.height, this, 'setBounds')
|
this, 'setBounds')
|
||||||
: bounds;
|
: rect;
|
||||||
},
|
},
|
||||||
|
|
||||||
setBounds: function() {
|
setBounds: function() {
|
||||||
|
@ -3273,29 +3287,49 @@ new function() {
|
||||||
return Item._getBounds(children, matrix, options);
|
return Item._getBounds(children, matrix, options);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_getBoundsCacheKey: function(options, internal) {
|
||||||
|
return [
|
||||||
|
options.stroke ? 1 : 0,
|
||||||
|
options.handle ? 1 : 0,
|
||||||
|
internal ? 1 : 0
|
||||||
|
].join('');
|
||||||
|
},
|
||||||
|
|
||||||
_getCachedBounds: function(matrix, options, noInternal) {
|
_getCachedBounds: function(matrix, options, noInternal) {
|
||||||
matrix = matrix && matrix._orNullIfIdentity();
|
matrix = matrix && matrix._orNullIfIdentity();
|
||||||
var internal = options.internal && !noInternal,
|
var internal = options.internal && !noInternal,
|
||||||
cacheItem = options.cacheItem,
|
cacheItem = options.cacheItem,
|
||||||
_matrix = internal ? null : this._matrix._orNullIfIdentity(),
|
_matrix = internal ? null : this._matrix._orNullIfIdentity(),
|
||||||
cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
|
cacheKey = cacheItem && (!matrix || matrix.equals(_matrix))
|
||||||
options.stroke ? 1 : 0,
|
&& this._getBoundsCacheKey(options, internal),
|
||||||
options.handle ? 1 : 0,
|
bounds = this._bounds;
|
||||||
internal ? 1 : 0
|
|
||||||
].join('');
|
|
||||||
Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
|
Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
|
||||||
if (cacheKey && this._bounds && cacheKey in this._bounds)
|
if (cacheKey && bounds && cacheKey in bounds) {
|
||||||
return this._bounds[cacheKey].rect.clone();
|
var cached = bounds[cacheKey];
|
||||||
var bounds = this._getBounds(matrix || _matrix, options);
|
return {
|
||||||
|
rect: cached.rect.clone(),
|
||||||
|
nonscaling: cached.nonscaling
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var res = this._getBounds(matrix || _matrix, options),
|
||||||
|
rect = res.rect || res,
|
||||||
|
style = this._style,
|
||||||
|
nonscaling = res.nonscaling || style.hasStroke()
|
||||||
|
&& !style.getStrokeScaling();
|
||||||
if (cacheKey) {
|
if (cacheKey) {
|
||||||
if (!this._bounds)
|
if (!bounds) {
|
||||||
this._bounds = {};
|
this._bounds = bounds = {};
|
||||||
var cached = this._bounds[cacheKey] = {
|
}
|
||||||
rect: bounds.clone(),
|
var cached = bounds[cacheKey] = {
|
||||||
|
rect: rect.clone(),
|
||||||
|
nonscaling: nonscaling,
|
||||||
internal: internal
|
internal: internal
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return bounds;
|
return {
|
||||||
|
rect: rect,
|
||||||
|
nonscaling: nonscaling
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
_getStrokeMatrix: function(matrix, options) {
|
_getStrokeMatrix: function(matrix, options) {
|
||||||
|
@ -3340,22 +3374,29 @@ new function() {
|
||||||
var x1 = Infinity,
|
var x1 = Infinity,
|
||||||
x2 = -x1,
|
x2 = -x1,
|
||||||
y1 = x1,
|
y1 = x1,
|
||||||
y2 = x2;
|
y2 = x2,
|
||||||
|
nonscaling = false;
|
||||||
options = options || {};
|
options = options || {};
|
||||||
for (var i = 0, l = items.length; i < l; i++) {
|
for (var i = 0, l = items.length; i < l; i++) {
|
||||||
var item = items[i];
|
var item = items[i];
|
||||||
if (item._visible && !item.isEmpty()) {
|
if (item._visible && !item.isEmpty()) {
|
||||||
var rect = item._getCachedBounds(
|
var bounds = item._getCachedBounds(
|
||||||
matrix && matrix.appended(item._matrix), options, true);
|
matrix && matrix.appended(item._matrix), options, true),
|
||||||
|
rect = bounds.rect;
|
||||||
x1 = Math.min(rect.x, x1);
|
x1 = Math.min(rect.x, x1);
|
||||||
y1 = Math.min(rect.y, y1);
|
y1 = Math.min(rect.y, y1);
|
||||||
x2 = Math.max(rect.x + rect.width, x2);
|
x2 = Math.max(rect.x + rect.width, x2);
|
||||||
y2 = Math.max(rect.y + rect.height, y2);
|
y2 = Math.max(rect.y + rect.height, y2);
|
||||||
|
if (bounds.nonscaling)
|
||||||
|
nonscaling = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isFinite(x1)
|
return {
|
||||||
|
rect: isFinite(x1)
|
||||||
? new Rectangle(x1, y1, x2 - x1, y2 - y1)
|
? new Rectangle(x1, y1, x2 - x1, y2 - y1)
|
||||||
: new Rectangle();
|
: new Rectangle(),
|
||||||
|
nonscaling: nonscaling
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3395,8 +3436,18 @@ new function() {
|
||||||
var current = this.getScaling(),
|
var current = this.getScaling(),
|
||||||
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
|
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
|
||||||
if (current && scaling && !current.equals(scaling)) {
|
if (current && scaling && !current.equals(scaling)) {
|
||||||
var decomposed = this._decomposed;
|
var rotation = this.getRotation(),
|
||||||
this.scale(scaling.x / current.x, scaling.y / current.y);
|
decomposed = this._decomposed,
|
||||||
|
matrix = new Matrix(),
|
||||||
|
center = this.getPosition(true);
|
||||||
|
matrix.translate(center);
|
||||||
|
if (rotation)
|
||||||
|
matrix.rotate(rotation);
|
||||||
|
matrix.scale(scaling.x / current.x, scaling.y / current.y);
|
||||||
|
if (rotation)
|
||||||
|
matrix.rotate(-rotation);
|
||||||
|
matrix.translate(center.negate());
|
||||||
|
this.transform(matrix);
|
||||||
if (decomposed) {
|
if (decomposed) {
|
||||||
decomposed.scaling = scaling;
|
decomposed.scaling = scaling;
|
||||||
this._decomposed = decomposed;
|
this._decomposed = decomposed;
|
||||||
|
@ -4218,8 +4269,6 @@ new function() {
|
||||||
|
|
||||||
transform: function(matrix, _applyMatrix, _applyRecursively,
|
transform: function(matrix, _applyMatrix, _applyRecursively,
|
||||||
_setApplyMatrix) {
|
_setApplyMatrix) {
|
||||||
if (matrix && matrix.isIdentity())
|
|
||||||
matrix = null;
|
|
||||||
var _matrix = this._matrix,
|
var _matrix = this._matrix,
|
||||||
transform = matrix && !matrix.isIdentity(),
|
transform = matrix && !matrix.isIdentity(),
|
||||||
applyMatrix = (_applyMatrix || this._applyMatrix)
|
applyMatrix = (_applyMatrix || this._applyMatrix)
|
||||||
|
@ -4230,22 +4279,7 @@ new function() {
|
||||||
if (transform) {
|
if (transform) {
|
||||||
if (!matrix.isInvertible() && _matrix.isInvertible())
|
if (!matrix.isInvertible() && _matrix.isInvertible())
|
||||||
_matrix._backup = _matrix.getValues();
|
_matrix._backup = _matrix.getValues();
|
||||||
_matrix.prepend(matrix);
|
_matrix.prepend(matrix, true);
|
||||||
}
|
|
||||||
if (applyMatrix) {
|
|
||||||
if (this._transformContent(_matrix, _applyRecursively,
|
|
||||||
_setApplyMatrix)) {
|
|
||||||
var pivot = this._pivot;
|
|
||||||
if (pivot)
|
|
||||||
_matrix._transformPoint(pivot, pivot, true);
|
|
||||||
_matrix.reset(true);
|
|
||||||
if (_setApplyMatrix && this._canApplyMatrix)
|
|
||||||
this._applyMatrix = true;
|
|
||||||
} else {
|
|
||||||
applyMatrix = transform = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (transform) {
|
|
||||||
var style = this._style,
|
var style = this._style,
|
||||||
fillColor = style.getFillColor(true),
|
fillColor = style.getFillColor(true),
|
||||||
strokeColor = style.getStrokeColor(true);
|
strokeColor = style.getStrokeColor(true);
|
||||||
|
@ -4254,24 +4288,38 @@ new function() {
|
||||||
if (strokeColor)
|
if (strokeColor)
|
||||||
strokeColor.transform(matrix);
|
strokeColor.transform(matrix);
|
||||||
}
|
}
|
||||||
|
if (applyMatrix && (applyMatrix = this._transformContent(_matrix,
|
||||||
|
_applyRecursively, _setApplyMatrix))) {
|
||||||
|
var pivot = this._pivot;
|
||||||
|
if (pivot)
|
||||||
|
_matrix._transformPoint(pivot, pivot, true);
|
||||||
|
_matrix.reset(true);
|
||||||
|
if (_setApplyMatrix && this._canApplyMatrix)
|
||||||
|
this._applyMatrix = true;
|
||||||
|
}
|
||||||
var bounds = this._bounds,
|
var bounds = this._bounds,
|
||||||
position = this._position;
|
position = this._position;
|
||||||
|
if (transform || applyMatrix) {
|
||||||
this._changed(9);
|
this._changed(9);
|
||||||
var decomp = bounds && matrix && matrix.decompose();
|
}
|
||||||
if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
|
var decomp = transform && bounds && matrix.decompose();
|
||||||
|
if (decomp && decomp.skewing.isZero() && decomp.rotation % 90 === 0) {
|
||||||
for (var key in bounds) {
|
for (var key in bounds) {
|
||||||
var cache = bounds[key];
|
var cache = bounds[key];
|
||||||
if (applyMatrix || !cache.internal) {
|
if (cache.nonscaling) {
|
||||||
|
delete bounds[key];
|
||||||
|
} else if (applyMatrix || !cache.internal) {
|
||||||
var rect = cache.rect;
|
var rect = cache.rect;
|
||||||
matrix._transformBounds(rect, rect);
|
matrix._transformBounds(rect, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var getter = this._boundsGetter,
|
|
||||||
rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
|
|
||||||
if (rect)
|
|
||||||
this._position = rect.getCenter(true);
|
|
||||||
this._bounds = bounds;
|
this._bounds = bounds;
|
||||||
} else if (matrix && position) {
|
var cached = bounds[this._getBoundsCacheKey(
|
||||||
|
this._boundsOptions || {})];
|
||||||
|
if (cached) {
|
||||||
|
this._position = cached.rect.getCenter(true);
|
||||||
|
}
|
||||||
|
} else if (transform && position && this._pivot) {
|
||||||
this._position = matrix._transformPoint(position, position);
|
this._position = matrix._transformPoint(position, position);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -5483,10 +5531,8 @@ var HitResult = Base.extend({
|
||||||
initialize: function HitResult(type, item, values) {
|
initialize: function HitResult(type, item, values) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
if (values) {
|
if (values)
|
||||||
values.enumerable = true;
|
|
||||||
this.inject(values);
|
this.inject(values);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
statics: {
|
statics: {
|
||||||
|
@ -7006,7 +7052,7 @@ new function() {
|
||||||
cos = Math.cos(angle),
|
cos = Math.cos(angle),
|
||||||
rv = [],
|
rv = [],
|
||||||
roots = [];
|
roots = [];
|
||||||
for(var i = 0; i < 8; i += 2) {
|
for (var i = 0; i < 8; i += 2) {
|
||||||
var x = v[i] - px,
|
var x = v[i] - px,
|
||||||
y = v[i + 1] - py;
|
y = v[i + 1] - py;
|
||||||
rv.push(
|
rv.push(
|
||||||
|
@ -11016,10 +11062,10 @@ var PointText = TextItem.extend({
|
||||||
x = 0;
|
x = 0;
|
||||||
if (justification !== 'left')
|
if (justification !== 'left')
|
||||||
x -= width / (justification === 'center' ? 2: 1);
|
x -= width / (justification === 'center' ? 2: 1);
|
||||||
var bounds = new Rectangle(x,
|
var rect = new Rectangle(x,
|
||||||
numLines ? - 0.75 * leading : 0,
|
numLines ? - 0.75 * leading : 0,
|
||||||
width, numLines * leading);
|
width, numLines * leading);
|
||||||
return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
|
return matrix ? matrix._transformBounds(rect, rect) : rect;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -12694,8 +12740,8 @@ new function() {
|
||||||
point, prevPoint)
|
point, prevPoint)
|
||||||
|| hitItem && hitItem !== dragItem
|
|| hitItem && hitItem !== dragItem
|
||||||
&& !hitItem.isDescendant(dragItem)
|
&& !hitItem.isDescendant(dragItem)
|
||||||
&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
|
&& emitMouseEvent(hitItem, null, type, event, point, prevPoint,
|
||||||
point, prevPoint, dragItem)
|
dragItem)
|
||||||
|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
|
|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
|
||||||
point, prevPoint));
|
point, prevPoint));
|
||||||
}
|
}
|
||||||
|
@ -13807,9 +13853,9 @@ new function() {
|
||||||
if (!Numerical.isZero(scale.x - 1)
|
if (!Numerical.isZero(scale.x - 1)
|
||||||
|| !Numerical.isZero(scale.y - 1))
|
|| !Numerical.isZero(scale.y - 1))
|
||||||
parts.push('scale(' + formatter.point(scale) +')');
|
parts.push('scale(' + formatter.point(scale) +')');
|
||||||
if (skew && skew.x)
|
if (skew.x)
|
||||||
parts.push('skewX(' + formatter.number(skew.x) + ')');
|
parts.push('skewX(' + formatter.number(skew.x) + ')');
|
||||||
if (skew && skew.y)
|
if (skew.y)
|
||||||
parts.push('skewY(' + formatter.number(skew.y) + ')');
|
parts.push('skewY(' + formatter.number(skew.y) + ')');
|
||||||
attrs.transform = parts.join(' ');
|
attrs.transform = parts.join(' ');
|
||||||
} else {
|
} else {
|
||||||
|
@ -13870,8 +13916,9 @@ new function() {
|
||||||
if (length > 2) {
|
if (length > 2) {
|
||||||
type = item._closed ? 'polygon' : 'polyline';
|
type = item._closed ? 'polygon' : 'polyline';
|
||||||
var parts = [];
|
var parts = [];
|
||||||
for(var i = 0; i < length; i++)
|
for (var i = 0; i < length; i++) {
|
||||||
parts.push(formatter.point(segments[i]._point));
|
parts.push(formatter.point(segments[i]._point));
|
||||||
|
}
|
||||||
attrs.points = parts.join(' ');
|
attrs.points = parts.join(' ');
|
||||||
} else {
|
} else {
|
||||||
type = 'line';
|
type = 'line';
|
||||||
|
@ -14142,6 +14189,7 @@ new function() {
|
||||||
? new Rectangle([0, 0], view.getViewSize())
|
? new Rectangle([0, 0], view.getViewSize())
|
||||||
: bounds === 'content'
|
: bounds === 'content'
|
||||||
? Item._getBounds(children, matrix, { stroke: true })
|
? Item._getBounds(children, matrix, { stroke: true })
|
||||||
|
.rect
|
||||||
: Rectangle.read([bounds], 0, { readNull: true }),
|
: Rectangle.read([bounds], 0, { readNull: true }),
|
||||||
attrs = {
|
attrs = {
|
||||||
version: '1.1',
|
version: '1.1',
|
||||||
|
@ -14715,7 +14763,6 @@ new function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
paper = new (PaperScope.inject(Base.exports, {
|
paper = new (PaperScope.inject(Base.exports, {
|
||||||
enumerable: true,
|
|
||||||
Base: Base,
|
Base: Base,
|
||||||
Numerical: Numerical,
|
Numerical: Numerical,
|
||||||
Key: Key,
|
Key: Key,
|
||||||
|
|
223
dist/paper-full.js
vendored
223
dist/paper-full.js
vendored
|
@ -1,5 +1,5 @@
|
||||||
/*!
|
/*!
|
||||||
* Paper.js v0.11.2 - The Swiss Army Knife of Vector Graphics Scripting.
|
* Paper.js v0.11.3 - The Swiss Army Knife of Vector Graphics Scripting.
|
||||||
* http://paperjs.org/
|
* http://paperjs.org/
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
|
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Date: Thu Apr 20 19:14:30 2017 +0200
|
* Date: Sat Apr 22 20:01:34 2017 +0200
|
||||||
*
|
*
|
||||||
***
|
***
|
||||||
*
|
*
|
||||||
|
@ -98,12 +98,13 @@ var Base = new function() {
|
||||||
&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
|
&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
|
||||||
beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
|
beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
|
||||||
if (!res || isFunc || !res.get || typeof res.get !== 'function'
|
if (!res || isFunc || !res.get || typeof res.get !== 'function'
|
||||||
|| !Base.isPlainObject(res))
|
|| !Base.isPlainObject(res)) {
|
||||||
res = { value: res, writable: true };
|
res = { value: res, writable: true };
|
||||||
|
}
|
||||||
if ((describe(dest, name)
|
if ((describe(dest, name)
|
||||||
|| { configurable: true }).configurable) {
|
|| { configurable: true }).configurable) {
|
||||||
res.configurable = true;
|
res.configurable = true;
|
||||||
res.enumerable = enumerable;
|
res.enumerable = enumerable != null ? enumerable : !bean;
|
||||||
}
|
}
|
||||||
define(dest, name, res);
|
define(dest, name, res);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,7 @@ var Base = new function() {
|
||||||
preserve = src.preserve;
|
preserve = src.preserve;
|
||||||
if (statics !== src)
|
if (statics !== src)
|
||||||
inject(this.prototype, src, src.enumerable, beans, preserve);
|
inject(this.prototype, src, src.enumerable, beans, preserve);
|
||||||
inject(this, statics, true, beans, preserve);
|
inject(this, statics, null, beans, preserve);
|
||||||
}
|
}
|
||||||
for (var i = 1, l = arguments.length; i < l; i++)
|
for (var i = 1, l = arguments.length; i < l; i++)
|
||||||
this.inject(arguments[i]);
|
this.inject(arguments[i]);
|
||||||
|
@ -164,13 +165,15 @@ var Base = new function() {
|
||||||
proto = ctor.prototype = proto || create(this.prototype);
|
proto = ctor.prototype = proto || create(this.prototype);
|
||||||
define(proto, 'constructor',
|
define(proto, 'constructor',
|
||||||
{ value: ctor, writable: true, configurable: true });
|
{ value: ctor, writable: true, configurable: true });
|
||||||
inject(ctor, this, true);
|
inject(ctor, this);
|
||||||
if (arguments.length)
|
if (arguments.length)
|
||||||
this.inject.apply(ctor, arguments);
|
this.inject.apply(ctor, arguments);
|
||||||
ctor.base = base;
|
ctor.base = base;
|
||||||
return ctor;
|
return ctor;
|
||||||
}
|
}
|
||||||
}, true).inject({
|
}).inject({
|
||||||
|
enumerable: false,
|
||||||
|
|
||||||
initialize: Base,
|
initialize: Base,
|
||||||
|
|
||||||
set: Base,
|
set: Base,
|
||||||
|
@ -230,6 +233,8 @@ if (typeof module !== 'undefined')
|
||||||
module.exports = Base;
|
module.exports = Base;
|
||||||
|
|
||||||
Base.inject({
|
Base.inject({
|
||||||
|
enumerable: false,
|
||||||
|
|
||||||
toString: function() {
|
toString: function() {
|
||||||
return this._id != null
|
return this._id != null
|
||||||
? (this._class || 'Object') + (this._name
|
? (this._class || 'Object') + (this._name
|
||||||
|
@ -265,13 +270,12 @@ Base.inject({
|
||||||
if (props)
|
if (props)
|
||||||
Base.filter(this, props, exclude, this._prioritize);
|
Base.filter(this, props, exclude, this._prioritize);
|
||||||
return this;
|
return this;
|
||||||
},
|
}
|
||||||
|
}, {
|
||||||
|
|
||||||
statics: {
|
beans: false,
|
||||||
|
statics: {
|
||||||
exports: {
|
exports: {},
|
||||||
enumerable: true
|
|
||||||
},
|
|
||||||
|
|
||||||
extend: function extend() {
|
extend: function extend() {
|
||||||
var res = extend.base.apply(this, arguments),
|
var res = extend.base.apply(this, arguments),
|
||||||
|
@ -341,6 +345,11 @@ Base.inject({
|
||||||
: list) || obj;
|
: list) || obj;
|
||||||
if (readIndex) {
|
if (readIndex) {
|
||||||
list.__index = begin + obj.__read;
|
list.__index = begin + obj.__read;
|
||||||
|
var filtered = obj.__filtered;
|
||||||
|
if (filtered) {
|
||||||
|
list.__filtered = filtered;
|
||||||
|
obj.__filtered = undefined;
|
||||||
|
}
|
||||||
obj.__read = undefined;
|
obj.__read = undefined;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -371,14 +380,16 @@ Base.inject({
|
||||||
var value = this.getNamed(list, name),
|
var value = this.getNamed(list, name),
|
||||||
hasObject = value !== undefined;
|
hasObject = value !== undefined;
|
||||||
if (hasObject) {
|
if (hasObject) {
|
||||||
var filtered = list._filtered;
|
var filtered = list.__filtered;
|
||||||
if (!filtered) {
|
if (!filtered) {
|
||||||
filtered = list._filtered = Base.create(list[0]);
|
filtered = list.__filtered = Base.create(list[0]);
|
||||||
filtered._unfiltered = list[0];
|
filtered.__unfiltered = list[0];
|
||||||
}
|
}
|
||||||
filtered[name] = undefined;
|
filtered[name] = undefined;
|
||||||
}
|
}
|
||||||
return this.read(hasObject ? [value] : list, start, options, amount);
|
var l = hasObject ? [value] : list,
|
||||||
|
res = this.read(l, start, options, amount);
|
||||||
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
getNamed: function(list, name) {
|
getNamed: function(list, name) {
|
||||||
|
@ -386,7 +397,7 @@ Base.inject({
|
||||||
if (list._hasObject === undefined)
|
if (list._hasObject === undefined)
|
||||||
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
|
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
|
||||||
if (list._hasObject)
|
if (list._hasObject)
|
||||||
return name ? arg[name] : list._filtered || arg;
|
return name ? arg[name] : list.__filtered || arg;
|
||||||
},
|
},
|
||||||
|
|
||||||
hasNamed: function(list, name) {
|
hasNamed: function(list, name) {
|
||||||
|
@ -416,7 +427,7 @@ Base.inject({
|
||||||
processed = keys;
|
processed = keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(source._unfiltered || source).forEach(handleKey);
|
Object.keys(source.__unfiltered || source).forEach(handleKey);
|
||||||
return dest;
|
return dest;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -462,8 +473,7 @@ Base.inject({
|
||||||
} else if (Array.isArray(obj)) {
|
} else if (Array.isArray(obj)) {
|
||||||
res = [];
|
res = [];
|
||||||
for (var i = 0, l = obj.length; i < l; i++)
|
for (var i = 0, l = obj.length; i < l; i++)
|
||||||
res[i] = Base.serialize(obj[i], options, compact,
|
res[i] = Base.serialize(obj[i], options, compact, dictionary);
|
||||||
dictionary);
|
|
||||||
} else if (Base.isPlainObject(obj)) {
|
} else if (Base.isPlainObject(obj)) {
|
||||||
res = {};
|
res = {};
|
||||||
var keys = Object.keys(obj);
|
var keys = Object.keys(obj);
|
||||||
|
@ -586,8 +596,7 @@ Base.inject({
|
||||||
hyphenate: function(str) {
|
hyphenate: function(str) {
|
||||||
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}});
|
||||||
});
|
|
||||||
|
|
||||||
var Emitter = {
|
var Emitter = {
|
||||||
on: function(type, func) {
|
on: function(type, func) {
|
||||||
|
@ -769,7 +778,7 @@ var PaperScope = Base.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
version: "0.11.2",
|
version: "0.11.3",
|
||||||
|
|
||||||
getView: function() {
|
getView: function() {
|
||||||
var project = this.project;
|
var project = this.project;
|
||||||
|
@ -1739,6 +1748,9 @@ var Rectangle = Base.extend({
|
||||||
}
|
}
|
||||||
this._set(x, y, width, height);
|
this._set(x, y, width, height);
|
||||||
read = arguments.__index;
|
read = arguments.__index;
|
||||||
|
var filtered = arguments.__filtered;
|
||||||
|
if (filtered)
|
||||||
|
this.__filtered = filtered;
|
||||||
}
|
}
|
||||||
if (this.__read)
|
if (this.__read)
|
||||||
this.__read = read;
|
this.__read = read;
|
||||||
|
@ -2262,7 +2274,7 @@ var Matrix = Base.extend({
|
||||||
return this.shear(shear, center);
|
return this.shear(shear, center);
|
||||||
},
|
},
|
||||||
|
|
||||||
append: function(mx) {
|
append: function(mx, _dontNotify) {
|
||||||
if (mx) {
|
if (mx) {
|
||||||
var a1 = this._a,
|
var a1 = this._a,
|
||||||
b1 = this._b,
|
b1 = this._b,
|
||||||
|
@ -2280,12 +2292,13 @@ var Matrix = Base.extend({
|
||||||
this._d = b2 * b1 + d2 * d1;
|
this._d = b2 * b1 + d2 * d1;
|
||||||
this._tx += tx2 * a1 + ty2 * c1;
|
this._tx += tx2 * a1 + ty2 * c1;
|
||||||
this._ty += tx2 * b1 + ty2 * d1;
|
this._ty += tx2 * b1 + ty2 * d1;
|
||||||
|
if (!_dontNotify)
|
||||||
this._changed();
|
this._changed();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
prepend: function(mx) {
|
prepend: function(mx, _dontNotify) {
|
||||||
if (mx) {
|
if (mx) {
|
||||||
var a1 = this._a,
|
var a1 = this._a,
|
||||||
b1 = this._b,
|
b1 = this._b,
|
||||||
|
@ -2305,6 +2318,7 @@ var Matrix = Base.extend({
|
||||||
this._d = c2 * c1 + d2 * d1;
|
this._d = c2 * c1 + d2 * d1;
|
||||||
this._tx = a2 * tx1 + b2 * ty1 + tx2;
|
this._tx = a2 * tx1 + b2 * ty1 + tx2;
|
||||||
this._ty = c2 * tx1 + d2 * ty1 + ty2;
|
this._ty = c2 * tx1 + d2 * ty1 + ty2;
|
||||||
|
if (!_dontNotify)
|
||||||
this._changed();
|
this._changed();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -3236,11 +3250,11 @@ new function() {
|
||||||
this._boundsOptions);
|
this._boundsOptions);
|
||||||
if (!opts.stroke || this.getStrokeScaling())
|
if (!opts.stroke || this.getStrokeScaling())
|
||||||
opts.cacheItem = this;
|
opts.cacheItem = this;
|
||||||
var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
|
var rect = this._getCachedBounds(hasMatrix && matrix, opts).rect;
|
||||||
return !arguments.length
|
return !arguments.length
|
||||||
? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
|
? new LinkedRectangle(rect.x, rect.y, rect.width, rect.height,
|
||||||
bounds.height, this, 'setBounds')
|
this, 'setBounds')
|
||||||
: bounds;
|
: rect;
|
||||||
},
|
},
|
||||||
|
|
||||||
setBounds: function() {
|
setBounds: function() {
|
||||||
|
@ -3273,29 +3287,49 @@ new function() {
|
||||||
return Item._getBounds(children, matrix, options);
|
return Item._getBounds(children, matrix, options);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_getBoundsCacheKey: function(options, internal) {
|
||||||
|
return [
|
||||||
|
options.stroke ? 1 : 0,
|
||||||
|
options.handle ? 1 : 0,
|
||||||
|
internal ? 1 : 0
|
||||||
|
].join('');
|
||||||
|
},
|
||||||
|
|
||||||
_getCachedBounds: function(matrix, options, noInternal) {
|
_getCachedBounds: function(matrix, options, noInternal) {
|
||||||
matrix = matrix && matrix._orNullIfIdentity();
|
matrix = matrix && matrix._orNullIfIdentity();
|
||||||
var internal = options.internal && !noInternal,
|
var internal = options.internal && !noInternal,
|
||||||
cacheItem = options.cacheItem,
|
cacheItem = options.cacheItem,
|
||||||
_matrix = internal ? null : this._matrix._orNullIfIdentity(),
|
_matrix = internal ? null : this._matrix._orNullIfIdentity(),
|
||||||
cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
|
cacheKey = cacheItem && (!matrix || matrix.equals(_matrix))
|
||||||
options.stroke ? 1 : 0,
|
&& this._getBoundsCacheKey(options, internal),
|
||||||
options.handle ? 1 : 0,
|
bounds = this._bounds;
|
||||||
internal ? 1 : 0
|
|
||||||
].join('');
|
|
||||||
Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
|
Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
|
||||||
if (cacheKey && this._bounds && cacheKey in this._bounds)
|
if (cacheKey && bounds && cacheKey in bounds) {
|
||||||
return this._bounds[cacheKey].rect.clone();
|
var cached = bounds[cacheKey];
|
||||||
var bounds = this._getBounds(matrix || _matrix, options);
|
return {
|
||||||
|
rect: cached.rect.clone(),
|
||||||
|
nonscaling: cached.nonscaling
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var res = this._getBounds(matrix || _matrix, options),
|
||||||
|
rect = res.rect || res,
|
||||||
|
style = this._style,
|
||||||
|
nonscaling = res.nonscaling || style.hasStroke()
|
||||||
|
&& !style.getStrokeScaling();
|
||||||
if (cacheKey) {
|
if (cacheKey) {
|
||||||
if (!this._bounds)
|
if (!bounds) {
|
||||||
this._bounds = {};
|
this._bounds = bounds = {};
|
||||||
var cached = this._bounds[cacheKey] = {
|
}
|
||||||
rect: bounds.clone(),
|
var cached = bounds[cacheKey] = {
|
||||||
|
rect: rect.clone(),
|
||||||
|
nonscaling: nonscaling,
|
||||||
internal: internal
|
internal: internal
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return bounds;
|
return {
|
||||||
|
rect: rect,
|
||||||
|
nonscaling: nonscaling
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
_getStrokeMatrix: function(matrix, options) {
|
_getStrokeMatrix: function(matrix, options) {
|
||||||
|
@ -3340,22 +3374,29 @@ new function() {
|
||||||
var x1 = Infinity,
|
var x1 = Infinity,
|
||||||
x2 = -x1,
|
x2 = -x1,
|
||||||
y1 = x1,
|
y1 = x1,
|
||||||
y2 = x2;
|
y2 = x2,
|
||||||
|
nonscaling = false;
|
||||||
options = options || {};
|
options = options || {};
|
||||||
for (var i = 0, l = items.length; i < l; i++) {
|
for (var i = 0, l = items.length; i < l; i++) {
|
||||||
var item = items[i];
|
var item = items[i];
|
||||||
if (item._visible && !item.isEmpty()) {
|
if (item._visible && !item.isEmpty()) {
|
||||||
var rect = item._getCachedBounds(
|
var bounds = item._getCachedBounds(
|
||||||
matrix && matrix.appended(item._matrix), options, true);
|
matrix && matrix.appended(item._matrix), options, true),
|
||||||
|
rect = bounds.rect;
|
||||||
x1 = Math.min(rect.x, x1);
|
x1 = Math.min(rect.x, x1);
|
||||||
y1 = Math.min(rect.y, y1);
|
y1 = Math.min(rect.y, y1);
|
||||||
x2 = Math.max(rect.x + rect.width, x2);
|
x2 = Math.max(rect.x + rect.width, x2);
|
||||||
y2 = Math.max(rect.y + rect.height, y2);
|
y2 = Math.max(rect.y + rect.height, y2);
|
||||||
|
if (bounds.nonscaling)
|
||||||
|
nonscaling = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isFinite(x1)
|
return {
|
||||||
|
rect: isFinite(x1)
|
||||||
? new Rectangle(x1, y1, x2 - x1, y2 - y1)
|
? new Rectangle(x1, y1, x2 - x1, y2 - y1)
|
||||||
: new Rectangle();
|
: new Rectangle(),
|
||||||
|
nonscaling: nonscaling
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3395,8 +3436,18 @@ new function() {
|
||||||
var current = this.getScaling(),
|
var current = this.getScaling(),
|
||||||
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
|
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
|
||||||
if (current && scaling && !current.equals(scaling)) {
|
if (current && scaling && !current.equals(scaling)) {
|
||||||
var decomposed = this._decomposed;
|
var rotation = this.getRotation(),
|
||||||
this.scale(scaling.x / current.x, scaling.y / current.y);
|
decomposed = this._decomposed,
|
||||||
|
matrix = new Matrix(),
|
||||||
|
center = this.getPosition(true);
|
||||||
|
matrix.translate(center);
|
||||||
|
if (rotation)
|
||||||
|
matrix.rotate(rotation);
|
||||||
|
matrix.scale(scaling.x / current.x, scaling.y / current.y);
|
||||||
|
if (rotation)
|
||||||
|
matrix.rotate(-rotation);
|
||||||
|
matrix.translate(center.negate());
|
||||||
|
this.transform(matrix);
|
||||||
if (decomposed) {
|
if (decomposed) {
|
||||||
decomposed.scaling = scaling;
|
decomposed.scaling = scaling;
|
||||||
this._decomposed = decomposed;
|
this._decomposed = decomposed;
|
||||||
|
@ -4218,8 +4269,6 @@ new function() {
|
||||||
|
|
||||||
transform: function(matrix, _applyMatrix, _applyRecursively,
|
transform: function(matrix, _applyMatrix, _applyRecursively,
|
||||||
_setApplyMatrix) {
|
_setApplyMatrix) {
|
||||||
if (matrix && matrix.isIdentity())
|
|
||||||
matrix = null;
|
|
||||||
var _matrix = this._matrix,
|
var _matrix = this._matrix,
|
||||||
transform = matrix && !matrix.isIdentity(),
|
transform = matrix && !matrix.isIdentity(),
|
||||||
applyMatrix = (_applyMatrix || this._applyMatrix)
|
applyMatrix = (_applyMatrix || this._applyMatrix)
|
||||||
|
@ -4230,22 +4279,7 @@ new function() {
|
||||||
if (transform) {
|
if (transform) {
|
||||||
if (!matrix.isInvertible() && _matrix.isInvertible())
|
if (!matrix.isInvertible() && _matrix.isInvertible())
|
||||||
_matrix._backup = _matrix.getValues();
|
_matrix._backup = _matrix.getValues();
|
||||||
_matrix.prepend(matrix);
|
_matrix.prepend(matrix, true);
|
||||||
}
|
|
||||||
if (applyMatrix) {
|
|
||||||
if (this._transformContent(_matrix, _applyRecursively,
|
|
||||||
_setApplyMatrix)) {
|
|
||||||
var pivot = this._pivot;
|
|
||||||
if (pivot)
|
|
||||||
_matrix._transformPoint(pivot, pivot, true);
|
|
||||||
_matrix.reset(true);
|
|
||||||
if (_setApplyMatrix && this._canApplyMatrix)
|
|
||||||
this._applyMatrix = true;
|
|
||||||
} else {
|
|
||||||
applyMatrix = transform = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (transform) {
|
|
||||||
var style = this._style,
|
var style = this._style,
|
||||||
fillColor = style.getFillColor(true),
|
fillColor = style.getFillColor(true),
|
||||||
strokeColor = style.getStrokeColor(true);
|
strokeColor = style.getStrokeColor(true);
|
||||||
|
@ -4254,24 +4288,38 @@ new function() {
|
||||||
if (strokeColor)
|
if (strokeColor)
|
||||||
strokeColor.transform(matrix);
|
strokeColor.transform(matrix);
|
||||||
}
|
}
|
||||||
|
if (applyMatrix && (applyMatrix = this._transformContent(_matrix,
|
||||||
|
_applyRecursively, _setApplyMatrix))) {
|
||||||
|
var pivot = this._pivot;
|
||||||
|
if (pivot)
|
||||||
|
_matrix._transformPoint(pivot, pivot, true);
|
||||||
|
_matrix.reset(true);
|
||||||
|
if (_setApplyMatrix && this._canApplyMatrix)
|
||||||
|
this._applyMatrix = true;
|
||||||
|
}
|
||||||
var bounds = this._bounds,
|
var bounds = this._bounds,
|
||||||
position = this._position;
|
position = this._position;
|
||||||
|
if (transform || applyMatrix) {
|
||||||
this._changed(9);
|
this._changed(9);
|
||||||
var decomp = bounds && matrix && matrix.decompose();
|
}
|
||||||
if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
|
var decomp = transform && bounds && matrix.decompose();
|
||||||
|
if (decomp && decomp.skewing.isZero() && decomp.rotation % 90 === 0) {
|
||||||
for (var key in bounds) {
|
for (var key in bounds) {
|
||||||
var cache = bounds[key];
|
var cache = bounds[key];
|
||||||
if (applyMatrix || !cache.internal) {
|
if (cache.nonscaling) {
|
||||||
|
delete bounds[key];
|
||||||
|
} else if (applyMatrix || !cache.internal) {
|
||||||
var rect = cache.rect;
|
var rect = cache.rect;
|
||||||
matrix._transformBounds(rect, rect);
|
matrix._transformBounds(rect, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var getter = this._boundsGetter,
|
|
||||||
rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
|
|
||||||
if (rect)
|
|
||||||
this._position = rect.getCenter(true);
|
|
||||||
this._bounds = bounds;
|
this._bounds = bounds;
|
||||||
} else if (matrix && position) {
|
var cached = bounds[this._getBoundsCacheKey(
|
||||||
|
this._boundsOptions || {})];
|
||||||
|
if (cached) {
|
||||||
|
this._position = cached.rect.getCenter(true);
|
||||||
|
}
|
||||||
|
} else if (transform && position && this._pivot) {
|
||||||
this._position = matrix._transformPoint(position, position);
|
this._position = matrix._transformPoint(position, position);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -5483,10 +5531,8 @@ var HitResult = Base.extend({
|
||||||
initialize: function HitResult(type, item, values) {
|
initialize: function HitResult(type, item, values) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
if (values) {
|
if (values)
|
||||||
values.enumerable = true;
|
|
||||||
this.inject(values);
|
this.inject(values);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
statics: {
|
statics: {
|
||||||
|
@ -7006,7 +7052,7 @@ new function() {
|
||||||
cos = Math.cos(angle),
|
cos = Math.cos(angle),
|
||||||
rv = [],
|
rv = [],
|
||||||
roots = [];
|
roots = [];
|
||||||
for(var i = 0; i < 8; i += 2) {
|
for (var i = 0; i < 8; i += 2) {
|
||||||
var x = v[i] - px,
|
var x = v[i] - px,
|
||||||
y = v[i + 1] - py;
|
y = v[i + 1] - py;
|
||||||
rv.push(
|
rv.push(
|
||||||
|
@ -11016,10 +11062,10 @@ var PointText = TextItem.extend({
|
||||||
x = 0;
|
x = 0;
|
||||||
if (justification !== 'left')
|
if (justification !== 'left')
|
||||||
x -= width / (justification === 'center' ? 2: 1);
|
x -= width / (justification === 'center' ? 2: 1);
|
||||||
var bounds = new Rectangle(x,
|
var rect = new Rectangle(x,
|
||||||
numLines ? - 0.75 * leading : 0,
|
numLines ? - 0.75 * leading : 0,
|
||||||
width, numLines * leading);
|
width, numLines * leading);
|
||||||
return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
|
return matrix ? matrix._transformBounds(rect, rect) : rect;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -12694,8 +12740,8 @@ new function() {
|
||||||
point, prevPoint)
|
point, prevPoint)
|
||||||
|| hitItem && hitItem !== dragItem
|
|| hitItem && hitItem !== dragItem
|
||||||
&& !hitItem.isDescendant(dragItem)
|
&& !hitItem.isDescendant(dragItem)
|
||||||
&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
|
&& emitMouseEvent(hitItem, null, type, event, point, prevPoint,
|
||||||
point, prevPoint, dragItem)
|
dragItem)
|
||||||
|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
|
|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
|
||||||
point, prevPoint));
|
point, prevPoint));
|
||||||
}
|
}
|
||||||
|
@ -13807,9 +13853,9 @@ new function() {
|
||||||
if (!Numerical.isZero(scale.x - 1)
|
if (!Numerical.isZero(scale.x - 1)
|
||||||
|| !Numerical.isZero(scale.y - 1))
|
|| !Numerical.isZero(scale.y - 1))
|
||||||
parts.push('scale(' + formatter.point(scale) +')');
|
parts.push('scale(' + formatter.point(scale) +')');
|
||||||
if (skew && skew.x)
|
if (skew.x)
|
||||||
parts.push('skewX(' + formatter.number(skew.x) + ')');
|
parts.push('skewX(' + formatter.number(skew.x) + ')');
|
||||||
if (skew && skew.y)
|
if (skew.y)
|
||||||
parts.push('skewY(' + formatter.number(skew.y) + ')');
|
parts.push('skewY(' + formatter.number(skew.y) + ')');
|
||||||
attrs.transform = parts.join(' ');
|
attrs.transform = parts.join(' ');
|
||||||
} else {
|
} else {
|
||||||
|
@ -13870,8 +13916,9 @@ new function() {
|
||||||
if (length > 2) {
|
if (length > 2) {
|
||||||
type = item._closed ? 'polygon' : 'polyline';
|
type = item._closed ? 'polygon' : 'polyline';
|
||||||
var parts = [];
|
var parts = [];
|
||||||
for(var i = 0; i < length; i++)
|
for (var i = 0; i < length; i++) {
|
||||||
parts.push(formatter.point(segments[i]._point));
|
parts.push(formatter.point(segments[i]._point));
|
||||||
|
}
|
||||||
attrs.points = parts.join(' ');
|
attrs.points = parts.join(' ');
|
||||||
} else {
|
} else {
|
||||||
type = 'line';
|
type = 'line';
|
||||||
|
@ -14142,6 +14189,7 @@ new function() {
|
||||||
? new Rectangle([0, 0], view.getViewSize())
|
? new Rectangle([0, 0], view.getViewSize())
|
||||||
: bounds === 'content'
|
: bounds === 'content'
|
||||||
? Item._getBounds(children, matrix, { stroke: true })
|
? Item._getBounds(children, matrix, { stroke: true })
|
||||||
|
.rect
|
||||||
: Rectangle.read([bounds], 0, { readNull: true }),
|
: Rectangle.read([bounds], 0, { readNull: true }),
|
||||||
attrs = {
|
attrs = {
|
||||||
version: '1.1',
|
version: '1.1',
|
||||||
|
@ -16413,7 +16461,6 @@ Base.exports.PaperScript = function() {
|
||||||
}.call(this);
|
}.call(this);
|
||||||
|
|
||||||
paper = new (PaperScope.inject(Base.exports, {
|
paper = new (PaperScope.inject(Base.exports, {
|
||||||
enumerable: true,
|
|
||||||
Base: Base,
|
Base: Base,
|
||||||
Numerical: Numerical,
|
Numerical: Numerical,
|
||||||
Key: Key,
|
Key: Key,
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
var clones = 30;
|
var clones = 30;
|
||||||
var angle = 360 / clones;
|
var angle = 360 / clones;
|
||||||
|
|
||||||
for(var i = 0; i < clones; i++) {
|
for (var i = 0; i < clones; i++) {
|
||||||
var clonedPath = circlePath.clone();
|
var clonedPath = circlePath.clone();
|
||||||
clonedPath.rotate(angle * i, circlePath.bounds.topLeft);
|
clonedPath.rotate(angle * i, circlePath.bounds.topLeft);
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
function getEqualizerBands(data) {
|
function getEqualizerBands(data) {
|
||||||
var bands = [];
|
var bands = [];
|
||||||
var amount = Math.sqrt(data.length) / 2;
|
var amount = Math.sqrt(data.length) / 2;
|
||||||
for(var i = 0; i < amount; i++) {
|
for (var i = 0; i < amount; i++) {
|
||||||
var start = Math.pow(2, i) - 1;
|
var start = Math.pow(2, i) - 1;
|
||||||
var end = start * 2 + 1;
|
var end = start * 2 + 1;
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
function removeSmallBits(path) {
|
function removeSmallBits(path) {
|
||||||
var averageLength = path.length / path.segments.length;
|
var averageLength = path.length / path.segments.length;
|
||||||
var min = path.length / 50;
|
var min = path.length / 50;
|
||||||
for(var i = path.segments.length - 1; i >= 0; i--) {
|
for (var i = path.segments.length - 1; i >= 0; i--) {
|
||||||
var segment = path.segments[i];
|
var segment = path.segments[i];
|
||||||
var cur = segment.point;
|
var cur = segment.point;
|
||||||
var nextSegment = segment.next;
|
var nextSegment = segment.next;
|
||||||
|
@ -69,8 +69,8 @@
|
||||||
function generateBeeHivePoints(size, loose) {
|
function generateBeeHivePoints(size, loose) {
|
||||||
var points = [];
|
var points = [];
|
||||||
var col = view.size / size;
|
var col = view.size / size;
|
||||||
for(var i = -1; i < size.width + 1; i++) {
|
for (var i = -1; i < size.width + 1; i++) {
|
||||||
for(var j = -1; j < size.height + 1; j++) {
|
for (var j = -1; j < size.height + 1; j++) {
|
||||||
var point = new Point(i, j) / new Point(size) * view.size + col / 2;
|
var point = new Point(i, j) / new Point(size) * view.size + col / 2;
|
||||||
if (j % 2)
|
if (j % 2)
|
||||||
point += new Point(col.width / 2, 0);
|
point += new Point(col.width / 2, 0);
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
var clones = 30;
|
var clones = 30;
|
||||||
var angle = 360 / clones;
|
var angle = 360 / clones;
|
||||||
|
|
||||||
for(var i = 0; i < clones; i++) {
|
for (var i = 0; i < clones; i++) {
|
||||||
var clonedPath = circlePath.clone();
|
var clonedPath = circlePath.clone();
|
||||||
clonedPath.rotate(angle * i, circlePath.bounds.topLeft);
|
clonedPath.rotate(angle * i, circlePath.bounds.topLeft);
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,13 +36,15 @@ gulp.task('publish', function() {
|
||||||
if (options.branch !== 'develop') {
|
if (options.branch !== 'develop') {
|
||||||
throw new Error('Publishing is only allowed on the develop branch.');
|
throw new Error('Publishing is only allowed on the develop branch.');
|
||||||
}
|
}
|
||||||
|
// publish:website comes before publish:release, so paperjs.zip file is gone
|
||||||
|
// before npm publish:
|
||||||
return run(
|
return run(
|
||||||
'publish:json',
|
'publish:json',
|
||||||
'publish:dist',
|
'publish:dist',
|
||||||
'publish:packages',
|
'publish:packages',
|
||||||
'publish:commit',
|
'publish:commit',
|
||||||
'publish:release',
|
|
||||||
'publish:website',
|
'publish:website',
|
||||||
|
'publish:release',
|
||||||
'publish:load'
|
'publish:load'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -115,8 +117,18 @@ gulp.task('publish:website', function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('publish:website:build',
|
gulp.task('publish:website:build', [
|
||||||
['publish:website:docs', 'publish:website:zip', 'publish:website:lib']);
|
'publish:website:json', 'publish:website:docs',
|
||||||
|
'publish:website:zip', 'publish:website:assets'
|
||||||
|
]);
|
||||||
|
|
||||||
|
gulp.task('publish:website:json', ['publish:version'], function() {
|
||||||
|
return gulp.src([sitePath + '/package.json'])
|
||||||
|
.pipe(jsonEditor({
|
||||||
|
version: options.version
|
||||||
|
}, jsonOptions))
|
||||||
|
.pipe(gulp.dest(sitePath));
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('publish:website:docs:clean', function() {
|
gulp.task('publish:website:docs:clean', function() {
|
||||||
return del([ referencePath + '/*' ], { force: true });
|
return del([ referencePath + '/*' ], { force: true });
|
||||||
|
@ -135,7 +147,10 @@ gulp.task('publish:website:zip', ['publish:version'], function() {
|
||||||
.pipe(gulp.dest(downloadPath));
|
.pipe(gulp.dest(downloadPath));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('publish:website:lib', ['publish:version'], function() {
|
gulp.task('publish:website:assets', function() {
|
||||||
|
// Always delete the old asset first, in case it's a symlink which Gulp
|
||||||
|
// doesn't handle well.
|
||||||
|
fs.unlinkSync(assetPath + '/paper.js');
|
||||||
return gulp.src('dist/paper-full.js')
|
return gulp.src('dist/paper-full.js')
|
||||||
.pipe(rename({ basename: 'paper' }))
|
.pipe(rename({ basename: 'paper' }))
|
||||||
.pipe(gulp.dest(assetPath));
|
.pipe(gulp.dest(assetPath));
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "paper",
|
"name": "paper",
|
||||||
"version": "0.11.2",
|
"version": "0.11.3",
|
||||||
"description": "The Swiss Army Knife of Vector Graphics Scripting",
|
"description": "The Swiss Army Knife of Vector Graphics Scripting",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "http://paperjs.org",
|
"homepage": "http://paperjs.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/paperjs/paper.js"
|
"url": "https://github.com/paperjs/paper.js"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/paperjs/paper.js/issues",
|
"bugs": "https://github.com/paperjs/paper.js/issues",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
"run-sequence": "^1.2.2",
|
"run-sequence": "^1.2.2",
|
||||||
"source-map-support": "^0.4.0",
|
"source-map-support": "^0.4.0",
|
||||||
"stats.js": "0.16.0",
|
"stats.js": "0.16.0",
|
||||||
"straps": "^2.1.0"
|
"straps": "^3.0.1"
|
||||||
},
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"canvas": false,
|
"canvas": false,
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit bab27f25fed8d78f072d8f9a9f68da61e7d1e975
|
Subproject commit fc7ac57828aefadff29f7559a5e39f88d35b0c66
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2e257a436e1cfec74ca6ffe4828a761ec058b42f
|
Subproject commit 18feab4d8968339c60d8610584ab3574c49d7a91
|
|
@ -377,7 +377,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
||||||
* @param {Matrix} matrix the matrix to append
|
* @param {Matrix} matrix the matrix to append
|
||||||
* @return {Matrix} this matrix, modified
|
* @return {Matrix} this matrix, modified
|
||||||
*/
|
*/
|
||||||
append: function(mx) {
|
append: function(mx, _dontNotify) {
|
||||||
if (mx) {
|
if (mx) {
|
||||||
var a1 = this._a,
|
var a1 = this._a,
|
||||||
b1 = this._b,
|
b1 = this._b,
|
||||||
|
@ -395,6 +395,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
||||||
this._d = b2 * b1 + d2 * d1;
|
this._d = b2 * b1 + d2 * d1;
|
||||||
this._tx += tx2 * a1 + ty2 * c1;
|
this._tx += tx2 * a1 + ty2 * c1;
|
||||||
this._ty += tx2 * b1 + ty2 * d1;
|
this._ty += tx2 * b1 + ty2 * d1;
|
||||||
|
if (!_dontNotify)
|
||||||
this._changed();
|
this._changed();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -407,7 +408,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
||||||
* @param {Matrix} matrix the matrix to prepend
|
* @param {Matrix} matrix the matrix to prepend
|
||||||
* @return {Matrix} this matrix, modified
|
* @return {Matrix} this matrix, modified
|
||||||
*/
|
*/
|
||||||
prepend: function(mx) {
|
prepend: function(mx, _dontNotify) {
|
||||||
if (mx) {
|
if (mx) {
|
||||||
var a1 = this._a,
|
var a1 = this._a,
|
||||||
b1 = this._b,
|
b1 = this._b,
|
||||||
|
@ -427,6 +428,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
||||||
this._d = c2 * c1 + d2 * d1;
|
this._d = c2 * c1 + d2 * d1;
|
||||||
this._tx = a2 * tx1 + b2 * ty1 + tx2;
|
this._tx = a2 * tx1 + b2 * ty1 + tx2;
|
||||||
this._ty = c2 * tx1 + d2 * ty1 + ty2;
|
this._ty = c2 * tx1 + d2 * ty1 + ty2;
|
||||||
|
if (!_dontNotify)
|
||||||
this._changed();
|
this._changed();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -671,7 +673,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to decompose the affine transformation described by this matrix
|
* Attempts to decompose the affine transformation described by this matrix
|
||||||
* into `scaling`, `rotation` and `shearing`, and returns an object with
|
* into `scaling`, `rotation` and `skewing`, and returns an object with
|
||||||
* these properties if it succeeded, `null` otherwise.
|
* these properties if it succeeded, `null` otherwise.
|
||||||
*
|
*
|
||||||
* @return {Object} the decomposed matrix, or `null` if decomposition is not
|
* @return {Object} the decomposed matrix, or `null` if decomposition is not
|
||||||
|
|
|
@ -141,6 +141,12 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{
|
||||||
}
|
}
|
||||||
this._set(x, y, width, height);
|
this._set(x, y, width, height);
|
||||||
read = arguments.__index;
|
read = arguments.__index;
|
||||||
|
// arguments.__filtered wouldn't survive the function call even if a
|
||||||
|
// previous arguments list was passed through Function#apply().
|
||||||
|
// Return it on the object instead, see Base.read()
|
||||||
|
var filtered = arguments.__filtered;
|
||||||
|
if (filtered)
|
||||||
|
this.__filtered = filtered;
|
||||||
}
|
}
|
||||||
if (this.__read)
|
if (this.__read)
|
||||||
this.__read = read;
|
this.__read = read;
|
||||||
|
|
212
src/core/Base.js
212
src/core/Base.js
|
@ -17,6 +17,8 @@
|
||||||
*/
|
*/
|
||||||
// Extend Base with utility functions used across the library.
|
// Extend Base with utility functions used across the library.
|
||||||
Base.inject(/** @lends Base# */{
|
Base.inject(/** @lends Base# */{
|
||||||
|
enumerable: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders base objects to strings in object literal notation.
|
* Renders base objects to strings in object literal notation.
|
||||||
*/
|
*/
|
||||||
|
@ -92,14 +94,15 @@ Base.inject(/** @lends Base# */{
|
||||||
if (props)
|
if (props)
|
||||||
Base.filter(this, props, exclude, this._prioritize);
|
Base.filter(this, props, exclude, this._prioritize);
|
||||||
return this;
|
return this;
|
||||||
},
|
}
|
||||||
|
}, /** @lends Base# */{
|
||||||
statics: /** @lends Base */{
|
// Mess with indentation in order to get more line-space for the statics below.
|
||||||
|
// Explicitly deactivate the creation of beans, as we have functions here
|
||||||
|
// that look like bean getters but actually read arguments, see getNamed().
|
||||||
|
beans: false,
|
||||||
|
statics: /** @lends Base */{
|
||||||
// Keep track of all named classes for serialization and exporting.
|
// Keep track of all named classes for serialization and exporting.
|
||||||
exports: {
|
exports: {},
|
||||||
enumerable: true // For PaperScope.inject() in export.js
|
|
||||||
},
|
|
||||||
|
|
||||||
extend: function extend() {
|
extend: function extend() {
|
||||||
// Override Base.extend() to register named classes in Base.exports,
|
// Override Base.extend() to register named classes in Base.exports,
|
||||||
|
@ -112,9 +115,9 @@ Base.inject(/** @lends Base# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if two values or objects are equals to each other, by using
|
* Checks if two values or objects are equals to each other, by using their
|
||||||
* their equals() methods if available, and also comparing elements of
|
* equals() methods if available, and also comparing elements of arrays and
|
||||||
* arrays and properties of objects.
|
* properties of objects.
|
||||||
*/
|
*/
|
||||||
equals: function(obj1, obj2) {
|
equals: function(obj1, obj2) {
|
||||||
if (obj1 === obj2)
|
if (obj1 === obj2)
|
||||||
|
@ -158,26 +161,25 @@ Base.inject(/** @lends Base# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When called on a subclass of Base, it reads arguments of the type of
|
* When called on a subclass of Base, it reads arguments of the type of the
|
||||||
* the subclass from the passed arguments list or array, at the given
|
* subclass from the passed arguments list or array, at the given index, up
|
||||||
* index, up to the specified length.
|
* to the specified length. When called directly on Base, it reads any value
|
||||||
* When called directly on Base, it reads any value without conversion
|
* without conversion from the passed arguments list or array. This is used
|
||||||
* from the passed arguments list or array.
|
* in argument conversion, e.g. by all basic types (Point, Size, Rectangle)
|
||||||
* This is used in argument conversion, e.g. by all basic types (Point,
|
* and also higher classes such as Color and Segment.
|
||||||
* Size, Rectangle) and also higher classes such as Color and Segment.
|
|
||||||
*
|
*
|
||||||
* @param {Array} list the list to read from, either an arguments object
|
* @param {Array} list the list to read from, either an arguments object or
|
||||||
* or a normal array
|
* a normal array
|
||||||
* @param {Number} start the index at which to start reading in the list
|
* @param {Number} start the index at which to start reading in the list
|
||||||
* @param {Object} options `options.readNull` controls whether null is
|
* @param {Object} options `options.readNull` controls whether null is
|
||||||
* returned or converted. `options.clone` controls whether passed
|
* returned or converted. `options.clone` controls whether passed
|
||||||
* objects should be cloned if they are already provided in the
|
* objects should be cloned if they are already provided in the required
|
||||||
* required type
|
* type
|
||||||
* @param {Number} length the amount of elements that can be read
|
* @param {Number} length the amount of elements that can be read
|
||||||
*/
|
*/
|
||||||
read: function(list, start, options, amount) {
|
read: function(list, start, options, amount) {
|
||||||
// See if it's called directly on Base, and if so, read value and
|
// See if it's called directly on Base, and if so, read value and return
|
||||||
// return without object conversion.
|
// without object conversion.
|
||||||
if (this === Base) {
|
if (this === Base) {
|
||||||
var value = this.peek(list, start);
|
var value = this.peek(list, start);
|
||||||
list.__index++;
|
list.__index++;
|
||||||
|
@ -189,9 +191,9 @@ Base.inject(/** @lends Base# */{
|
||||||
length = list.length,
|
length = list.length,
|
||||||
obj = list[begin];
|
obj = list[begin];
|
||||||
amount = amount || length - begin;
|
amount = amount || length - begin;
|
||||||
// When read() is called on a sub-class of which the object is
|
// When read() is called on a sub-class of which the object is already
|
||||||
// already an instance, or when there is only one value in the list
|
// an instance, or when there is only one value in the list and it's
|
||||||
// and it's null or undefined, return the obj.
|
// null or undefined, return the obj.
|
||||||
if (obj instanceof this
|
if (obj instanceof this
|
||||||
|| options && options.readNull && obj == null && amount <= 1) {
|
|| options && options.readNull && obj == null && amount <= 1) {
|
||||||
if (readIndex)
|
if (readIndex)
|
||||||
|
@ -208,6 +210,14 @@ Base.inject(/** @lends Base# */{
|
||||||
: list) || obj;
|
: list) || obj;
|
||||||
if (readIndex) {
|
if (readIndex) {
|
||||||
list.__index = begin + obj.__read;
|
list.__index = begin + obj.__read;
|
||||||
|
// This is only in use in Rectangle so far: Nested calls to
|
||||||
|
// `Base.readNamed()` would loose __filtered if it wasn't returned
|
||||||
|
// on the object.
|
||||||
|
var filtered = obj.__filtered;
|
||||||
|
if (filtered) {
|
||||||
|
list.__filtered = filtered;
|
||||||
|
obj.__filtered = undefined;
|
||||||
|
}
|
||||||
obj.__read = undefined;
|
obj.__read = undefined;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -259,20 +269,20 @@ Base.inject(/** @lends Base# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows using of Base.read() mechanism in combination with reading
|
* Allows using of Base.read() mechanism in combination with reading named
|
||||||
* named arguments form a passed property object literal. Calling
|
* arguments form a passed property object literal. Calling Base.readNamed()
|
||||||
* Base.readNamed() can read both from such named properties and normal
|
* can read both from such named properties and normal unnamed arguments
|
||||||
* unnamed arguments through Base.read(). In use for example for the
|
* through Base.read(). In use for example for the various
|
||||||
* various Path.Constructors.
|
* Path.Constructors.
|
||||||
*
|
*
|
||||||
* @param {Array} list the list to read from, either an arguments object
|
* @param {Array} list the list to read from, either an arguments object or
|
||||||
* or a normal array
|
* a normal array
|
||||||
* @param {String} name the property name to read from
|
* @param {String} name the property name to read from
|
||||||
* @param {Number} start the index at which to start reading in the list
|
* @param {Number} start the index at which to start reading in the list
|
||||||
* @param {Object} options `options.readNull` controls whether null is
|
* @param {Object} options `options.readNull` controls whether null is
|
||||||
* returned or converted. `options.clone` controls whether passed
|
* returned or converted. `options.clone` controls whether passed
|
||||||
* objects should be cloned if they are already provided in the
|
* objects should be cloned if they are already provided in the required
|
||||||
* required type
|
* type
|
||||||
* @param {Number} amount the amount of elements that can be read
|
* @param {Number} amount the amount of elements that can be read
|
||||||
*/
|
*/
|
||||||
readNamed: function(list, name, start, options, amount) {
|
readNamed: function(list, name, start, options, amount) {
|
||||||
|
@ -281,18 +291,20 @@ Base.inject(/** @lends Base# */{
|
||||||
if (hasObject) {
|
if (hasObject) {
|
||||||
// Create a _filtered object that inherits from list[0], and
|
// Create a _filtered object that inherits from list[0], and
|
||||||
// override all fields that were already read with undefined.
|
// override all fields that were already read with undefined.
|
||||||
var filtered = list._filtered;
|
var filtered = list.__filtered;
|
||||||
if (!filtered) {
|
if (!filtered) {
|
||||||
filtered = list._filtered = Base.create(list[0]);
|
filtered = list.__filtered = Base.create(list[0]);
|
||||||
// Point _unfiltered to the original so Base#_set() can
|
// Point _unfiltered to the original so Base#_set() can
|
||||||
// execute hasOwnProperty on it.
|
// execute hasOwnProperty on it.
|
||||||
filtered._unfiltered = list[0];
|
filtered.__unfiltered = list[0];
|
||||||
}
|
}
|
||||||
// delete wouldn't work since the masked parent's value would
|
// delete wouldn't work since the masked parent's value would
|
||||||
// shine through.
|
// shine through.
|
||||||
filtered[name] = undefined;
|
filtered[name] = undefined;
|
||||||
}
|
}
|
||||||
return this.read(hasObject ? [value] : list, start, options, amount);
|
var l = hasObject ? [value] : list,
|
||||||
|
res = this.read(l, start, options, amount);
|
||||||
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -307,13 +319,12 @@ Base.inject(/** @lends Base# */{
|
||||||
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
|
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
|
||||||
if (list._hasObject)
|
if (list._hasObject)
|
||||||
// Return the whole arguments object if no name is provided.
|
// Return the whole arguments object if no name is provided.
|
||||||
return name ? arg[name] : list._filtered || arg;
|
return name ? arg[name] : list.__filtered || arg;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the argument list has a named argument with the given name.
|
* Checks if the argument list has a named argument with the given name. If
|
||||||
* If name is `null`, it returns `true` if there are any named
|
* name is `null`, it returns `true` if there are any named arguments.
|
||||||
* arguments.
|
|
||||||
*/
|
*/
|
||||||
hasNamed: function(list, name) {
|
hasNamed: function(list, name) {
|
||||||
return !!this.getNamed(list, name);
|
return !!this.getNamed(list, name);
|
||||||
|
@ -321,18 +332,17 @@ Base.inject(/** @lends Base# */{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies all properties from `source` over to `dest`, supporting
|
* Copies all properties from `source` over to `dest`, supporting
|
||||||
* `_filtered` handling as required by {@link Base.readNamed()}
|
* `_filtered` handling as required by {@link Base.readNamed()} mechanism,
|
||||||
* mechanism, as well as a way to exclude and prioritize properties.
|
* as well as a way to exclude and prioritize properties.
|
||||||
*
|
*
|
||||||
* @param {Object} dest the destination that is to receive the
|
* @param {Object} dest the destination that is to receive the properties
|
||||||
* properties
|
* @param {Object} source the source from where to retrieve the properties
|
||||||
* @param {Object} source the source from where to retrieve the
|
* to be copied
|
||||||
* properties to be copied
|
* @param {Object} [exclude] an object that can define any properties as
|
||||||
* @param {Object} [exclude] an object that can define any properties
|
* `true` that should be excluded when copying
|
||||||
* as `true` that should be excluded when copying
|
* @param {String[]} [prioritize] a list of keys that should be prioritized
|
||||||
* @param {String[]} [prioritize] a list of keys that should be
|
* when copying, if they are defined in `source`, processed in the order
|
||||||
* prioritized when copying, if they are defined in `source`,
|
* of appearance
|
||||||
* processed in the order of appearance
|
|
||||||
*/
|
*/
|
||||||
filter: function(dest, source, exclude, prioritize) {
|
filter: function(dest, source, exclude, prioritize) {
|
||||||
var processed;
|
var processed;
|
||||||
|
@ -362,16 +372,16 @@ Base.inject(/** @lends Base# */{
|
||||||
processed = keys;
|
processed = keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If source is a filtered object, we get the keys from the
|
// If source is a filtered object, we get the keys from the the original
|
||||||
// the original object (it's parent / prototype). See _filtered
|
// object (it's parent / prototype). See _filtered inheritance trick in
|
||||||
// inheritance trick in the argument reading code.
|
// the argument reading code.
|
||||||
Object.keys(source._unfiltered || source).forEach(handleKey);
|
Object.keys(source.__unfiltered || source).forEach(handleKey);
|
||||||
return dest;
|
return dest;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if obj is either a plain object or an array, as used by
|
* Returns true if obj is either a plain object or an array, as used by many
|
||||||
* many argument reading methods.
|
* argument reading methods.
|
||||||
*/
|
*/
|
||||||
isPlainValue: function(obj, asString) {
|
isPlainValue: function(obj, asString) {
|
||||||
return Base.isPlainObject(obj) || Array.isArray(obj)
|
return Base.isPlainObject(obj) || Array.isArray(obj)
|
||||||
|
@ -380,7 +390,7 @@ Base.inject(/** @lends Base# */{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes the passed object into a format that can be passed to
|
* Serializes the passed object into a format that can be passed to
|
||||||
* JSON.stringify() for JSON serialization.
|
* `JSON.stringify()` for JSON serialization.
|
||||||
*/
|
*/
|
||||||
serialize: function(obj, options, compact, dictionary) {
|
serialize: function(obj, options, compact, dictionary) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
@ -389,10 +399,10 @@ Base.inject(/** @lends Base# */{
|
||||||
res;
|
res;
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
options.formatter = new Formatter(options.precision);
|
options.formatter = new Formatter(options.precision);
|
||||||
// Create a simple dictionary object that handles all the
|
// Create a simple dictionary object that handles all the storing
|
||||||
// storing and retrieving of dictionary definitions and
|
// and retrieving of dictionary definitions and references, e.g. for
|
||||||
// references, e.g. for symbols and gradients. Items that want
|
// symbols and gradients. Items that want to support this need to
|
||||||
// to support this need to define globally unique _id attribute.
|
// define globally unique _id attribute.
|
||||||
/**
|
/**
|
||||||
* @namespace
|
* @namespace
|
||||||
* @private
|
* @private
|
||||||
|
@ -402,10 +412,9 @@ Base.inject(/** @lends Base# */{
|
||||||
definitions: {},
|
definitions: {},
|
||||||
references: {},
|
references: {},
|
||||||
add: function(item, create) {
|
add: function(item, create) {
|
||||||
// See if we have reference entry with the given id
|
// See if we have reference entry with the given id already.
|
||||||
// already. If not, call create on the item to allow it
|
// If not, call create on the item to allow it to create the
|
||||||
// to create the definition, then store the reference
|
// definition, then store the reference to it and return it.
|
||||||
// to it and return it.
|
|
||||||
var id = '#' + item._id,
|
var id = '#' + item._id,
|
||||||
ref = this.references[id];
|
ref = this.references[id];
|
||||||
if (!ref) {
|
if (!ref) {
|
||||||
|
@ -426,11 +435,11 @@ Base.inject(/** @lends Base# */{
|
||||||
if (obj && obj._serialize) {
|
if (obj && obj._serialize) {
|
||||||
res = obj._serialize(options, dictionary);
|
res = obj._serialize(options, dictionary);
|
||||||
// If we don't serialize to compact form (meaning no type
|
// If we don't serialize to compact form (meaning no type
|
||||||
// identifier), see if _serialize didn't already add the class,
|
// identifier), see if _serialize didn't already add the class, e.g.
|
||||||
// e.g. for classes that do not support compact form.
|
// for classes that do not support compact form.
|
||||||
var name = obj._class;
|
var name = obj._class;
|
||||||
// Enforce class names on root level, except if the class
|
// Enforce class names on root level, except if the class explicitly
|
||||||
// explicitly asks to be serialized in compact form (Project).
|
// asks to be serialized in compact form (Project).
|
||||||
if (name && !obj._compactSerialize && (isRoot || !compact)
|
if (name && !obj._compactSerialize && (isRoot || !compact)
|
||||||
&& res[0] !== name) {
|
&& res[0] !== name) {
|
||||||
res.unshift(name);
|
res.unshift(name);
|
||||||
|
@ -438,8 +447,7 @@ Base.inject(/** @lends Base# */{
|
||||||
} else if (Array.isArray(obj)) {
|
} else if (Array.isArray(obj)) {
|
||||||
res = [];
|
res = [];
|
||||||
for (var i = 0, l = obj.length; i < l; i++)
|
for (var i = 0, l = obj.length; i < l; i++)
|
||||||
res[i] = Base.serialize(obj[i], options, compact,
|
res[i] = Base.serialize(obj[i], options, compact, dictionary);
|
||||||
dictionary);
|
|
||||||
} else if (Base.isPlainObject(obj)) {
|
} else if (Base.isPlainObject(obj)) {
|
||||||
res = {};
|
res = {};
|
||||||
var keys = Object.keys(obj);
|
var keys = Object.keys(obj);
|
||||||
|
@ -461,37 +469,36 @@ Base.inject(/** @lends Base# */{
|
||||||
/**
|
/**
|
||||||
* Deserializes from parsed JSON data. A simple convention is followed:
|
* Deserializes from parsed JSON data. A simple convention is followed:
|
||||||
* Array values with a string at the first position are links to
|
* Array values with a string at the first position are links to
|
||||||
* deserializable types through Base.exports, and the values following
|
* deserializable types through Base.exports, and the values following in
|
||||||
* in the array are the arguments to their initialize function.
|
* the array are the arguments to their initialize function. Any other value
|
||||||
* Any other value is passed on unmodified.
|
* is passed on unmodified. The passed json data is recoursively traversed
|
||||||
* The passed json data is recoursively traversed and converted, leaves
|
* and converted, leaves first.
|
||||||
* first
|
|
||||||
*/
|
*/
|
||||||
deserialize: function(json, create, _data, _setDictionary, _isRoot) {
|
deserialize: function(json, create, _data, _setDictionary, _isRoot) {
|
||||||
var res = json,
|
var res = json,
|
||||||
isFirst = !_data,
|
isFirst = !_data,
|
||||||
hasDictionary = isFirst && json && json.length
|
hasDictionary = isFirst && json && json.length
|
||||||
&& json[0][0] === 'dictionary';
|
&& json[0][0] === 'dictionary';
|
||||||
// A _data side-car to deserialize that can hold any kind of
|
// A _data side-car to deserialize that can hold any kind of 'global'
|
||||||
// 'global' data across a deserialization. It's currently only used
|
// data across a deserialization. It's currently only used to hold
|
||||||
// to hold dictionary definitions.
|
// dictionary definitions.
|
||||||
_data = _data || {};
|
_data = _data || {};
|
||||||
if (Array.isArray(json)) {
|
if (Array.isArray(json)) {
|
||||||
// See if it's a serialized type. If so, the rest of the array
|
// See if it's a serialized type. If so, the rest of the array are
|
||||||
// are the arguments to #initialize(). Either way, we simply
|
// the arguments to #initialize(). Either way, we simply deserialize
|
||||||
// deserialize all elements of the array.
|
// all elements of the array.
|
||||||
var type = json[0],
|
var type = json[0],
|
||||||
// Handle stored dictionary specially, since we need to
|
// Handle stored dictionary specially, since we need to keep a
|
||||||
// keep a lookup table to retrieve referenced items from.
|
// lookup table to retrieve referenced items from.
|
||||||
isDictionary = type === 'dictionary';
|
isDictionary = type === 'dictionary';
|
||||||
// First see if this is perhaps a dictionary reference, and
|
// First see if this is perhaps a dictionary reference, and if so
|
||||||
// if so return its definition instead.
|
// return its definition instead.
|
||||||
if (json.length == 1 && /^#/.test(type)) {
|
if (json.length == 1 && /^#/.test(type)) {
|
||||||
return _data.dictionary[type];
|
return _data.dictionary[type];
|
||||||
}
|
}
|
||||||
type = Base.exports[type];
|
type = Base.exports[type];
|
||||||
res = [];
|
res = [];
|
||||||
// Skip first type entry for arguments
|
// Skip first type entry for arguments.
|
||||||
// Pass true for _isRoot in children if we have a dictionary,
|
// Pass true for _isRoot in children if we have a dictionary,
|
||||||
// in which case we need to shift the root level one down.
|
// in which case we need to shift the root level one down.
|
||||||
for (var i = type ? 1 : 0, l = json.length; i < l; i++) {
|
for (var i = type ? 1 : 0, l = json.length; i < l; i++) {
|
||||||
|
@ -502,9 +509,9 @@ Base.inject(/** @lends Base# */{
|
||||||
// Create serialized type and pass collected arguments to
|
// Create serialized type and pass collected arguments to
|
||||||
// constructor().
|
// constructor().
|
||||||
var args = res;
|
var args = res;
|
||||||
// If a create method is provided, handle our own
|
// If a create method is provided, handle our own creation. This
|
||||||
// creation. This is used in #importJSON() to pass
|
// is used in #importJSON() to pass on insert = false to all
|
||||||
// on insert = false to all items except layers.
|
// items except layers.
|
||||||
if (create) {
|
if (create) {
|
||||||
res = create(type, args, isFirst || _isRoot);
|
res = create(type, args, isFirst || _isRoot);
|
||||||
} else {
|
} else {
|
||||||
|
@ -545,10 +552,10 @@ Base.inject(/** @lends Base# */{
|
||||||
&& target.constructor === ctor,
|
&& target.constructor === ctor,
|
||||||
obj = useTarget ? target
|
obj = useTarget ? target
|
||||||
: Base.create(ctor.prototype);
|
: Base.create(ctor.prototype);
|
||||||
// NOTE: We don't set insert false for layers since we
|
// NOTE: We don't set insert false for layers since we want
|
||||||
// want these to be created on the fly in the active
|
// these to be created on the fly in the active project into
|
||||||
// project into which we're importing (except for if
|
// which we're importing (except for if it's a preexisting
|
||||||
// it's a preexisting target layer).
|
// target layer).
|
||||||
if (args.length === 1 && obj instanceof Item
|
if (args.length === 1 && obj instanceof Item
|
||||||
&& (useTarget || !(obj instanceof Layer))) {
|
&& (useTarget || !(obj instanceof Layer))) {
|
||||||
var arg = args[0];
|
var arg = args[0];
|
||||||
|
@ -566,9 +573,9 @@ Base.inject(/** @lends Base# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility function for adding and removing items from a list of which
|
* Utility function for adding and removing items from a list of which each
|
||||||
* each entry keeps a reference to its index in the list in the private
|
* entry keeps a reference to its index in the list in the private _index
|
||||||
* _index property. Used for PaperScope#projects and Item#children.
|
* property. Used for PaperScope#projects and Item#children.
|
||||||
*/
|
*/
|
||||||
splice: function(list, items, index, remove) {
|
splice: function(list, items, index, remove) {
|
||||||
var amount = items && items.length,
|
var amount = items && items.length,
|
||||||
|
@ -624,5 +631,4 @@ Base.inject(/** @lends Base# */{
|
||||||
hyphenate: function(str) {
|
hyphenate: function(str) {
|
||||||
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}});
|
||||||
});
|
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
// global one in the whole scope.
|
// global one in the whole scope.
|
||||||
|
|
||||||
paper = new (PaperScope.inject(Base.exports, {
|
paper = new (PaperScope.inject(Base.exports, {
|
||||||
// Mark fields as enumerable so PaperScope.inject can pick them up
|
|
||||||
enumerable: true,
|
|
||||||
Base: Base,
|
Base: Base,
|
||||||
Numerical: Numerical,
|
Numerical: Numerical,
|
||||||
Key: Key,
|
Key: Key,
|
||||||
|
|
|
@ -26,11 +26,8 @@ var HitResult = Base.extend(/** @lends HitResult# */{
|
||||||
// Inject passed values, so we can be flexible about the HitResult
|
// Inject passed values, so we can be flexible about the HitResult
|
||||||
// properties.
|
// properties.
|
||||||
// This allows the definition of getters too, e.g. for 'pixel'.
|
// This allows the definition of getters too, e.g. for 'pixel'.
|
||||||
if (values) {
|
if (values)
|
||||||
// Make enumerable so toString() works.
|
|
||||||
values.enumerable = true;
|
|
||||||
this.inject(values);
|
this.inject(values);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
181
src/item/Item.js
181
src/item/Item.js
|
@ -827,14 +827,14 @@ new function() { // Injection scope for various item event handlers
|
||||||
opts.cacheItem = this;
|
opts.cacheItem = this;
|
||||||
// If we're caching bounds, pass on this item as cacheItem, so
|
// If we're caching bounds, pass on this item as cacheItem, so
|
||||||
// the children can setup _boundsCache structures for it.
|
// the children can setup _boundsCache structures for it.
|
||||||
var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
|
var rect = this._getCachedBounds(hasMatrix && matrix, opts).rect;
|
||||||
// If we're returning '#bounds', create a LinkedRectangle that uses
|
// If we're returning '#bounds', create a LinkedRectangle that uses
|
||||||
// the setBounds() setter to update the Item whenever the bounds are
|
// the setBounds() setter to update the Item whenever the bounds are
|
||||||
// changed:
|
// changed:
|
||||||
return !arguments.length
|
return !arguments.length
|
||||||
? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
|
? new LinkedRectangle(rect.x, rect.y, rect.width, rect.height,
|
||||||
bounds.height, this, 'setBounds')
|
this, 'setBounds')
|
||||||
: bounds;
|
: rect;
|
||||||
},
|
},
|
||||||
|
|
||||||
setBounds: function(/* rect */) {
|
setBounds: function(/* rect */) {
|
||||||
|
@ -889,6 +889,14 @@ new function() { // Injection scope for various item event handlers
|
||||||
return Item._getBounds(children, matrix, options);
|
return Item._getBounds(children, matrix, options);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_getBoundsCacheKey: function(options, internal) {
|
||||||
|
return [
|
||||||
|
options.stroke ? 1 : 0,
|
||||||
|
options.handle ? 1 : 0,
|
||||||
|
internal ? 1 : 0
|
||||||
|
].join('');
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private method that deals with the calling of _getBounds, recursive
|
* Private method that deals with the calling of _getBounds, recursive
|
||||||
* matrix concatenation and handles all the complicated caching mechanisms.
|
* matrix concatenation and handles all the complicated caching mechanisms.
|
||||||
|
@ -904,29 +912,43 @@ new function() { // Injection scope for various item event handlers
|
||||||
cacheItem = options.cacheItem,
|
cacheItem = options.cacheItem,
|
||||||
_matrix = internal ? null : this._matrix._orNullIfIdentity(),
|
_matrix = internal ? null : this._matrix._orNullIfIdentity(),
|
||||||
// Create a key for caching, reflecting all bounds options.
|
// Create a key for caching, reflecting all bounds options.
|
||||||
cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
|
cacheKey = cacheItem && (!matrix || matrix.equals(_matrix))
|
||||||
options.stroke ? 1 : 0,
|
&& this._getBoundsCacheKey(options, internal),
|
||||||
options.handle ? 1 : 0,
|
bounds = this._bounds;
|
||||||
internal ? 1 : 0
|
|
||||||
].join('');
|
|
||||||
// NOTE: This needs to happen before returning cached values, since even
|
// NOTE: This needs to happen before returning cached values, since even
|
||||||
// then, _boundsCache needs to be kept up-to-date.
|
// then, _boundsCache needs to be kept up-to-date.
|
||||||
Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
|
Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
|
||||||
if (cacheKey && this._bounds && cacheKey in this._bounds)
|
if (cacheKey && bounds && cacheKey in bounds) {
|
||||||
return this._bounds[cacheKey].rect.clone();
|
var cached = bounds[cacheKey];
|
||||||
var bounds = this._getBounds(matrix || _matrix, options);
|
return {
|
||||||
|
rect: cached.rect.clone(),
|
||||||
|
nonscaling: cached.nonscaling
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var res = this._getBounds(matrix || _matrix, options),
|
||||||
|
// Support two versions of _getBounds(): One that directly returns a
|
||||||
|
// Rectangle, and one that returns a bounds object with nonscaling.
|
||||||
|
rect = res.rect || res,
|
||||||
|
style = this._style,
|
||||||
|
nonscaling = res.nonscaling || style.hasStroke()
|
||||||
|
&& !style.getStrokeScaling();
|
||||||
// If we can cache the result, update the _bounds cache structure
|
// If we can cache the result, update the _bounds cache structure
|
||||||
// before returning
|
// before returning
|
||||||
if (cacheKey) {
|
if (cacheKey) {
|
||||||
if (!this._bounds)
|
if (!bounds) {
|
||||||
this._bounds = {};
|
this._bounds = bounds = {};
|
||||||
var cached = this._bounds[cacheKey] = {
|
}
|
||||||
rect: bounds.clone(),
|
var cached = bounds[cacheKey] = {
|
||||||
|
rect: rect.clone(),
|
||||||
|
nonscaling: nonscaling,
|
||||||
// Mark as internal, so Item#transform() won't transform it
|
// Mark as internal, so Item#transform() won't transform it
|
||||||
internal: internal
|
internal: internal
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return bounds;
|
return {
|
||||||
|
rect: rect,
|
||||||
|
nonscaling: nonscaling
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1005,7 +1027,10 @@ new function() { // Injection scope for various item event handlers
|
||||||
var x1 = Infinity,
|
var x1 = Infinity,
|
||||||
x2 = -x1,
|
x2 = -x1,
|
||||||
y1 = x1,
|
y1 = x1,
|
||||||
y2 = x2;
|
y2 = x2,
|
||||||
|
nonscaling = false;
|
||||||
|
// NOTE: As soon as one child-item has non-scaling strokes, the full
|
||||||
|
// bounds need to be considered non-scaling for caching purposes.
|
||||||
options = options || {};
|
options = options || {};
|
||||||
for (var i = 0, l = items.length; i < l; i++) {
|
for (var i = 0, l = items.length; i < l; i++) {
|
||||||
var item = items[i];
|
var item = items[i];
|
||||||
|
@ -1013,17 +1038,23 @@ new function() { // Injection scope for various item event handlers
|
||||||
// Pass true for noInternal, since even when getting
|
// Pass true for noInternal, since even when getting
|
||||||
// internal bounds for this item, we need to apply the
|
// internal bounds for this item, we need to apply the
|
||||||
// matrices to its children.
|
// matrices to its children.
|
||||||
var rect = item._getCachedBounds(
|
var bounds = item._getCachedBounds(
|
||||||
matrix && matrix.appended(item._matrix), options, true);
|
matrix && matrix.appended(item._matrix), options, true),
|
||||||
|
rect = bounds.rect;
|
||||||
x1 = Math.min(rect.x, x1);
|
x1 = Math.min(rect.x, x1);
|
||||||
y1 = Math.min(rect.y, y1);
|
y1 = Math.min(rect.y, y1);
|
||||||
x2 = Math.max(rect.x + rect.width, x2);
|
x2 = Math.max(rect.x + rect.width, x2);
|
||||||
y2 = Math.max(rect.y + rect.height, y2);
|
y2 = Math.max(rect.y + rect.height, y2);
|
||||||
|
if (bounds.nonscaling)
|
||||||
|
nonscaling = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isFinite(x1)
|
return {
|
||||||
|
rect: isFinite(x1)
|
||||||
? new Rectangle(x1, y1, x2 - x1, y2 - y1)
|
? new Rectangle(x1, y1, x2 - x1, y2 - y1)
|
||||||
: new Rectangle();
|
: new Rectangle(),
|
||||||
|
nonscaling: nonscaling
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1122,8 +1153,22 @@ new function() { // Injection scope for various item event handlers
|
||||||
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
|
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
|
||||||
if (current && scaling && !current.equals(scaling)) {
|
if (current && scaling && !current.equals(scaling)) {
|
||||||
// See #setRotation() for preservation of _decomposed.
|
// See #setRotation() for preservation of _decomposed.
|
||||||
var decomposed = this._decomposed;
|
var rotation = this.getRotation(),
|
||||||
this.scale(scaling.x / current.x, scaling.y / current.y);
|
decomposed = this._decomposed,
|
||||||
|
matrix = new Matrix(),
|
||||||
|
center = this.getPosition(true);
|
||||||
|
// Create a matrix in which the scaling is applied in the non-
|
||||||
|
// rotated state, so it is always applied before the rotation.
|
||||||
|
// TODO: What about skewing? Do we need separately stored values for
|
||||||
|
// these properties, and apply them separately from the matrix?
|
||||||
|
matrix.translate(center);
|
||||||
|
if (rotation)
|
||||||
|
matrix.rotate(rotation);
|
||||||
|
matrix.scale(scaling.x / current.x, scaling.y / current.y);
|
||||||
|
if (rotation)
|
||||||
|
matrix.rotate(-rotation);
|
||||||
|
matrix.translate(center.negate());
|
||||||
|
this.transform(matrix);
|
||||||
if (decomposed) {
|
if (decomposed) {
|
||||||
decomposed.scaling = scaling;
|
decomposed.scaling = scaling;
|
||||||
this._decomposed = decomposed;
|
this._decomposed = decomposed;
|
||||||
|
@ -3376,11 +3421,9 @@ new function() { // Injection scope for hit-test functions shared with project
|
||||||
// 'lines'. Default: ['objects', 'children']
|
// 'lines'. Default: ['objects', 'children']
|
||||||
transform: function(matrix, _applyMatrix, _applyRecursively,
|
transform: function(matrix, _applyMatrix, _applyRecursively,
|
||||||
_setApplyMatrix) {
|
_setApplyMatrix) {
|
||||||
|
var _matrix = this._matrix,
|
||||||
// If no matrix is provided, or the matrix is the identity, we might
|
// If no matrix is provided, or the matrix is the identity, we might
|
||||||
// still have some work to do in case _applyMatrix is true
|
// still have some work to do in case _applyMatrix is true
|
||||||
if (matrix && matrix.isIdentity())
|
|
||||||
matrix = null;
|
|
||||||
var _matrix = this._matrix,
|
|
||||||
transform = matrix && !matrix.isIdentity(),
|
transform = matrix && !matrix.isIdentity(),
|
||||||
applyMatrix = (_applyMatrix || this._applyMatrix)
|
applyMatrix = (_applyMatrix || this._applyMatrix)
|
||||||
// Don't apply _matrix if the result of concatenating with
|
// Don't apply _matrix if the result of concatenating with
|
||||||
|
@ -3398,30 +3441,8 @@ new function() { // Injection scope for hit-test functions shared with project
|
||||||
// non-invertible. This is then used again in setBounds to restore.
|
// non-invertible. This is then used again in setBounds to restore.
|
||||||
if (!matrix.isInvertible() && _matrix.isInvertible())
|
if (!matrix.isInvertible() && _matrix.isInvertible())
|
||||||
_matrix._backup = _matrix.getValues();
|
_matrix._backup = _matrix.getValues();
|
||||||
_matrix.prepend(matrix);
|
// Pass `true` for _dontNotify, as we're handling this after.
|
||||||
}
|
_matrix.prepend(matrix, true);
|
||||||
// Call #_transformContent() now, if we need to directly apply the
|
|
||||||
// internal _matrix transformations to the item's content.
|
|
||||||
// Application is not possible on Raster, PointText, SymbolItem, since
|
|
||||||
// the matrix is where the actual transformation state is stored.
|
|
||||||
if (applyMatrix) {
|
|
||||||
if (this._transformContent(_matrix, _applyRecursively,
|
|
||||||
_setApplyMatrix)) {
|
|
||||||
var pivot = this._pivot;
|
|
||||||
if (pivot)
|
|
||||||
_matrix._transformPoint(pivot, pivot, true);
|
|
||||||
// Reset the internal matrix to the identity transformation if
|
|
||||||
// it was possible to apply it.
|
|
||||||
_matrix.reset(true);
|
|
||||||
// Set the internal _applyMatrix flag to true if we're told to
|
|
||||||
// do so
|
|
||||||
if (_setApplyMatrix && this._canApplyMatrix)
|
|
||||||
this._applyMatrix = true;
|
|
||||||
} else {
|
|
||||||
applyMatrix = transform = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (transform) {
|
|
||||||
// When a new matrix was applied, we also need to transform gradient
|
// When a new matrix was applied, we also need to transform gradient
|
||||||
// color points. These always need transforming, regardless of
|
// color points. These always need transforming, regardless of
|
||||||
// #applyMatrix, as they are defined in the parent's coordinate
|
// #applyMatrix, as they are defined in the parent's coordinate
|
||||||
|
@ -3438,39 +3459,65 @@ new function() { // Injection scope for hit-test functions shared with project
|
||||||
if (strokeColor)
|
if (strokeColor)
|
||||||
strokeColor.transform(matrix);
|
strokeColor.transform(matrix);
|
||||||
}
|
}
|
||||||
|
// Call #_transformContent() now, if we need to directly apply the
|
||||||
|
// internal _matrix transformations to the item's content.
|
||||||
|
// Application is not possible on Raster, PointText, SymbolItem, since
|
||||||
|
// the matrix is where the actual transformation state is stored.
|
||||||
|
if (applyMatrix && (applyMatrix = this._transformContent(_matrix,
|
||||||
|
_applyRecursively, _setApplyMatrix))) {
|
||||||
|
// Pivot is provided in the parent's coordinate system, so transform
|
||||||
|
// it along too.
|
||||||
|
var pivot = this._pivot;
|
||||||
|
if (pivot)
|
||||||
|
_matrix._transformPoint(pivot, pivot, true);
|
||||||
|
// Reset the internal matrix to the identity transformation if
|
||||||
|
// it was possible to apply it, but do not notify owner of change.
|
||||||
|
_matrix.reset(true);
|
||||||
|
// Set the internal _applyMatrix flag to true if we're told to
|
||||||
|
// do so
|
||||||
|
if (_setApplyMatrix && this._canApplyMatrix)
|
||||||
|
this._applyMatrix = true;
|
||||||
|
}
|
||||||
// Calling _changed will clear _bounds and _position, but depending
|
// Calling _changed will clear _bounds and _position, but depending
|
||||||
// on matrix we can calculate and set them again, so preserve them.
|
// on matrix we can calculate and set them again, so preserve them.
|
||||||
var bounds = this._bounds,
|
var bounds = this._bounds,
|
||||||
position = this._position;
|
position = this._position;
|
||||||
// We always need to call _changed since we're caching bounds on all
|
if (transform || applyMatrix) {
|
||||||
// items, including Group.
|
|
||||||
this._changed(/*#=*/Change.GEOMETRY);
|
this._changed(/*#=*/Change.GEOMETRY);
|
||||||
|
}
|
||||||
// Detect matrices that contain only translations and scaling
|
// Detect matrices that contain only translations and scaling
|
||||||
// and transform the cached _bounds and _position without having to
|
// and transform the cached _bounds and _position without having to
|
||||||
// fully recalculate each time.
|
// fully recalculate each time.
|
||||||
var decomp = bounds && matrix && matrix.decompose();
|
var decomp = transform && bounds && matrix.decompose();
|
||||||
if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
|
if (decomp && decomp.skewing.isZero() && decomp.rotation % 90 === 0) {
|
||||||
// Transform the old bound by looping through all the cached bounds
|
// Transform the old bound by looping through all the cached
|
||||||
// in _bounds and transform each.
|
// bounds in _bounds and transform each.
|
||||||
for (var key in bounds) {
|
for (var key in bounds) {
|
||||||
var cache = bounds[key];
|
var cache = bounds[key];
|
||||||
|
// If any item involved in the determination of these bounds has
|
||||||
|
// non-scaling strokes, delete the cache now as it can't be
|
||||||
|
// preserved through the transformation.
|
||||||
|
if (cache.nonscaling) {
|
||||||
|
delete bounds[key];
|
||||||
|
} else if (applyMatrix || !cache.internal) {
|
||||||
// If these are internal bounds, only transform them if this
|
// If these are internal bounds, only transform them if this
|
||||||
// item applied its matrix.
|
// item applied its matrix.
|
||||||
if (applyMatrix || !cache.internal) {
|
|
||||||
var rect = cache.rect;
|
var rect = cache.rect;
|
||||||
matrix._transformBounds(rect, rect);
|
matrix._transformBounds(rect, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we have cached bounds, update _position again as its
|
|
||||||
// center. We need to take into account _boundsGetter here too, in
|
|
||||||
// case another getter is assigned to it, e.g. 'getStrokeBounds'.
|
|
||||||
var getter = this._boundsGetter,
|
|
||||||
rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
|
|
||||||
if (rect)
|
|
||||||
this._position = rect.getCenter(true);
|
|
||||||
this._bounds = bounds;
|
this._bounds = bounds;
|
||||||
} else if (matrix && position) {
|
// If we have cached bounds, try to determine _position as its
|
||||||
// Transform position as well.
|
// center. Use _boundsOptions do get the cached default bounds.
|
||||||
|
var cached = bounds[this._getBoundsCacheKey(
|
||||||
|
this._boundsOptions || {})];
|
||||||
|
if (cached) {
|
||||||
|
this._position = cached.rect.getCenter(true);
|
||||||
|
}
|
||||||
|
} else if (transform && position && this._pivot) {
|
||||||
|
// If the item has a pivot defined, it means that the default
|
||||||
|
// position defined as the center of the bounds won't shift with
|
||||||
|
// arbitrary transformations and we can therefore update _position:
|
||||||
this._position = matrix._transformPoint(position, position);
|
this._position = matrix._transformPoint(position, position);
|
||||||
}
|
}
|
||||||
// Allow chaining here, since transform() is related to Matrix functions
|
// Allow chaining here, since transform() is related to Matrix functions
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
// The paper.js version.
|
// The paper.js version.
|
||||||
// NOTE: Adjust value here before calling `gulp publish`, which then updates and
|
// NOTE: Adjust value here before calling `gulp publish`, which then updates and
|
||||||
// publishes the various JSON package files automatically.
|
// publishes the various JSON package files automatically.
|
||||||
var version = '0.11.2';
|
var version = '0.11.3';
|
||||||
|
|
||||||
// If this file is loaded in the browser, we're in load.js mode.
|
// If this file is loaded in the browser, we're in load.js mode.
|
||||||
var load = typeof window === 'object';
|
var load = typeof window === 'object';
|
||||||
|
|
|
@ -1955,7 +1955,7 @@ new function() { // Scope for bezier intersection using fat-line clipping
|
||||||
// Calculate the curve values of the rotated curve.
|
// Calculate the curve values of the rotated curve.
|
||||||
rv = [],
|
rv = [],
|
||||||
roots = [];
|
roots = [];
|
||||||
for(var i = 0; i < 8; i += 2) {
|
for (var i = 0; i < 8; i += 2) {
|
||||||
var x = v[i] - px,
|
var x = v[i] - px,
|
||||||
y = v[i + 1] - py;
|
y = v[i + 1] - py;
|
||||||
rv.push(
|
rv.push(
|
||||||
|
|
|
@ -51,9 +51,9 @@ new function() {
|
||||||
if (!Numerical.isZero(scale.x - 1)
|
if (!Numerical.isZero(scale.x - 1)
|
||||||
|| !Numerical.isZero(scale.y - 1))
|
|| !Numerical.isZero(scale.y - 1))
|
||||||
parts.push('scale(' + formatter.point(scale) +')');
|
parts.push('scale(' + formatter.point(scale) +')');
|
||||||
if (skew && skew.x)
|
if (skew.x)
|
||||||
parts.push('skewX(' + formatter.number(skew.x) + ')');
|
parts.push('skewX(' + formatter.number(skew.x) + ')');
|
||||||
if (skew && skew.y)
|
if (skew.y)
|
||||||
parts.push('skewY(' + formatter.number(skew.y) + ')');
|
parts.push('skewY(' + formatter.number(skew.y) + ')');
|
||||||
attrs.transform = parts.join(' ');
|
attrs.transform = parts.join(' ');
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,8 +115,9 @@ new function() {
|
||||||
if (length > 2) {
|
if (length > 2) {
|
||||||
type = item._closed ? 'polygon' : 'polyline';
|
type = item._closed ? 'polygon' : 'polyline';
|
||||||
var parts = [];
|
var parts = [];
|
||||||
for(var i = 0; i < length; i++)
|
for (var i = 0; i < length; i++) {
|
||||||
parts.push(formatter.point(segments[i]._point));
|
parts.push(formatter.point(segments[i]._point));
|
||||||
|
}
|
||||||
attrs.points = parts.join(' ');
|
attrs.points = parts.join(' ');
|
||||||
} else {
|
} else {
|
||||||
type = 'line';
|
type = 'line';
|
||||||
|
@ -416,6 +417,7 @@ new function() {
|
||||||
? new Rectangle([0, 0], view.getViewSize())
|
? new Rectangle([0, 0], view.getViewSize())
|
||||||
: bounds === 'content'
|
: bounds === 'content'
|
||||||
? Item._getBounds(children, matrix, { stroke: true })
|
? Item._getBounds(children, matrix, { stroke: true })
|
||||||
|
.rect
|
||||||
: Rectangle.read([bounds], 0, { readNull: true }),
|
: Rectangle.read([bounds], 0, { readNull: true }),
|
||||||
attrs = {
|
attrs = {
|
||||||
version: '1.1',
|
version: '1.1',
|
||||||
|
|
|
@ -115,9 +115,9 @@ var PointText = TextItem.extend(/** @lends PointText# */{
|
||||||
x -= width / (justification === 'center' ? 2: 1);
|
x -= width / (justification === 'center' ? 2: 1);
|
||||||
// Until we don't have baseline measuring, assume 1 / 4 leading as a
|
// Until we don't have baseline measuring, assume 1 / 4 leading as a
|
||||||
// rough guess:
|
// rough guess:
|
||||||
var bounds = new Rectangle(x,
|
var rect = new Rectangle(x,
|
||||||
numLines ? - 0.75 * leading : 0,
|
numLines ? - 0.75 * leading : 0,
|
||||||
width, numLines * leading);
|
width, numLines * leading);
|
||||||
return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
|
return matrix ? matrix._transformBounds(rect, rect) : rect;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -125,7 +125,7 @@ var Numerical = new function() {
|
||||||
/**
|
/**
|
||||||
* The machine epsilon for a double precision (Javascript Number) is
|
* The machine epsilon for a double precision (Javascript Number) is
|
||||||
* 2.220446049250313e-16. (try this in the js console:
|
* 2.220446049250313e-16. (try this in the js console:
|
||||||
* (function(){for(var e=1;1<1+e/2;)e/=2;return e}())
|
* (function(){ for (var e = 1; 1 < 1+e/2;) e/=2; return e }())
|
||||||
*
|
*
|
||||||
* The constant MACHINE_EPSILON here refers to the constants δ and ε
|
* The constant MACHINE_EPSILON here refers to the constants δ and ε
|
||||||
* such that, the error introduced by addition, multiplication on a
|
* such that, the error introduced by addition, multiplication on a
|
||||||
|
|
|
@ -1271,12 +1271,11 @@ new function() { // Injection scope for event handling on the browser
|
||||||
point, prevPoint)
|
point, prevPoint)
|
||||||
// Next handle the hit-item, if it's different from the drag-item
|
// Next handle the hit-item, if it's different from the drag-item
|
||||||
// and not a descendant of it (in which case it would already have
|
// and not a descendant of it (in which case it would already have
|
||||||
// received an event in the call above). Use fallbacks to translate
|
// received an event in the call above).
|
||||||
// mousedrag to mousemove, since drag is handled above.
|
|
||||||
|| hitItem && hitItem !== dragItem
|
|| hitItem && hitItem !== dragItem
|
||||||
&& !hitItem.isDescendant(dragItem)
|
&& !hitItem.isDescendant(dragItem)
|
||||||
&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
|
&& emitMouseEvent(hitItem, null, type, event, point, prevPoint,
|
||||||
point, prevPoint, dragItem)
|
dragItem)
|
||||||
// Lastly handle the mouse events on the view, if we're still here.
|
// Lastly handle the mouse events on the view, if we're still here.
|
||||||
|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
|
|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
|
||||||
point, prevPoint));
|
point, prevPoint));
|
||||||
|
|
|
@ -876,3 +876,56 @@ test('Item#pivot', function() {
|
||||||
equals(path2.pivot, pivot.add(difference),
|
equals(path2.pivot, pivot.add(difference),
|
||||||
'Changing position of an item with applyMatrix = true should change pivot');
|
'Changing position of an item with applyMatrix = true should change pivot');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Item#position with irregular shape, #pivot and rotation', function() {
|
||||||
|
var path1 = new Path([ [0, 0], [200, 100], [0, 100] ]);
|
||||||
|
var path2 = path1.clone();
|
||||||
|
path2.pivot = path2.position;
|
||||||
|
equals(path1.position, new Point(100, 50),
|
||||||
|
'path1.position, before rotation');
|
||||||
|
path1.rotate(45);
|
||||||
|
equals(path1.position, new Point(64.64466, 50),
|
||||||
|
'path1.position, after rotation');
|
||||||
|
equals(path2.position, new Point(100, 50),
|
||||||
|
'path2.position with pivot, before rotation');
|
||||||
|
path2.rotate(45);
|
||||||
|
equals(path2.position, new Point(100, 50),
|
||||||
|
'path2.position with pivot, after rotation');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Item#scaling, #rotation', function() {
|
||||||
|
var expected = new Rectangle(100, 50, 100, 200);
|
||||||
|
|
||||||
|
var rect1 = new Path.Rectangle({
|
||||||
|
from: [100, 100],
|
||||||
|
to: [200, 200],
|
||||||
|
applyMatrix: false
|
||||||
|
});
|
||||||
|
var rect2 = rect1.clone();
|
||||||
|
|
||||||
|
rect1.scaling = [2, 1];
|
||||||
|
rect1.rotation = 90;
|
||||||
|
equals(rect1.bounds, expected,
|
||||||
|
'rect1.bounds, setting rect1.scaling before rect1.rotation');
|
||||||
|
|
||||||
|
rect2.rotation = 90;
|
||||||
|
rect2.scaling = [2, 1];
|
||||||
|
equals(rect2.bounds, expected,
|
||||||
|
'rect2.bounds, setting rect2.scaling before rect2.rotation');
|
||||||
|
|
||||||
|
var shape1 = new Shape.Rectangle({
|
||||||
|
from: [100, 100],
|
||||||
|
to: [200, 200]
|
||||||
|
});
|
||||||
|
var shape2 = shape1.clone();
|
||||||
|
|
||||||
|
shape1.scaling = [2, 1];
|
||||||
|
shape1.rotation = 90;
|
||||||
|
equals(shape1.bounds, expected,
|
||||||
|
'shape1.bounds, setting shape1.scaling before shape1.rotation');
|
||||||
|
|
||||||
|
shape2.rotation = 90;
|
||||||
|
shape2.scaling = [2, 1];
|
||||||
|
equals(shape2.bounds, expected,
|
||||||
|
'shape2.bounds, setting shape2.scaling before shape2.rotation');
|
||||||
|
});
|
||||||
|
|
|
@ -694,12 +694,15 @@ test('path.strokeBounds with applyMatrix disabled', function() {
|
||||||
strokeColor: 'red',
|
strokeColor: 'red',
|
||||||
strokeWidth: 10
|
strokeWidth: 10
|
||||||
});
|
});
|
||||||
equals(path.strokeBounds, new Rectangle(5, 5, 30, 30), 'path.strokeBounds, applyMatrix enabled');
|
equals(path.strokeBounds, new Rectangle(5, 5, 30, 30),
|
||||||
|
'path.strokeBounds, applyMatrix enabled');
|
||||||
path.applyMatrix = false;
|
path.applyMatrix = false;
|
||||||
equals(path.strokeBounds, new Rectangle(5, 5, 30, 30), 'path.strokeBounds, applyMatrix disabled');
|
equals(path.strokeBounds, new Rectangle(5, 5, 30, 30),
|
||||||
|
'path.strokeBounds, applyMatrix disabled');
|
||||||
path.scale([4, 2], [0, 0]);
|
path.scale([4, 2], [0, 0]);
|
||||||
var expected = new Rectangle(20, 10, 120, 60);
|
var expected = new Rectangle(20, 10, 120, 60);
|
||||||
equals(path.strokeBounds, expected, 'path.strokeBounds after scaling, applyMatrix disabled');
|
equals(path.strokeBounds, expected,
|
||||||
|
'path.strokeBounds after scaling, applyMatrix disabled');
|
||||||
function testHitResult() {
|
function testHitResult() {
|
||||||
// Hit-testing needs to handle applyMatrix disabled with stroke scaling,
|
// Hit-testing needs to handle applyMatrix disabled with stroke scaling,
|
||||||
// even when hit-testing on "distorted" stroke joins:
|
// even when hit-testing on "distorted" stroke joins:
|
||||||
|
@ -714,10 +717,29 @@ test('path.strokeBounds with applyMatrix disabled', function() {
|
||||||
testHitResult();
|
testHitResult();
|
||||||
path.applyMatrix = true;
|
path.applyMatrix = true;
|
||||||
expected = new Rectangle(35, 15, 90, 50);
|
expected = new Rectangle(35, 15, 90, 50);
|
||||||
equals(path.strokeBounds, expected, 'path.strokeBounds after scaling, applyMatrix enabled');
|
equals(path.strokeBounds, expected,
|
||||||
|
'path.strokeBounds after scaling, applyMatrix enabled');
|
||||||
testHitResult();
|
testHitResult();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('TEST', function() {
|
||||||
|
var path = new Path.Rectangle({
|
||||||
|
applyMatrix: false,
|
||||||
|
point: [10, 10],
|
||||||
|
size: [20, 20],
|
||||||
|
strokeScaling: true,
|
||||||
|
strokeColor: 'red',
|
||||||
|
strokeWidth: 10
|
||||||
|
});
|
||||||
|
path.scale([4, 2], [0, 0]);
|
||||||
|
equals(path.strokeBounds, new Rectangle(20, 10, 120, 60),
|
||||||
|
'path.strokeBounds after scaling, applyMatrix disabled');
|
||||||
|
path.applyMatrix = true;
|
||||||
|
equals(path.strokeBounds, new Rectangle(35, 15, 90, 50),
|
||||||
|
'path.strokeBounds after scaling, applyMatrix enabled');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
test('symbolItem.bounds with strokeScaling disabled', function() {
|
test('symbolItem.bounds with strokeScaling disabled', function() {
|
||||||
var path = new Path.Rectangle({
|
var path = new Path.Rectangle({
|
||||||
size: [20, 20],
|
size: [20, 20],
|
||||||
|
|
|
@ -154,7 +154,7 @@ test('transform test 1', function() {
|
||||||
var clones = 30;
|
var clones = 30;
|
||||||
var angle = 360 / clones;
|
var angle = 360 / clones;
|
||||||
|
|
||||||
for(var i = 0; i < clones; i++) {
|
for (var i = 0; i < clones; i++) {
|
||||||
var clonedPath = circlePath.clone();
|
var clonedPath = circlePath.clone();
|
||||||
clonedPath.rotate(angle * i, circlePath.bounds.topLeft);
|
clonedPath.rotate(angle * i, circlePath.bounds.topLeft);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue