--- a/server/php/basic/public_html/static/lib/paper/paper-full.js Fri Aug 28 23:04:21 2015 +0200
+++ b/server/php/basic/public_html/static/lib/paper/paper-full.js Mon Sep 07 16:34:30 2015 +0200
@@ -1,5 +1,5 @@
/*!
- * Paper.js v0.9.22 - The Swiss Army Knife of Vector Graphics Scripting.
+ * Paper.js v0.9.24 - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
@@ -9,7 +9,7 @@
*
* All rights reserved.
*
- * Date: Sat Feb 28 19:20:48 2015 +0100
+ * Date: Fri Aug 21 16:39:41 2015 +0200
*
***
*
@@ -88,7 +88,7 @@
val = dest[val.substring(1)] || val;
var isFunc = typeof val === 'function',
res = val,
- prev = preserve || isFunc
+ prev = preserve || isFunc && !val.base
? (val && val.get ? name in dest : dest[name])
: null,
bean;
@@ -161,19 +161,22 @@
extend: function() {
var base = this,
- ctor;
+ ctor,
+ proto;
for (var i = 0, l = arguments.length; i < l; i++)
if (ctor = arguments[i].initialize)
break;
ctor = ctor || function() {
base.apply(this, arguments);
};
- ctor.prototype = create(this.prototype);
- ctor.base = base;
- define(ctor.prototype, 'constructor',
+ proto = ctor.prototype = create(this.prototype);
+ define(proto, 'constructor',
{ value: ctor, writable: true, configurable: true });
inject(ctor, this, true);
- return arguments.length ? this.inject.apply(ctor, arguments) : ctor;
+ if (arguments.length)
+ this.inject.apply(ctor, arguments);
+ ctor.base = base;
+ return ctor;
}
}, true).inject({
inject: function() {
@@ -259,9 +262,10 @@
_set: function(props, exclude, dontCheck) {
if (props && (dontCheck || Base.isPlainObject(props))) {
- var orig = props._filtering || props;
- for (var key in orig) {
- if (orig.hasOwnProperty(key) && !(exclude && exclude[key])) {
+ var keys = Object.keys(props._filtering || props);
+ for (var i = 0, l = keys.length; i < l; i++) {
+ var key = keys[i];
+ if (!(exclude && exclude[key])) {
var value = props[key];
if (value !== undefined)
this[key] = value;
@@ -286,35 +290,33 @@
},
equals: function(obj1, obj2) {
- function checkKeys(o1, o2) {
- for (var i in o1)
- if (o1.hasOwnProperty(i) && !o2.hasOwnProperty(i))
- return false;
- return true;
- }
if (obj1 === obj2)
return true;
if (obj1 && obj1.equals)
return obj1.equals(obj2);
if (obj2 && obj2.equals)
return obj2.equals(obj1);
- if (Array.isArray(obj1) && Array.isArray(obj2)) {
- if (obj1.length !== obj2.length)
- return false;
- for (var i = 0, l = obj1.length; i < l; i++) {
- if (!Base.equals(obj1[i], obj2[i]))
+ if (obj1 && obj2
+ && typeof obj1 === 'object' && typeof obj2 === 'object') {
+ if (Array.isArray(obj1) && Array.isArray(obj2)) {
+ var length = obj1.length;
+ if (length !== obj2.length)
return false;
- }
- return true;
- }
- if (obj1 && typeof obj1 === 'object'
- && obj2 && typeof obj2 === 'object') {
- if (!checkKeys(obj1, obj2) || !checkKeys(obj2, obj1))
- return false;
- for (var i in obj1) {
- if (obj1.hasOwnProperty(i)
- && !Base.equals(obj1[i], obj2[i]))
+ while (length--) {
+ if (!Base.equals(obj1[length], obj2[length]))
+ return false;
+ }
+ } else {
+ var keys = Object.keys(obj1),
+ length = keys.length;
+ if (length !== Object.keys(obj2).length)
return false;
+ while (length--) {
+ var key = keys[length];
+ if (!(obj2.hasOwnProperty(key)
+ && Base.equals(obj1[key], obj2[key])))
+ return false;
+ }
}
return true;
}
@@ -443,10 +445,12 @@
res._compact = true;
} else if (Base.isPlainObject(obj)) {
res = {};
- for (var i in obj)
- if (obj.hasOwnProperty(i))
- res[i] = Base.serialize(obj[i], options, compact,
- dictionary);
+ var keys = Object.keys(obj);
+ for (var i = 0, l = keys.length; i < l; i++) {
+ var key = keys[i];
+ res[key] = Base.serialize(obj[key], options, compact,
+ dictionary);
+ }
} else if (typeof obj === 'number') {
res = options.formatter.number(obj, options.precision);
} else {
@@ -457,24 +461,23 @@
: res;
},
- deserialize: function(json, create, _data) {
+ deserialize: function(json, create, _data, _isDictionary) {
var res = json,
isRoot = !_data;
_data = _data || {};
if (Array.isArray(json)) {
var type = json[0],
isDictionary = type === 'dictionary';
- if (!isDictionary) {
- if (_data.dictionary && json.length == 1 && /^#/.test(type))
- return _data.dictionary[type];
- type = Base.exports[type];
- }
+ if (json.length == 1 && /^#/.test(type))
+ return _data.dictionary[type];
+ type = Base.exports[type];
res = [];
+ if (_isDictionary)
+ _data.dictionary = res;
for (var i = type ? 1 : 0, l = json.length; i < l; i++)
- res.push(Base.deserialize(json[i], create, _data));
- if (isDictionary) {
- _data.dictionary = res[0];
- } else if (type) {
+ res.push(Base.deserialize(json[i], create, _data,
+ isDictionary));
+ if (type) {
var args = res;
if (create) {
res = create(type, args);
@@ -485,6 +488,8 @@
}
} else if (Base.isPlainObject(json)) {
res = {};
+ if (_isDictionary)
+ _data.dictionary = res;
for (var key in json)
res[key] = Base.deserialize(json[key], create, _data);
}
@@ -570,15 +575,14 @@
this.on(key, value);
}, this);
} else {
- var entry = this._eventTypes[type];
- if (entry) {
- var handlers = this._callbacks = this._callbacks || {};
- handlers = handlers[type] = handlers[type] || [];
- if (handlers.indexOf(func) === -1) {
- handlers.push(func);
- if (entry.install && handlers.length == 1)
- entry.install.call(this, type);
- }
+ var types = this._eventTypes,
+ entry = types && types[type],
+ handlers = this._callbacks = this._callbacks || {};
+ handlers = handlers[type] = handlers[type] || [];
+ if (handlers.indexOf(func) === -1) {
+ handlers.push(func);
+ if (entry && entry.install && handlers.length == 1)
+ entry.install.call(this, type);
}
}
return this;
@@ -591,13 +595,14 @@
}, this);
return;
}
- var entry = this._eventTypes[type],
+ var types = this._eventTypes,
+ entry = types && types[type],
handlers = this._callbacks && this._callbacks[type],
index;
- if (entry && handlers) {
+ if (handlers) {
if (!func || (index = handlers.indexOf(func)) !== -1
&& handlers.length === 1) {
- if (entry.uninstall)
+ if (entry && entry.uninstall)
entry.uninstall.call(this, type);
delete this._callbacks[type];
} else if (index !== -1) {
@@ -619,10 +624,11 @@
if (!handlers)
return false;
var args = [].slice.call(arguments, 1);
+ handlers = handlers.slice();
for (var i = 0, l = handlers.length; i < l; i++) {
- if (handlers[i].apply(this, args) === false
- && event && event.stop) {
- event.stop();
+ if (handlers[i].apply(this, args) === false) {
+ if (event && event.stop)
+ event.stop();
break;
}
}
@@ -642,8 +648,9 @@
key = install ? 'install' : 'uninstall';
for (var type in handlers) {
if (handlers[type].length > 0) {
- var entry = this._eventTypes[type],
- func = entry[key];
+ var types = this._eventTypes,
+ entry = types && types[type],
+ func = entry && entry[key];
if (func)
func.call(this, type);
}
@@ -708,8 +715,15 @@
}
if (!this.browser) {
- var browser = proto.browser = {};
- navigator.userAgent.toLowerCase().replace(
+ var agent = navigator.userAgent.toLowerCase(),
+ platform = (/(win)/.exec(agent)
+ || /(mac)/.exec(agent)
+ || /(linux)/.exec(agent)
+ || [])[0],
+ browser = proto.browser = { platform: platform };
+ if (platform)
+ browser[platform] = true;
+ agent.replace(
/(opera|chrome|safari|webkit|firefox|msie|trident|atom)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:([.\d]+))?/g,
function(all, n, v1, v2, rv) {
if (!browser.chrome) {
@@ -732,7 +746,7 @@
}
},
- version: '0.9.22',
+ version: '0.9.24',
getView: function() {
return this.project && this.project.getView();
@@ -969,16 +983,9 @@
D;
b /= 2;
D = b * b - a * c;
- if (abs(D) < MACHINE_EPSILON) {
- var pow = Math.pow,
- gmC = pow(abs(a*b*c), 1/3);
+ if (D !== 0 && abs(D) < MACHINE_EPSILON) {
+ var gmC = pow(abs(a * b * c), 1 / 3);
if (gmC < 1e-8) {
- /*
- * we multiply with a factor to normalize the
- * coefficients. The factor is just the nearest exponent
- * of 10, big enough to raise all the coefficients to
- * nearly [-1, +1] range.
- */
var mult = pow(10, abs(
Math.floor(Math.log(gmC) * Math.LOG10E)));
if (!isFinite(mult))
@@ -989,9 +996,9 @@
D = b * b - a * c;
}
}
- if (abs(a) < MACHINE_EPSILON) {
- if (abs(B) < MACHINE_EPSILON)
- return abs(c) < MACHINE_EPSILON ? -1 : 0;
+ if (abs(a) < EPSILON) {
+ if (abs(B) < EPSILON)
+ return abs(c) < EPSILON ? -1 : 0;
x1 = -c / B;
} else {
if (D >= -MACHINE_EPSILON) {
@@ -1016,13 +1023,14 @@
},
solveCubic: function(a, b, c, d, roots, min, max) {
- var x, b1, c2, count = 0;
- if (a === 0) {
+ var count = 0,
+ x, b1, c2;
+ if (abs(a) < EPSILON) {
a = b;
b1 = c;
c2 = d;
x = Infinity;
- } else if (d === 0) {
+ } else if (abs(d) < EPSILON) {
b1 = b;
c2 = c;
x = 0;
@@ -1070,6 +1078,23 @@
};
};
+var UID = {
+ _id: 1,
+ _pools: {},
+
+ get: function(ctor) {
+ if (ctor) {
+ var name = ctor._class,
+ pool = this._pools[name];
+ if (!pool)
+ pool = this._pools[name] = { _id: 1 };
+ return pool._id++;
+ } else {
+ return this._id++;
+ }
+ }
+};
+
var Point = Base.extend({
_class: 'Point',
_readIndex: true,
@@ -1284,12 +1309,14 @@
return this.getDistance(point) < tolerance;
},
- isColinear: function(point) {
- return Math.abs(this.cross(point)) < 1e-12;
- },
+ isCollinear: function(point) {
+ return Math.abs(this.cross(point)) < 0.000001;
+ },
+
+ isColinear: '#isCollinear',
isOrthogonal: function(point) {
- return Math.abs(this.dot(point)) < 1e-12;
+ return Math.abs(this.dot(point)) < 0.000001;
},
isZero: function() {
@@ -2638,7 +2665,7 @@
_class: 'Symbol',
initialize: function Symbol(item, dontCenter) {
- this._id = Symbol._id = (Symbol._id || 0) + 1;
+ this._id = UID.get();
this.project = paper.project;
this.project.symbols.push(this);
if (item)
@@ -2735,7 +2762,7 @@
matrix = this._matrix = new Matrix(),
project = hasProps && props.project || paper.project;
if (!internal)
- this._id = Item._id = (Item._id || 0) + 1;
+ this._id = UID.get();
this._applyMatrix = this._canApplyMatrix && paper.settings.applyMatrix;
if (point)
matrix.translate(point);
@@ -2751,7 +2778,8 @@
}
}
if (hasProps && props !== Item.NO_INSERT)
- this._set(props, { insert: true, parent: true }, true);
+ this._set(props, { insert: true, project: true, parent: true },
+ true);
return hasProps;
},
@@ -3046,14 +3074,11 @@
},
setPivot: function() {
- this._pivot = Point.read(arguments);
+ this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
this._position = undefined;
},
_pivot: null,
-
- getRegistration: '#getPivot',
- setRegistration: '#setPivot'
}, Base.each(['bounds', 'strokeBounds', 'handleBounds', 'roughBounds',
'internalBounds', 'internalRoughBounds'],
function(key) {
@@ -3080,6 +3105,7 @@
var children = this._children;
if (!children || children.length == 0)
return new Rectangle();
+ Item._updateBoundsCache(this, cacheItem);
var x1 = Infinity,
x2 = -x1,
y1 = x1,
@@ -3120,18 +3146,7 @@
matrix = matrix && matrix.orNullIfIdentity();
var _matrix = internalGetter ? null : this._matrix.orNullIfIdentity(),
cache = (!matrix || matrix.equals(_matrix)) && getter;
- var cacheParent = this._parent || this._parentSymbol;
- if (cacheParent) {
- var id = cacheItem._id,
- ref = cacheParent._boundsCache = cacheParent._boundsCache || {
- ids: {},
- list: []
- };
- if (!ref.ids[id]) {
- ref.list.push(cacheItem);
- ref.ids[id] = cacheItem;
- }
- }
+ Item._updateBoundsCache(this._parent || this._parentSymbol, cacheItem);
if (cache && this._bounds && this._bounds[cache])
return this._bounds[cache].clone();
var bounds = this._getBounds(internalGetter || getter,
@@ -3146,11 +3161,25 @@
},
statics: {
+ _updateBoundsCache: function(parent, item) {
+ if (parent) {
+ var id = item._id,
+ ref = parent._boundsCache = parent._boundsCache || {
+ ids: {},
+ list: []
+ };
+ if (!ref.ids[id]) {
+ ref.list.push(item);
+ ref.ids[id] = item;
+ }
+ }
+ },
+
_clearBoundsCache: function(item) {
var cache = item._boundsCache;
if (cache) {
item._bounds = item._position = item._boundsCache = undefined;
- for (var i = 0, list = cache.list, l = list.length; i < l; i++) {
+ for (var i = 0, list = cache.list, l = list.length; i < l; i++){
var other = list[i];
if (other !== item) {
other._bounds = other._position = undefined;
@@ -3206,8 +3235,9 @@
return this._matrix;
},
- setMatrix: function(matrix) {
- this._matrix.initialize(matrix);
+ setMatrix: function() {
+ var matrix = this._matrix;
+ matrix.initialize.apply(matrix, arguments);
if (this._applyMatrix) {
this.transform(null, true);
} else {
@@ -3340,24 +3370,27 @@
return this._clone(new this.constructor(Item.NO_INSERT), insert);
},
- _clone: function(copy, insert) {
+ _clone: function(copy, insert, includeMatrix) {
+ var keys = ['_locked', '_visible', '_blendMode', '_opacity',
+ '_clipMask', '_guide'],
+ children = this._children;
copy.setStyle(this._style);
- if (this._children) {
- for (var i = 0, l = this._children.length; i < l; i++)
- copy.addChild(this._children[i].clone(false), true);
- }
- if (insert || insert === undefined)
- copy.insertAbove(this);
- var keys = ['_locked', '_visible', '_blendMode', '_opacity',
- '_clipMask', '_guide', '_applyMatrix'];
+ for (var i = 0, l = children && children.length; i < l; i++) {
+ copy.addChild(children[i].clone(false), true);
+ }
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
if (this.hasOwnProperty(key))
copy[key] = this[key];
}
- copy._matrix.initialize(this._matrix);
+ if (includeMatrix !== false)
+ copy._matrix.initialize(this._matrix);
+ copy.setApplyMatrix(this._applyMatrix);
+ copy.setPivot(this._pivot);
+ copy.setSelected(this._selected);
copy._data = this._data ? Base.clone(this._data) : null;
- copy.setSelected(this._selected);
+ if (insert || insert === undefined)
+ copy.insertAbove(this);
if (this._name)
copy.setName(this._name, true);
return copy;
@@ -3517,11 +3550,14 @@
}
return true;
}
- if (typeof name === 'object') {
+ var type = typeof name;
+ if (type === 'object') {
for (var key in name) {
if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
return false;
}
+ } else if (type === 'function') {
+ return name(this);
} else {
var value = /^(empty|editable)$/.test(name)
? this['is' + Base.capitalize(name)]()
@@ -3559,15 +3595,17 @@
statics: {
_getItems: function _getItems(children, match, matrix, param,
firstOnly) {
- if (!param) {
+ if (!param && typeof match === 'object') {
var overlapping = match.overlapping,
inside = match.inside,
bounds = overlapping || inside,
rect = bounds && Rectangle.read([bounds]);
param = {
items: [],
- inside: rect,
- overlapping: overlapping && new Path.Rectangle({
+ inside: !!inside,
+ overlapping: !!overlapping,
+ rect: rect,
+ path: overlapping && new Path.Rectangle({
rectangle: rect,
insert: false
})
@@ -3576,20 +3614,20 @@
match = Base.set({}, match,
{ inside: true, overlapping: true });
}
- var items = param.items,
- inside = param.inside,
- overlapping = param.overlapping;
- matrix = inside && (matrix || new Matrix());
+ var items = param && param.items,
+ rect = param && param.rect;
+ matrix = rect && (matrix || new Matrix());
for (var i = 0, l = children && children.length; i < l; i++) {
var child = children[i],
childMatrix = matrix && matrix.chain(child._matrix),
add = true;
- if (inside) {
+ if (rect) {
var bounds = child.getBounds(childMatrix);
- if (!inside.intersects(bounds))
+ if (!rect.intersects(bounds))
continue;
- if (!(inside && inside.contains(bounds)) && !(overlapping
- && overlapping.intersects(child, childMatrix)))
+ if (!(param.inside && rect.contains(bounds))
+ && !(param.overlapping && (bounds.contains(rect)
+ || param.path.intersects(child, childMatrix))))
add = false;
}
if (add && child.matches(match)) {
@@ -4066,7 +4104,7 @@
|| param.clip
|| (nativeBlend || normalBlend && opacity < 1)
&& this._canComposite(),
- pixelRatio = param.pixelRatio,
+ pixelRatio = param.pixelRatio || 1,
mainCtx, itemOffset, prevOffset;
if (!direct) {
var bounds = this.getStrokeBounds(getViewMatrix(globalMatrix));
@@ -4422,16 +4460,14 @@
},
toPath: function(insert) {
- var path = new Path[Base.capitalize(this._type)]({
+ var path = this._clone(new Path[Base.capitalize(this._type)]({
center: new Point(),
size: this._size,
radius: this._radius,
insert: false
- });
- path.setStyle(this._style);
- path.transform(this._matrix);
- if (insert || insert === undefined)
- path.insertAbove(this);
+ }), insert);
+ if (paper.settings.applyMatrix)
+ path.setApplyMatrix(true);
return path;
},
@@ -4455,7 +4491,7 @@
size = this._size,
width = size.width,
height = size.height;
- if (untransformed && type === 'rect' && rx === 0 && ry === 0) {
+ if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
ctx.rect(-width / 2, -height / 2, width, height);
} else {
var x = width / 2,
@@ -4647,6 +4683,7 @@
_boundsGetter: 'getBounds',
_boundsSelected: true,
_serializeFields: {
+ crossOrigin: null,
source: null
},
@@ -4680,6 +4717,7 @@
copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
copy.setImage(copyCanvas);
}
+ copy._crossOrigin = this._crossOrigin;
return this._clone(copy, insert);
},
@@ -4799,6 +4837,7 @@
setSource: function(src) {
var that = this,
+ crossOrigin = this._crossOrigin,
image;
function loaded() {
@@ -4811,20 +4850,29 @@
}
}
- image = document.getElementById(src) || new Image();
-
+ image = document.getElementById(src) || new Image();
+ if (crossOrigin)
+ image.crossOrigin = crossOrigin;
if (image.naturalWidth && image.naturalHeight) {
setTimeout(loaded, 0);
} else {
- DomEvent.add(image, {
- load: loaded
- });
+ DomEvent.add(image, { load: loaded });
if (!image.src)
image.src = src;
}
this.setImage(image);
},
+ getCrossOrigin: function() {
+ return this._image && this._image.crossOrigin || this._crossOrigin || '';
+ },
+
+ setCrossOrigin: function(crossOrigin) {
+ this._crossOrigin = crossOrigin;
+ if (this._image)
+ this._image.crossOrigin = crossOrigin;
+ },
+
getElement: function() {
return this._canvas || this._loaded && this._image;
}
@@ -5109,7 +5157,7 @@
},
_serialize: function(options) {
- return Base.serialize(this.isLinear() ? this._point
+ return Base.serialize(this.isStraight() ? this._point
: [this._point, this._handleIn, this._handleOut],
options, true);
},
@@ -5160,53 +5208,34 @@
this._handleOut.set(point.x, point.y);
},
- isLinear: function() {
+ hasHandles: function() {
+ return !this.isStraight();
+ },
+
+ isStraight: function() {
return this._handleIn.isZero() && this._handleOut.isZero();
},
- setLinear: function(linear) {
- if (linear) {
- this._handleIn.set(0, 0);
- this._handleOut.set(0, 0);
- } else {
- }
- },
-
- isColinear: function(segment) {
- var next1 = this.getNext(),
- next2 = segment.getNext();
- return this._handleOut.isZero() && next1._handleIn.isZero()
- && segment._handleOut.isZero() && next2._handleIn.isZero()
- && next1._point.subtract(this._point).isColinear(
- next2._point.subtract(segment._point));
- },
+ isLinear: function() {
+ return Segment.isLinear(this, this.getNext());
+ },
+
+ isCollinear: function(segment) {
+ return Segment.isCollinear(this, this.getNext(),
+ segment, segment.getNext());
+ },
+
+ isColinear: '#isCollinear',
isOrthogonal: function() {
- var prev = this.getPrevious(),
- next = this.getNext();
- return prev._handleOut.isZero() && this._handleIn.isZero()
- && this._handleOut.isZero() && next._handleIn.isZero()
- && this._point.subtract(prev._point).isOrthogonal(
- next._point.subtract(this._point));
- },
-
- isArc: function() {
- var next = this.getNext(),
- handle1 = this._handleOut,
- handle2 = next._handleIn,
- kappa = 0.5522847498307936;
- if (handle1.isOrthogonal(handle2)) {
- var from = this._point,
- to = next._point,
- corner = new Line(from, handle1, true).intersect(
- new Line(to, handle2, true), true);
- return corner && Numerical.isZero(handle1.getLength() /
- corner.subtract(from).getLength() - kappa)
- && Numerical.isZero(handle2.getLength() /
- corner.subtract(to).getLength() - kappa);
- }
- return false;
- },
+ return Segment.isOrthogonal(this.getPrevious(), this, this.getNext());
+ },
+
+ isOrthogonalArc: function() {
+ return Segment.isOrthogonalArc(this, this.getNext());
+ },
+
+ isArc: '#isOrthogonalArc',
_selectionState: 0,
@@ -5361,6 +5390,46 @@
}
}
return coords;
+ },
+
+ statics: {
+
+ isLinear: function(seg1, seg2) {
+ var l = seg2._point.subtract(seg1._point);
+ return l.isCollinear(seg1._handleOut)
+ && l.isCollinear(seg2._handleIn);
+ },
+
+ isCollinear: function(seg1, seg2, seg3, seg4) {
+ return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+ && seg3._handleOut.isZero() && seg4._handleIn.isZero()
+ && seg2._point.subtract(seg1._point).isCollinear(
+ seg4._point.subtract(seg3._point));
+ },
+
+ isOrthogonal: function(seg1, seg2, seg3) {
+ return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+ && seg2._handleOut.isZero() && seg3._handleIn.isZero()
+ && seg2._point.subtract(seg1._point).isOrthogonal(
+ seg3._point.subtract(seg2._point));
+ },
+
+ isOrthogonalArc: function(seg1, seg2) {
+ var handle1 = seg1._handleOut,
+ handle2 = seg2._handleIn,
+ kappa = 0.5522847498307936;
+ if (handle1.isOrthogonal(handle2)) {
+ var pt1 = seg1._point,
+ pt2 = seg2._point,
+ corner = new Line(pt1, handle1, true).intersect(
+ new Line(pt2, handle2, true), true);
+ return corner && Numerical.isZero(handle1.getLength() /
+ corner.subtract(pt1).getLength() - kappa)
+ && Numerical.isZero(handle2.getLength() /
+ corner.subtract(pt2).getLength() - kappa);
+ }
+ return false;
+ },
}
});
@@ -5586,9 +5655,22 @@
return Curve.getLength(this.getValues(), from, to);
},
+ hasHandles: function() {
+ return !this._segment1._handleOut.isZero()
+ || !this._segment2._handleIn.isZero();
+ },
+
isLinear: function() {
- return this._segment1._handleOut.isZero()
- && this._segment2._handleIn.isZero();
+ return Segment.isLinear(this._segment1, this._segment2);
+ },
+
+ isCollinear: function(curve) {
+ return Ssegment.isCollinear(this._segment1, this._segment2,
+ curve._segment1, curve._segment2);
+ },
+
+ isOrthogonalArc: function() {
+ return Segment.isOrthogonalArc(this._segment1, this._segment2);
},
getIntersections: function(curve) {
@@ -5698,54 +5780,6 @@
return values;
},
- evaluate: function(v, t, type) {
- var p1x = v[0], p1y = v[1],
- c1x = v[2], c1y = v[3],
- c2x = v[4], c2y = v[5],
- p2x = v[6], p2y = v[7],
- tolerance = 0.000001,
- x, y;
-
- if (type === 0 && (t < tolerance || t > 1 - tolerance)) {
- var isZero = t < tolerance;
- x = isZero ? p1x : p2x;
- y = isZero ? p1y : p2y;
- } else {
- var cx = 3 * (c1x - p1x),
- bx = 3 * (c2x - c1x) - cx,
- ax = p2x - p1x - cx - bx,
-
- cy = 3 * (c1y - p1y),
- by = 3 * (c2y - c1y) - cy,
- ay = p2y - p1y - cy - by;
- if (type === 0) {
- x = ((ax * t + bx) * t + cx) * t + p1x;
- y = ((ay * t + by) * t + cy) * t + p1y;
- } else {
- if (t < tolerance && c1x === p1x && c1y === p1y
- || t > 1 - tolerance && c2x === p2x && c2y === p2y) {
- x = c2x - c1x;
- y = c2y - c1y;
- } else if (t < tolerance) {
- x = cx;
- y = cy;
- } else if (t > 1 - tolerance) {
- x = 3 * (p2x - c2x);
- y = 3 * (p2y - c2y);
- } else {
- x = (3 * ax * t + 2 * bx) * t + cx;
- y = (3 * ay * t + 2 * by) * t + cy;
- }
- if (type === 3) {
- var x2 = 6 * ax * t + 2 * bx,
- y2 = 6 * ay * t + 2 * by;
- return (x * y2 - y * x2) / Math.pow(x * x + y * y, 3 / 2);
- }
- }
- }
- return type === 2 ? new Point(y, -x) : new Point(x, y);
- },
-
subdivide: function(v, t) {
var p1x = v[0], p1y = v[1],
c1x = v[2], c1y = v[3],
@@ -5773,10 +5807,7 @@
p2 = v[coord + 6],
c = 3 * (c1 - p1),
b = 3 * (c2 - c1) - c,
- a = p2 - p1 - c - b,
- isZero = Numerical.isZero;
- if (isZero(a) && isZero(b))
- a = b = 0;
+ a = p2 - p1 - c - b;
return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
},
@@ -5791,17 +5822,20 @@
sx = Curve.solveCubic(v, 0, x, txs, 0, 1),
sy = Curve.solveCubic(v, 1, y, tys, 0, 1),
tx, ty;
- for (var cx = 0; sx == -1 || cx < sx;) {
- if (sx == -1 || (tx = txs[cx++]) >= 0 && tx <= 1) {
- for (var cy = 0; sy == -1 || cy < sy;) {
- if (sy == -1 || (ty = tys[cy++]) >= 0 && ty <= 1) {
- if (sx == -1) tx = ty;
- else if (sy == -1) ty = tx;
+ for (var cx = 0; sx === -1 || cx < sx;) {
+ if (sx === -1 || (tx = txs[cx++]) > 0 && tx < 1) {
+ for (var cy = 0; sy === -1 || cy < sy;) {
+ if (sy === -1 || (ty = tys[cy++]) > 0 && ty < 1) {
+ if (sx === -1) {
+ tx = ty;
+ } else if (sy === -1) {
+ ty = tx;
+ }
if (Math.abs(tx - ty) < tolerance)
return (tx + ty) * 0.5;
}
}
- if (sx == -1)
+ if (sx === -1)
break;
}
}
@@ -5816,10 +5850,18 @@
return v;
},
- isLinear: function(v) {
+ hasHandles: function(v) {
var isZero = Numerical.isZero;
- return isZero(v[0] - v[2]) && isZero(v[1] - v[3])
- && isZero(v[4] - v[6]) && isZero(v[5] - v[7]);
+ return !(isZero(v[0] - v[2]) && isZero(v[1] - v[3])
+ && isZero(v[4] - v[6]) && isZero(v[5] - v[7]));
+ },
+
+ isLinear: function(v) {
+ var p1x = v[0], p1y = v[1],
+ p2x = v[6], p2y = v[7],
+ l = new Point(p2x - p1x, p2y - p1y);
+ return l.isCollinear(new Point(v[2] - p1x, v[3] - p1y))
+ && l.isCollinear(new Point(v[4] - p2x, v[5] - p2y));
},
isFlatEnough: function(v, tolerance) {
@@ -5891,7 +5933,8 @@
padding);
}
}
-}}, Base.each(['getBounds', 'getStrokeBounds', 'getHandleBounds', 'getRoughBounds'],
+}}, Base.each(
+ ['getBounds', 'getStrokeBounds', 'getHandleBounds', 'getRoughBounds'],
function(name) {
this[name] = function() {
if (!this._bounds)
@@ -5906,18 +5949,7 @@
},
{
-}), Base.each(['getPoint', 'getTangent', 'getNormal', 'getCurvature'],
- function(name, index) {
- this[name + 'At'] = function(offset, isParameter) {
- var values = this.getValues();
- return Curve.evaluate(values, isParameter
- ? offset : Curve.getParameterAt(values, offset, 0), index);
- };
- this[name] = function(parameter) {
- return Curve.evaluate(this.getValues(), parameter, index);
- };
- },
-{
+}), {
beans: false,
getParameterAt: function(offset, start) {
@@ -5930,9 +5962,10 @@
},
getLocationAt: function(offset, isParameter) {
- if (!isParameter)
- offset = this.getParameterAt(offset);
- return offset >= 0 && offset <= 1 && new CurveLocation(this, offset);
+ var t = isParameter ? offset : this.getParameterAt(offset);
+ return t != null && t >= 0 && t <= 1
+ ? new CurveLocation(this, t)
+ : null;
},
getLocationOf: function() {
@@ -5954,8 +5987,7 @@
function refine(t) {
if (t >= 0 && t <= 1) {
- var dist = point.getDistance(
- Curve.evaluate(values, t, 0), true);
+ var dist = point.getDistance(Curve.getPoint(values, t), true);
if (dist < minDist) {
minDist = dist;
minT = t;
@@ -5972,7 +6004,7 @@
if (!refine(minT - step) && !refine(minT + step))
step /= 2;
}
- var pt = Curve.evaluate(values, minT, 0);
+ var pt = Curve.getPoint(values, minT);
return new CurveLocation(this, minT, pt, null, null, null,
point.getDistance(pt));
},
@@ -5981,7 +6013,23 @@
return this.getNearestLocation.apply(this, arguments).getPoint();
}
-}),
+},
+new function() {
+ var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
+ 'getWeightedNormal', 'getCurvature'];
+ return Base.each(methods,
+ function(name) {
+ this[name + 'At'] = function(offset, isParameter) {
+ var values = this.getValues();
+ return Curve[name](values, isParameter ? offset
+ : Curve.getParameterAt(values, offset, 0));
+ };
+ }, {
+ statics: {
+ evaluateMethods: methods
+ }
+ })
+},
new function() {
function getLengthIntegrand(v) {
@@ -6009,6 +6057,64 @@
return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
}
+ function evaluate(v, t, type, normalized) {
+ if (t == null || t < 0 || t > 1)
+ return null;
+ var p1x = v[0], p1y = v[1],
+ c1x = v[2], c1y = v[3],
+ c2x = v[4], c2y = v[5],
+ p2x = v[6], p2y = v[7],
+ tolerance = 0.000001,
+ x, y;
+
+ if (type === 0 && (t < tolerance || t > 1 - tolerance)) {
+ var isZero = t < tolerance;
+ x = isZero ? p1x : p2x;
+ y = isZero ? p1y : p2y;
+ } else {
+ var cx = 3 * (c1x - p1x),
+ bx = 3 * (c2x - c1x) - cx,
+ ax = p2x - p1x - cx - bx,
+
+ cy = 3 * (c1y - p1y),
+ by = 3 * (c2y - c1y) - cy,
+ ay = p2y - p1y - cy - by;
+ if (type === 0) {
+ x = ((ax * t + bx) * t + cx) * t + p1x;
+ y = ((ay * t + by) * t + cy) * t + p1y;
+ } else {
+ if (t < tolerance) {
+ x = cx;
+ y = cy;
+ } else if (t > 1 - tolerance) {
+ x = 3 * (p2x - c2x);
+ y = 3 * (p2y - c2y);
+ } else {
+ x = (3 * ax * t + 2 * bx) * t + cx;
+ y = (3 * ay * t + 2 * by) * t + cy;
+ }
+ if (normalized) {
+ if (x === 0 && y === 0
+ && (t < tolerance || t > 1 - tolerance)) {
+ x = c2x - c1x;
+ y = c2y - c1y;
+ }
+ var len = Math.sqrt(x * x + y * y);
+ x /= len;
+ y /= len;
+ }
+ if (type === 3) {
+ var x2 = 6 * ax * t + 2 * bx,
+ y2 = 6 * ay * t + 2 * by,
+ d = Math.pow(x * x + y * y, 3 / 2);
+ x = d !== 0 ? (x * y2 - y * x2) / d : 0;
+ y = 0;
+ }
+ }
+ }
+ return type === 2 ? new Point(y, -x) : new Point(x, y);
+ }
+
return {
statics: true,
@@ -6034,14 +6140,19 @@
start = offset < 0 ? 1 : 0
if (offset === 0)
return start;
- var forward = offset > 0,
+ var tolerance = 0.000001,
+ abs = Math.abs,
+ forward = offset > 0,
a = forward ? start : 0,
b = forward ? 1 : start,
ds = getLengthIntegrand(v),
rangeLength = Numerical.integrate(ds, a, b,
getIterations(a, b));
- if (Math.abs(offset) >= rangeLength)
+ if (abs(offset - rangeLength) < tolerance) {
return forward ? b : a;
+ } else if (abs(offset) > rangeLength) {
+ return null;
+ }
var guess = offset / rangeLength,
length = 0;
function f(t) {
@@ -6051,7 +6162,31 @@
return length - offset;
}
return Numerical.findRoot(f, ds, start + guess, a, b, 16,
- 0.000001);
+ tolerance);
+ },
+
+ getPoint: function(v, t) {
+ return evaluate(v, t, 0, false);
+ },
+
+ getTangent: function(v, t) {
+ return evaluate(v, t, 1, true);
+ },
+
+ getWeightedTangent: function(v, t) {
+ return evaluate(v, t, 1, false);
+ },
+
+ getNormal: function(v, t) {
+ return evaluate(v, t, 2, true);
+ },
+
+ getWeightedNormal: function(v, t) {
+ return evaluate(v, t, 2, false);
+ },
+
+ getCurvature: function(v, t) {
+ return evaluate(v, t, 3, false).x;
}
};
}, new function() {
@@ -6079,7 +6214,7 @@
dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
tMinNew, tMaxNew, tDiff;
- if (q0x === q3x && uMax - uMin <= tolerance && recursion > 3) {
+ if (q0x === q3x && uMax - uMin < tolerance && recursion > 3) {
tMaxNew = tMinNew = (tMax + tMin) / 2;
tDiff = 0;
} else {
@@ -6123,12 +6258,12 @@
t2 = uMin + (uMax - uMin) / 2;
if (reverse) {
addLocation(locations, include,
- curve2, t2, Curve.evaluate(v2, t2, 0),
- curve1, t1, Curve.evaluate(v1, t1, 0));
+ curve2, t2, Curve.getPoint(v2, t2),
+ curve1, t1, Curve.getPoint(v1, t1));
} else {
addLocation(locations, include,
- curve1, t1, Curve.evaluate(v1, t1, 0),
- curve2, t2, Curve.evaluate(v2, t2, 0));
+ curve1, t1, Curve.getPoint(v1, t1),
+ curve2, t2, Curve.getPoint(v2, t2));
}
} else if (tDiff > 0) {
addCurveIntersections(v2, v1, curve2, curve1, locations, include,
@@ -6219,14 +6354,14 @@
count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
for (var i = 0; i < count; i++) {
var tc = roots[i],
- x = Curve.evaluate(rvc, tc, 0).x;
+ x = Curve.getPoint(rvc, tc).x;
if (x >= 0 && x <= rlx2) {
var tl = Curve.getParameterOf(rvl, x, 0),
t1 = flip ? tl : tc,
t2 = flip ? tc : tl;
addLocation(locations, include,
- curve1, t1, Curve.evaluate(v1, t1, 0),
- curve2, t2, Curve.evaluate(v2, t2, 0));
+ curve1, t1, Curve.getPoint(v1, t1),
+ curve2, t2, Curve.getPoint(v2, t2));
}
}
}
@@ -6322,16 +6457,18 @@
initialize: function CurveLocation(curve, parameter, point, _curve2,
_parameter2, _point2, _distance) {
- this._id = CurveLocation._id = (CurveLocation._id || 0) + 1;
+ this._id = UID.get(CurveLocation);
+ var path = curve._path;
+ this._version = path ? path._version : 0;
this._curve = curve;
- this._segment1 = curve._segment1;
- this._segment2 = curve._segment2;
this._parameter = parameter;
- this._point = point;
+ this._point = point || curve.getPointAt(parameter, true);
this._curve2 = _curve2;
this._parameter2 = _parameter2;
this._point2 = _point2;
this._distance = _distance;
+ this._segment1 = curve._segment1;
+ this._segment2 = curve._segment2;
},
getSegment: function(_preferFirst) {
@@ -6354,24 +6491,22 @@
return this._segment;
},
- getCurve: function(_uncached) {
- if (!this._curve || _uncached) {
- this._curve = this._segment1.getCurve();
- if (this._curve.getParameterOf(this._point) == null)
- this._curve = this._segment2.getPrevious().getCurve();
- }
- return this._curve;
- },
-
- getIntersection: function() {
- var intersection = this._intersection;
- if (!intersection && this._curve2) {
- var param = this._parameter2;
- this._intersection = intersection = new CurveLocation(
- this._curve2, param, this._point2 || this._point, this);
- intersection._intersection = this;
- }
- return intersection;
+ getCurve: function() {
+ var curve = this._curve,
+ path = curve && curve._path;
+ if (path && path._version !== this._version) {
+ curve = null;
+ this._parameter = null;
+ }
+ if (!curve) {
+ curve = this._segment1.getCurve();
+ if (curve.getParameterOf(this._point) == null)
+ curve = this._segment2.getPrevious().getCurve();
+ this._curve = curve;
+ path = curve._path;
+ this._version = path ? path._version : 0;
+ }
+ return curve;
},
getPath: function() {
@@ -6384,6 +6519,18 @@
return curve && curve.getIndex();
},
+ getParameter: function() {
+ var curve = this.getCurve(),
+ parameter = this._parameter;
+ return curve && parameter == null
+ ? this._parameter = curve.getParameterOf(this._point)
+ : parameter;
+ },
+
+ getPoint: function() {
+ return this._point;
+ },
+
getOffset: function() {
var path = this.getPath();
return path ? path._getOffset(this) : this.getCurveOffset();
@@ -6395,20 +6542,14 @@
return parameter != null && curve && curve.getPartLength(0, parameter);
},
- getParameter: function(_uncached) {
- if ((this._parameter == null || _uncached) && this._point) {
- var curve = this.getCurve(_uncached);
- this._parameter = curve && curve.getParameterOf(this._point);
- }
- return this._parameter;
- },
-
- getPoint: function(_uncached) {
- if ((!this._point || _uncached) && this._parameter != null) {
- var curve = this.getCurve(_uncached);
- this._point = curve && curve.getPointAt(this._parameter, true);
- }
- return this._point;
+ getIntersection: function() {
+ var intersection = this._intersection;
+ if (!intersection && this._curve2) {
+ this._intersection = intersection = new CurveLocation(this._curve2,
+ this._parameter2, this._point2 || this._point, this);
+ intersection._intersection = this;
+ }
+ return intersection;
},
getDistance: function() {
@@ -6416,24 +6557,24 @@
},
divide: function() {
- var curve = this.getCurve(true);
- return curve && curve.divide(this.getParameter(true), true);
+ var curve = this.getCurve();
+ return curve && curve.divide(this.getParameter(), true);
},
split: function() {
- var curve = this.getCurve(true);
- return curve && curve.split(this.getParameter(true), true);
+ var curve = this.getCurve();
+ return curve && curve.split(this.getParameter(), true);
},
equals: function(loc) {
var abs = Math.abs,
tolerance = 0.000001;
return this === loc
- || loc
- && this._curve === loc._curve
+ || loc instanceof CurveLocation
+ && this.getCurve() === loc.getCurve()
+ && abs(this.getParameter() - loc.getParameter()) < tolerance
&& this._curve2 === loc._curve2
- && abs(this._parameter - loc._parameter) <= tolerance
- && abs(this._parameter2 - loc._parameter2) <= tolerance
+ && abs(this._parameter2 - loc._parameter2) < tolerance
|| false;
},
@@ -6453,13 +6594,15 @@
parts.push('distance: ' + f.number(this._distance));
return '{ ' + parts.join(', ') + ' }';
}
-}, Base.each(['getTangent', 'getNormal', 'getCurvature'], function(name) {
- var get = name + 'At';
- this[name] = function() {
- var parameter = this.getParameter(),
- curve = this.getCurve();
- return parameter != null && curve && curve[get](parameter, true);
- };
+}, Base.each(Curve.evaluateMethods, function(name) {
+ if (name !== 'getPoint') {
+ var get = name + 'At';
+ this[name] = function() {
+ var parameter = this.getParameter(),
+ curve = this.getCurve();
+ return parameter != null && curve && curve[get](parameter, true);
+ };
+ }
}, {}));
var PathItem = Item.extend({
@@ -6567,8 +6710,6 @@
case 'm':
case 'l':
var move = lower === 'm';
- if (move && previous && previous !== 'z')
- this.closePath(true);
for (var j = 0; j < length; j += 2)
this[j === 0 && move ? 'moveTo' : 'lineTo'](
current = getPoint(j));
@@ -6657,6 +6798,7 @@
initialize: function Path(arg) {
this._closed = false;
this._segments = [];
+ this._version = 0;
var segments = Array.isArray(arg)
? typeof arg[0] === 'object'
? arg
@@ -6699,8 +6841,10 @@
if (parent)
parent._currentPath = undefined;
this._length = this._clockwise = undefined;
- if (this._curves && !(flags & 16)) {
- for (var i = 0, l = this._curves.length; i < l; i++)
+ if (flags & 16) {
+ this._version++;
+ } else if (this._curves) {
+ for (var i = 0, l = this._curves.length; i < l; i++)
this._curves[i]._changed();
}
this._monoCurves = undefined;
@@ -6833,14 +6977,24 @@
return this._segments.length === 0;
},
- isPolygon: function() {
- for (var i = 0, l = this._segments.length; i < l; i++) {
- if (!this._segments[i].isLinear())
+ isLinear: function() {
+ var segments = this._segments;
+ for (var i = 0, l = segments.length; i < l; i++) {
+ if (!segments[i].isLinear())
return false;
}
return true;
},
+ hasHandles: function() {
+ var segments = this._segments;
+ for (var i = 0, l = segments.length; i < l; i++) {
+ if (segments[i].hasHandles())
+ return true;
+ }
+ return false;
+ },
+
_transformContent: function(matrix) {
var coords = new Array(6);
for (var i = 0, l = this._segments.length; i < l; i++)
@@ -7039,7 +7193,7 @@
end = iterator.length + (this._closed ? -step : step) / 2;
var segments = [];
while (pos <= end) {
- segments.push(new Segment(iterator.evaluate(pos, 0)));
+ segments.push(new Segment(iterator.getPointAt(pos)));
pos += step;
}
this.setSegments(segments);
@@ -7175,8 +7329,8 @@
radius,
topCenter;
- function isColinear(i, j) {
- return segments[i].isColinear(segments[j]);
+ function isCollinear(i, j) {
+ return segments[i].isCollinear(segments[j]);
}
function isOrthogonal(i) {
@@ -7184,20 +7338,20 @@
}
function isArc(i) {
- return segments[i].isArc();
+ return segments[i].isOrthogonalArc();
}
function getDistance(i, j) {
return segments[i]._point.getDistance(segments[j]._point);
}
- if (this.isPolygon() && segments.length === 4
- && isColinear(0, 2) && isColinear(1, 3) && isOrthogonal(1)) {
+ if (!this.hasHandles() && segments.length === 4
+ && isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {
type = Shape.Rectangle;
size = new Size(getDistance(0, 3), getDistance(0, 1));
topCenter = segments[1]._point.add(segments[2]._point).divide(2);
} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
- && isArc(6) && isColinear(1, 5) && isColinear(3, 7)) {
+ && isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {
type = Shape.Rectangle;
size = new Size(getDistance(1, 6), getDistance(0, 3));
radius = size.subtract(new Size(getDistance(0, 7),
@@ -7217,16 +7371,13 @@
if (type) {
var center = this.getPosition(true),
- shape = new type({
+ shape = this._clone(new type({
center: center,
size: size,
radius: radius,
insert: false
- });
+ }), insert, false);
shape.rotate(topCenter.subtract(center).getAngle() + 90);
- shape.setStyle(this._style);
- if (insert || insert === undefined)
- shape.insertAbove(this);
return shape;
}
return null;
@@ -7354,7 +7505,7 @@
: null;
}
-}, Base.each(['getPoint', 'getTangent', 'getNormal', 'getCurvature'],
+}, Base.each(Curve.evaluateMethods,
function(name) {
this[name + 'At'] = function(offset, isParameter) {
var loc = this.getLocationAt(offset, isParameter);
@@ -7400,8 +7551,9 @@
var curves = this.getCurves(),
length = 0;
if (isParameter) {
- var index = ~~offset;
- return curves[index].getLocationAt(offset - index, true);
+ var index = ~~offset,
+ curve = curves[index];
+ return curve ? curve.getLocationAt(offset - index, true) : null;
}
for (var i = 0, l = curves.length; i < l; i++) {
var start = length,
@@ -7989,7 +8141,7 @@
var handleIn = segment._handleIn,
handleOut = segment._handleOut;
if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
- && handleIn.isColinear(handleOut)) {
+ && handleIn.isCollinear(handleOut)) {
addRound(segment);
} else {
Path._addBevelJoin(segment, join, radius, miterLimit, add);
@@ -8068,7 +8220,7 @@
_addSquareCap: function(segment, cap, radius, addPoint, area) {
var point = segment._point,
loc = segment.getLocation(),
- normal = loc.getNormal().normalize(radius);
+ normal = loc.getNormal().multiply(radius);
if (area) {
addPoint(point.subtract(normal));
addPoint(point.add(normal));
@@ -8522,17 +8674,17 @@
} while (segment && !segment._intersection && segment !== startSeg);
for (var j = 0; j < 3; j++) {
var length = totalLength * (j + 1) / 4;
- for (k = 0, m = chain.length; k < m; k++) {
+ for (var k = 0, m = chain.length; k < m; k++) {
var node = chain[k],
curveLength = node.length;
if (length <= curveLength) {
- if (length <= tolerance
- || curveLength - length <= tolerance)
+ if (length < tolerance
+ || curveLength - length < tolerance)
length = curveLength / 2;
var curve = node.segment.getCurve(),
pt = curve.getPointAt(length),
hor = curve.isLinear() && Math.abs(curve
- .getTangentAt(0.5, true).y) <= tolerance,
+ .getTangentAt(0.5, true).y) < tolerance,
path = curve._path;
if (path._parent instanceof CompoundPath)
path = path._parent;
@@ -8625,7 +8777,7 @@
var values = curves[i].values;
if (Curve.solveCubic(values, 0, px, roots, 0, 1) > 0) {
for (var j = roots.length - 1; j >= 0; j--) {
- var y = Curve.evaluate(values, roots[j], 0).y;
+ var y = Curve.getPoint(values, roots[j]).y;
if (y < yBefore && y > yTop) {
yTop = y;
} else if (y > yAfter && y < yBottom) {
@@ -8643,43 +8795,47 @@
} else {
var xBefore = px - tolerance,
xAfter = px + tolerance;
+ var startCounted = false,
+ prevCurve,
+ prevT;
for (var i = 0, l = curves.length; i < l; i++) {
var curve = curves[i],
values = curve.values,
- winding = curve.winding,
- prevT,
- prevX;
+ winding = curve.winding;
if (winding && (winding === 1
&& py >= values[1] && py <= values[7]
|| py >= values[7] && py <= values[1])
&& Curve.solveCubic(values, 1, py, roots, 0, 1) === 1) {
- var t = roots[0],
- x = Curve.evaluate(values, t, 0).x,
- slope = Curve.evaluate(values, t, 1).y;
- if (!(t > tMax
- && (i === l - 1 || curve.next !== curves[i + 1])
- && abs(Curve.evaluate(curve.next.values, 0, 0).x -x)
- <= tolerance
- || i > 0 && curve.previous === curves[i - 1]
- && abs(prevX - x) < tolerance
- && prevT > tMax && t < tMin)) {
+ var t = roots[0];
+ if (!(
+ t > tMax && startCounted && curve.next !== curves[i + 1]
+ || t < tMin && prevT > tMax
+ && curve.previous === prevCurve)) {
+ var x = Curve.getPoint(values, t).x,
+ slope = Curve.getTangent(values, t).y,
+ counted = false;
if (Numerical.isZero(slope) && !Curve.isLinear(values)
- || t < tMin && slope * Curve.evaluate(
- curve.previous.values, 1, 1).y < 0
- || t > tMax && slope * Curve.evaluate(
- curve.next.values, 0, 1).y < 0) {
+ || t < tMin && slope * Curve.getTangent(
+ curve.previous.values, 1).y < 0
+ || t > tMax && slope * Curve.getTangent(
+ curve.next.values, 0).y < 0) {
if (testContains && x >= xBefore && x <= xAfter) {
++windLeft;
++windRight;
+ counted = true;
}
} else if (x <= xBefore) {
windLeft += winding;
+ counted = true;
} else if (x >= xAfter) {
windRight += winding;
+ counted = true;
}
+ if (curve.previous !== curves[i - 1])
+ startCounted = t < tMin && counted;
}
+ prevCurve = curve;
prevT = t;
- prevX = x;
}
}
}
@@ -8759,7 +8915,7 @@
path.lastSegment._handleOut.set(0, 0);
}
if (path._segments.length >
- (path._closed ? path.isPolygon() ? 2 : 0 : 1))
+ (path._closed ? path.isLinear() ? 2 : 0 : 1))
paths.push(path);
}
return paths;
@@ -8889,7 +9045,7 @@
|| y >= values[7] && y <= values[1])
&& Curve.solveCubic(values, 1, y, roots, 0, 1) > 0) {
for (var j = roots.length - 1; j >= 0; j--)
- xIntercepts.push(Curve.evaluate(values, roots[j], 0).x);
+ xIntercepts.push(Curve.getPoint(values, roots[j]).x);
}
if (xIntercepts.length > 1)
break;
@@ -9017,11 +9173,6 @@
};
},
- evaluate: function(offset, type) {
- var param = this.getParameterAt(offset);
- return Curve.evaluate(this.curves[param.index], param.value, type);
- },
-
drawPart: function(ctx, from, to) {
from = this.getParameterAt(from);
to = this.getParameterAt(to);
@@ -9034,10 +9185,11 @@
ctx.bezierCurveTo.apply(ctx, curve.slice(2));
}
}
-}, Base.each(['getPoint', 'getTangent', 'getNormal', 'getCurvature'],
- function(name, index) {
- this[name + 'At'] = function(offset) {
- return this.evaluate(offset, index);
+}, Base.each(Curve.evaluateMethods,
+ function(name) {
+ this[name + 'At'] = function(offset, weighted) {
+ var param = this.getParameterAt(offset);
+ return Curve[name](this.curves[param.index], param.value, weighted);
};
}, {})
);
@@ -9093,18 +9245,19 @@
}
var uPrime = this.chordLengthParameterize(first, last),
maxError = Math.max(this.error, this.error * this.error),
- split;
+ split,
+ parametersInOrder = true;
for (var i = 0; i <= 4; i++) {
var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
var max = this.findMaxError(first, last, curve, uPrime);
- if (max.error < this.error) {
+ if (max.error < this.error && parametersInOrder) {
this.addCurve(curve);
return;
}
split = max.index;
if (max.error >= maxError)
break;
- this.reparameterize(first, last, uPrime, curve);
+ parametersInOrder = this.reparameterize(first, last, uPrime, curve);
maxError = max.error;
}
var V1 = this.points[split - 1].subtract(this.points[split]),
@@ -9168,20 +9321,35 @@
}
}
- var segLength = pt2.getDistance(pt1);
- epsilon *= segLength;
- if (alpha1 < epsilon || alpha2 < epsilon) {
+ var segLength = pt2.getDistance(pt1),
+ eps = epsilon * segLength,
+ handle1,
+ handle2;
+ if (alpha1 < eps || alpha2 < eps) {
alpha1 = alpha2 = segLength / 3;
- }
-
- return [pt1, pt1.add(tan1.normalize(alpha1)),
- pt2.add(tan2.normalize(alpha2)), pt2];
+ } else {
+ var line = pt2.subtract(pt1);
+ handle1 = tan1.normalize(alpha1);
+ handle2 = tan2.normalize(alpha2);
+ if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
+ alpha1 = alpha2 = segLength / 3;
+ handle1 = handle2 = null;
+ }
+ }
+
+ return [pt1, pt1.add(handle1 || tan1.normalize(alpha1)),
+ pt2.add(handle2 || tan2.normalize(alpha2)), pt2];
},
reparameterize: function(first, last, u, curve) {
for (var i = first; i <= last; i++) {
u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
}
+ for (var i = 1, l = u.length; i < l; i++) {
+ if (u[i] <= u[i - 1])
+ return false;
+ }
+ return true;
},
findRoot: function(curve, point, u) {
@@ -9266,9 +9434,9 @@
return this._content === item._content;
},
- _clone: function _clone(copy, insert) {
+ _clone: function _clone(copy, insert, includeMatrix) {
copy.setContent(this._content);
- return _clone.base.call(this, copy, insert);
+ return _clone.base.call(this, copy, insert, includeMatrix);
},
getContent: function() {
@@ -9547,11 +9715,8 @@
this._properties = types[type];
this._type = type;
}
- value = parser.call(this, value);
- if (value != null) {
- this._components[index] = value;
- this._changed();
- }
+ this._components[index] = parser.call(this, value);
+ this._changed();
};
}, this);
}, {
@@ -9659,8 +9824,7 @@
read = 1;
}
this._type = type || 'rgb';
- if (type === 'gradient')
- this._id = Color._id = (Color._id || 0) + 1;
+ this._id = UID.get(Color);
if (!components) {
this._components = components = [];
var parsers = componentParsers[this._type];
@@ -9897,7 +10061,7 @@
_class: 'Gradient',
initialize: function Gradient(stops, radial) {
- this._id = Gradient._id = (Gradient._id || 0) + 1;
+ this._id = UID.get();
if (stops && this._set(stops))
stops = radial = null;
if (!this._stops)
@@ -9938,7 +10102,7 @@
var stops = [];
for (var i = 0, l = this._stops.length; i < l; i++)
stops[i] = this._stops[i].clone();
- return new Gradient(stops);
+ return new Gradient(stops, this._radial);
},
getStops: function() {
@@ -10900,12 +11064,23 @@
},
getPixelSize: function(size) {
- var ctx = this._context,
- prevFont = ctx.font;
- ctx.font = size + ' serif';
- size = parseFloat(ctx.font);
- ctx.font = prevFont;
- return size;
+ var browser = paper.browser,
+ pixels;
+ if (browser && browser.firefox) {
+ var parent = this._element.parentNode,
+ temp = document.createElement('div');
+ temp.style.fontSize = size;
+ parent.appendChild(temp);
+ pixels = parseFloat(DomElement.getStyles(temp).fontSize);
+ parent.removeChild(temp);
+ } else {
+ var ctx = this._context,
+ prevFont = ctx.font;
+ ctx.font = size + ' serif';
+ pixels = parseFloat(ctx.font);
+ ctx.font = prevFont;
+ }
+ return pixels;
},
getTextWidth: function(font, lines) {
@@ -10919,9 +11094,9 @@
return width;
},
- update: function() {
+ update: function(force) {
var project = this._project;
- if (!project || !project._needsUpdate)
+ if (!project || !force && !project._needsUpdate)
return false;
var ctx = this._context,
size = this._viewSize;
@@ -11125,6 +11300,7 @@
charCodeMap = {},
keyMap = {},
+ commandFixMap,
downCode;
function handleKey(down, keyCode, charCode, event) {
@@ -11137,13 +11313,28 @@
tool = scope && scope.tool,
name;
keyMap[key] = down;
- if (specialKey && (name = Base.camelize(specialKey)) in modifiers)
- modifiers[name] = down;
if (down) {
charCodeMap[keyCode] = charCode;
} else {
delete charCodeMap[keyCode];
}
+ if (specialKey && (name = Base.camelize(specialKey)) in modifiers) {
+ modifiers[name] = down;
+ var browser = paper.browser;
+ if (name === 'command' && browser && browser.mac) {
+ if (down) {
+ commandFixMap = {};
+ } else {
+ for (var code in commandFixMap) {
+ if (code in charCodeMap)
+ handleKey(false, code, commandFixMap[code], event);
+ }
+ commandFixMap = null;
+ }
+ }
+ } else if (down && commandFixMap) {
+ commandFixMap[keyCode] = charCode;
+ }
if (tool && tool.responds(type)) {
paper = scope;
tool.emit(type, new KeyEvent(down, key, character, event));
@@ -11336,9 +11527,9 @@
setMinDistance: function(minDistance) {
this._minDistance = minDistance;
- if (this._minDistance != null && this._maxDistance != null
- && this._minDistance > this._maxDistance) {
- this._maxDistance = this._minDistance;
+ if (minDistance != null && this._maxDistance != null
+ && minDistance > this._maxDistance) {
+ this._maxDistance = minDistance;
}
},
@@ -11348,8 +11539,8 @@
setMaxDistance: function(maxDistance) {
this._maxDistance = maxDistance;
- if (this._minDistance != null && this._maxDistance != null
- && this._maxDistance < this._minDistance) {
+ if (this._minDistance != null && maxDistance != null
+ && maxDistance < this._minDistance) {
this._minDistance = maxDistance;
}
},
@@ -11373,10 +11564,9 @@
distance = vector.getLength();
if (distance < minDist)
return false;
- var maxDist = maxDistance != null ? maxDistance : 0;
- if (maxDist != 0) {
- if (distance > maxDist) {
- point = this._point.add(vector.normalize(maxDist));
+ if (maxDistance != null && maxDistance != 0) {
+ if (distance > maxDistance) {
+ point = this._point.add(vector.normalize(maxDistance));
} else if (matchMaxDistance) {
return false;
}
@@ -11470,10 +11660,11 @@
});
var Http = {
- request: function(method, url, callback) {
+ request: function(method, url, callback, async) {
+ async = (async === undefined) ? true : async;
var xhr = new (window.ActiveXObject || XMLHttpRequest)(
'Microsoft.XMLHTTP');
- xhr.open(method.toUpperCase(), url, true);
+ xhr.open(method.toUpperCase(), url, async);
if ('overrideMimeType' in xhr)
xhr.overrideMimeType('text/plain');
xhr.onreadystatechange = function() {
@@ -11904,19 +12095,22 @@
return node;
}
- function exportRaster(item) {
+ function exportRaster(item, options) {
var attrs = getTransform(item._matrix, true),
- size = item.getSize();
+ size = item.getSize(),
+ image = item.getImage();
attrs.x -= size.width / 2;
attrs.y -= size.height / 2;
attrs.width = size.width;
attrs.height = size.height;
- attrs.href = item.toDataURL();
+ attrs.href = options.embedImages === false && image && image.src
+ || item.toDataURL();
return createElement('image', attrs);
}
function exportPath(item, options) {
- if (options.matchShapes) {
+ var matchShapes = options.matchShapes;
+ if (matchShapes) {
var shape = item.toShape(false);
if (shape)
return exportShape(shape, options);
@@ -11926,11 +12120,11 @@
attrs = getTransform(item._matrix);
if (segments.length === 0)
return null;
- if (item.isPolygon()) {
+ if (matchShapes && !item.hasHandles()) {
if (segments.length >= 3) {
type = item._closed ? 'polygon' : 'polyline';
var parts = [];
- for(i = 0, l = segments.length; i < l; i++)
+ for(var i = 0, l = segments.length; i < l; i++)
parts.push(formatter.point(segments[i]._point));
attrs.points = parts.join(' ');
} else {
@@ -12270,10 +12464,17 @@
item = applyAttributes(item, node, isRoot);
project._currentStyle = item._style.clone();
}
+ if (isRoot) {
+ var defs = node.querySelectorAll('defs');
+ for (var i = 0, l = defs.length; i < l; i++) {
+ importSVG(defs[i], options, false);
+ }
+ }
for (var i = 0, l = nodes.length; i < l; i++) {
var childNode = nodes[i],
child;
if (childNode.nodeType === 1
+ && childNode.nodeName.toLowerCase() !== 'defs'
&& (child = importSVG(childNode, options, false))
&& !(child instanceof Symbol))
children.push(child);
@@ -12473,7 +12674,7 @@
color.setAlpha(parseFloat(value));
}
- var attributes = Base.each(SVGStyles, function(entry) {
+ var attributes = Base.set(Base.each(SVGStyles, function(entry) {
this[entry.attribute] = function(item, value) {
item[entry.set](convertValue(value, entry.type, entry.fromSVG));
if (entry.type === 'color' && item instanceof Shape) {
@@ -12483,7 +12684,7 @@
item.getPosition(true).negate()));
}
};
- }, {
+ }, {}), {
id: function(item, value) {
definitions[value] = item;
if (item.setName)
@@ -12657,7 +12858,7 @@
}
if (isRoot) {
definitions = {};
- if (applyMatrix && item)
+ if (item && Base.pick(options.applyMatrix, applyMatrix))
item.matrix.apply(true, true);
}
return item;
@@ -12827,13 +13028,17 @@
|| parentType === 'MemberExpression' && parent.computed
)) {
if (node.type === 'UpdateExpression') {
- var arg = getCode(node.argument);
- var str = arg + ' = __$__(' + arg
- + ', "' + node.operator[0] + '", 1)';
+ var arg = getCode(node.argument),
+ exp = '__$__(' + arg + ', "' + node.operator[0]
+ + '", 1)',
+ str = arg + ' = ' + exp;
if (!node.prefix
&& (parentType === 'AssignmentExpression'
- || parentType === 'VariableDeclarator'))
+ || parentType === 'VariableDeclarator')) {
+ if (getCode(parent.left || parent.id) === arg)
+ str = exp;
str = arg + '; ' + str;
+ }
replaceCode(node, str);
} else {
if (/^.=$/.test(node.operator)
@@ -12958,7 +13163,8 @@
&& PaperScope.getAttribute(script, 'ignore') !== 'true') {
var canvasId = PaperScope.getAttribute(script, 'canvas'),
canvas = document.getElementById(canvasId),
- src = script.src,
+ src = script.src || script.getAttribute('data-src'),
+ async = PaperScope.hasAttribute(script, 'async'),
scopeAttribute = 'data-paper-scope';
if (!canvas)
throw new Error('Unable to find canvas with id "'
@@ -12969,7 +13175,7 @@
if (src) {
Http.request('get', src, function(code) {
execute(code, scope, src);
- });
+ }, async);
} else {
execute(script.innerHTML, scope, script.baseURI);
}