From facb9fbf3e0701f4e5c21157f71fec8ee0b9833b Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Tue, 3 Sep 2013 16:42:09 +1000 Subject: [PATCH] Readded --- ajax/libs/paper.js/0.22/paper.js | 7842 ++++++++++++++++++++++++++ ajax/libs/paper.js/0.22/paper.min.js | 5 + 2 files changed, 7847 insertions(+) create mode 100644 ajax/libs/paper.js/0.22/paper.js create mode 100644 ajax/libs/paper.js/0.22/paper.min.js diff --git a/ajax/libs/paper.js/0.22/paper.js b/ajax/libs/paper.js/0.22/paper.js new file mode 100644 index 000000000..440faf017 --- /dev/null +++ b/ajax/libs/paper.js/0.22/paper.js @@ -0,0 +1,7842 @@ +/*! + * Paper.js v0.22 + * + * This file is part of Paper.js, a JavaScript Vector Graphics Library, + * based on Scriptographer.org and designed to be largely API compatible. + * http://paperjs.org/ + * http://scriptographer.org/ + * + * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey + * http://lehni.org/ & http://jonathanpuckey.com/ + * + * Distributed under the MIT license. See LICENSE file for details. + * + * All rights reserved. + * + * Date: Thu Nov 10 19:19:25 2011 +0100 + * + *** + * + * Bootstrap.js JavaScript Framework. + * http://bootstrapjs.org/ + * + * Copyright (c) 2006 - 2011 Juerg Lehni + * http://lehni.org/ + * + * Distributed under the MIT license. + * + *** + * + * Parse-js + * + * A JavaScript tokenizer / parser / generator, originally written in Lisp. + * Copyright (c) Marijn Haverbeke + * http://marijn.haverbeke.nl/parse-js/ + * + * Ported by to JavaScript by Mihai Bazon + * Copyright (c) 2010, Mihai Bazon + * http://mihai.bazon.net/blog/ + * + * Modifications and adaptions to browser (c) 2011, Juerg Lehni + * http://lehni.org/ + * + * Distributed under the BSD license. + */ + +var paper = new function() { + +var Base = new function() { + var fix = !this.__proto__, + hidden = /^(statics|generics|preserve|enumerable|prototype|__proto__|toString|valueOf)$/, + proto = Object.prototype, + has = fix + ? function(name) { + return name !== '__proto__' && this.hasOwnProperty(name); + } + : proto.hasOwnProperty, + toString = proto.toString, + proto = Array.prototype, + isArray = Array.isArray = Array.isArray || function(obj) { + return toString.call(obj) === '[object Array]'; + }, + slice = proto.slice, + forEach = proto.forEach = proto.forEach || function(iter, bind) { + for (var i = 0, l = this.length; i < l; i++) + iter.call(bind, this[i], i, this); + }, + forIn = function(iter, bind) { + for (var i in this) + if (this.hasOwnProperty(i)) + iter.call(bind, this[i], i, this); + }, + _define = Object.defineProperty, + _describe = Object.getOwnPropertyDescriptor; + + function define(obj, name, desc) { + if (_define) { + try { + delete obj[name]; + return _define(obj, name, desc); + } catch (e) {} + } + if ((desc.get || desc.set) && obj.__defineGetter__) { + desc.get && obj.__defineGetter__(name, desc.get); + desc.set && obj.__defineSetter__(name, desc.set); + } else { + obj[name] = desc.value; + } + return obj; + } + + function describe(obj, name) { + if (_describe) { + try { + return _describe(obj, name); + } catch (e) {} + } + var get = obj.__lookupGetter__ && obj.__lookupGetter__(name); + return get + ? { get: get, set: obj.__lookupSetter__(name), enumerable: true, + configurable: true } + : has.call(obj, name) + ? { value: obj[name], enumerable: true, configurable: true, + writable: true } + : null; + } + + function inject(dest, src, enumerable, base, preserve, generics) { + var beans, bean; + + function field(name, val, dontCheck, generics) { + var val = val || (val = describe(src, name)) + && (val.get ? val : val.value), + func = typeof val === 'function', + res = val, + prev = preserve || func + ? (val && val.get ? name in dest : dest[name]) : null; + if (generics && func && (!preserve || !generics[name])) { + generics[name] = function(bind) { + return bind && dest[name].apply(bind, + slice.call(arguments, 1)); + } + } + if ((dontCheck || val !== undefined && has.call(src, name)) + && (!preserve || !prev)) { + if (func) { + if (prev && /\bthis\.base\b/.test(val)) { + var fromBase = base && base[name] == prev; + res = function() { + var tmp = describe(this, 'base'); + define(this, 'base', { value: fromBase + ? base[name] : prev, configurable: true }); + try { + return val.apply(this, arguments); + } finally { + tmp ? define(this, 'base', tmp) + : delete this.base; + } + }; + res.toString = function() { + return val.toString(); + } + res.valueOf = function() { + return val.valueOf(); + } + } + if (beans && val.length == 0 + && (bean = name.match(/^(get|is)(([A-Z])(.*))$/))) + beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]); + } + if (!res || func || !res.get && !res.set) + res = { value: res, writable: true }; + if ((describe(dest, name) + || { configurable: true }).configurable) { + res.configurable = true; + res.enumerable = enumerable; + } + define(dest, name, res); + } + } + if (src) { + beans = []; + for (var name in src) + if (has.call(src, name) && !hidden.test(name)) + field(name, null, true, generics); + field('toString'); + field('valueOf'); + for (var i = 0, l = beans && beans.length; i < l; i++) + try { + var bean = beans[i], part = bean[1]; + field(bean[0], { + get: dest['get' + part] || dest['is' + part], + set: dest['set' + part] + }, true); + } catch (e) {} + } + return dest; + } + + function extend(obj) { + var ctor = function(dont) { + if (fix) define(this, '__proto__', { value: obj }); + if (this.initialize && dont !== ctor.dont) + return this.initialize.apply(this, arguments); + } + ctor.prototype = obj; + ctor.toString = function() { + return (this.prototype.initialize || function() {}).toString(); + } + return ctor; + } + + function iterator(iter) { + return !iter + ? function(val) { return val } + : typeof iter !== 'function' + ? function(val) { return val == iter } + : iter; + } + + function each(obj, iter, bind, asArray) { + try { + if (obj) + (asArray || asArray === undefined && isArray(obj) + ? forEach : forIn).call(obj, iterator(iter), + bind = bind || obj); + } catch (e) { + if (e !== Base.stop) throw e; + } + return bind; + } + + function clone(obj) { + return each(obj, function(val, i) { + this[i] = val; + }, new obj.constructor()); + } + + return inject(function() {}, { + inject: function(src) { + if (src) { + var proto = this.prototype, + base = proto.__proto__ && proto.__proto__.constructor, + statics = src.statics == true ? src : src.statics; + if (statics != src) + inject(proto, src, src.enumerable, base && base.prototype, + src.preserve, src.generics && this); + inject(this, statics, true, base, src.preserve); + } + for (var i = 1, l = arguments.length; i < l; i++) + this.inject(arguments[i]); + return this; + }, + + extend: function(src) { + var proto = new this(this.dont), + ctor = extend(proto); + define(proto, 'constructor', + { value: ctor, writable: true, configurable: true }); + ctor.dont = {}; + inject(ctor, this, true); + return arguments.length ? this.inject.apply(ctor, arguments) : ctor; + } + }, true).inject({ + has: has, + each: each, + + inject: function() { + for (var i = 0, l = arguments.length; i < l; i++) + inject(this, arguments[i]); + return this; + }, + + extend: function() { + var res = new (extend(this)); + return res.inject.apply(res, arguments); + }, + + each: function(iter, bind) { + return each(this, iter, bind); + }, + + clone: function() { + return clone(this); + }, + + statics: { + each: each, + clone: clone, + define: define, + describe: describe, + iterator: iterator, + + has: function(obj, name) { + return has.call(obj, name); + }, + + type: function(obj) { + return (obj || obj === 0) && (obj._type || typeof obj) || null; + }, + + check: function(obj) { + return !!(obj || obj === 0); + }, + + pick: function() { + for (var i = 0, l = arguments.length; i < l; i++) + if (arguments[i] !== undefined) + return arguments[i]; + return null; + }, + + stop: {} + } + }); +} + +this.Base = Base.inject({ + generics: true, + + clone: function() { + return new this.constructor(this); + }, + + toString: function() { + return '{ ' + Base.each(this, function(value, key) { + if (key.charAt(0) != '_') { + var type = typeof value; + this.push(key + ': ' + (type === 'number' + ? Base.formatNumber(value) + : type === 'string' ? "'" + value + "'" : value)); + } + }, []).join(', ') + ' }'; + }, + + statics: { + read: function(list, start, length) { + var start = start || 0, + length = length || list.length - start; + var obj = list[start]; + if (obj instanceof this + || this.prototype._readNull && obj == null && length <= 1) + return obj; + obj = new this(this.dont); + return obj.initialize.apply(obj, start > 0 || length < list.length + ? Array.prototype.slice.call(list, start, start + length) + : list) || obj; + }, + + readAll: function(list, start) { + var res = [], entry; + for (var i = start || 0, l = list.length; i < l; i++) { + res.push(Array.isArray(entry = list[i]) + ? this.read(entry, 0) + : this.read(list, i, 1)); + } + return res; + }, + + splice: function(list, items, index, remove) { + var amount = items && items.length, + append = index === undefined; + index = append ? list.length : index; + for (var i = 0; i < amount; i++) + items[i]._index = index + i; + if (append) { + list.push.apply(list, items); + return []; + } else { + var args = [index, remove]; + if (items) + args.push.apply(args, items); + var removed = list.splice.apply(list, args); + for (var i = 0, l = removed.length; i < l; i++) + delete removed[i]._index; + for (var i = index + amount, l = list.length; i < l; i++) + list[i]._index = i; + return removed; + } + }, + + merge: function() { + return Base.each(arguments, function(hash) { + Base.each(hash, function(value, key) { + this[key] = value; + }, this); + }, new Base(), true); + }, + + capitalize: function(str) { + return str.replace(/\b[a-z]/g, function(match) { + return match.toUpperCase(); + }); + }, + + camelize: function(str) { + return str.replace(/-(\w)/g, function(all, chr) { + return chr.toUpperCase(); + }); + }, + + hyphenate: function(str) { + return str.replace(/[a-z][A-Z0-9]|[0-9][a-zA-Z]|[A-Z]{2}[a-z]/g, + function(match) { + return match.charAt(0) + '-' + match.substring(1); + } + ).toLowerCase(); + }, + + formatNumber: function(num) { + return (Math.round(num * 100000) / 100000).toString(); + } + } +}); + +var PaperScope = this.PaperScope = Base.extend({ + + initialize: function(script) { + paper = this; + this.view = null; + this.views = []; + this.project = null; + this.projects = []; + this.tool = null; + this.tools = []; + this._id = script && (script.getAttribute('id') || script.src) + || ('paperscope-' + (PaperScope._id++)); + if (script) + script.setAttribute('id', this._id); + PaperScope._scopes[this._id] = this; + }, + + version: 0.22, + + evaluate: function(code) { + var res = PaperScript.evaluate(code, this); + View.updateFocus(); + return res; + }, + + install: function(scope) { + var that = this; + Base.each(['project', 'view', 'tool'], function(key) { + Base.define(scope, key, { + configurable: true, + writable: true, + get: function() { + return that[key]; + } + }); + }); + for (var key in this) { + if (!/^(version|_id|load)/.test(key) && !(key in scope)) + scope[key] = this[key]; + } + }, + + setup: function(canvas) { + paper = this; + this.project = new Project(); + if (canvas) + this.view = new View(canvas); + }, + + clear: function() { + for (var i = this.projects.length - 1; i >= 0; i--) + this.projects[i].remove(); + for (var i = this.views.length - 1; i >= 0; i--) + this.views[i].remove(); + for (var i = this.tools.length - 1; i >= 0; i--) + this.tools[i].remove(); + }, + + remove: function() { + this.clear(); + delete PaperScope._scopes[this._id]; + }, + + _needsRedraw: function() { + if (!this._redrawNotified) { + for (var i = this.views.length - 1; i >= 0; i--) + this.views[i]._redrawNeeded = true; + this._redrawNotified = true; + } + }, + + statics: { + _scopes: {}, + _id: 0, + + get: function(id) { + if (typeof id === 'object') + id = id.getAttribute('id'); + return this._scopes[id] || null; + }, + + each: function(iter) { + Base.each(this._scopes, iter); + } + } +}); + +var PaperScopeItem = Base.extend({ + + initialize: function(activate) { + this._scope = paper; + this._index = this._scope[this._list].push(this) - 1; + if (activate || !this._scope[this._reference]) + this.activate(); + }, + + activate: function() { + if (!this._scope) + return false; + this._scope[this._reference] = this; + return true; + }, + + remove: function() { + if (this._index == null) + return false; + Base.splice(this._scope[this._list], null, this._index, 1); + if (this._scope[this._reference] == this) + this._scope[this._reference] = null; + this._scope = null; + return true; + } +}); + +var Point = this.Point = Base.extend({ + initialize: function(arg0, arg1) { + if (arg1 !== undefined) { + this.x = arg0; + this.y = arg1; + } else if (arg0 !== undefined) { + if (arg0 == null) { + this.x = this.y = 0; + } else if (arg0.x !== undefined) { + this.x = arg0.x; + this.y = arg0.y; + } else if (arg0.width !== undefined) { + this.x = arg0.width; + this.y = arg0.height; + } else if (Array.isArray(arg0)) { + this.x = arg0[0]; + this.y = arg0.length > 1 ? arg0[1] : arg0[0]; + } else if (arg0.angle !== undefined) { + this.x = arg0.length; + this.y = 0; + this.setAngle(arg0.angle); + } else if (typeof arg0 === 'number') { + this.x = this.y = arg0; + } else { + this.x = this.y = 0; + } + } else { + this.x = this.y = 0; + } + }, + + set: function(x, y) { + this.x = x; + this.y = y; + return this; + }, + + clone: function() { + return Point.create(this.x, this.y); + }, + + toString: function() { + var format = Base.formatNumber; + return '{ x: ' + format(this.x) + ', y: ' + format(this.y) + ' }'; + }, + + add: function(point) { + point = Point.read(arguments); + return Point.create(this.x + point.x, this.y + point.y); + }, + + subtract: function(point) { + point = Point.read(arguments); + return Point.create(this.x - point.x, this.y - point.y); + }, + + multiply: function(point) { + point = Point.read(arguments); + return Point.create(this.x * point.x, this.y * point.y); + }, + + divide: function(point) { + point = Point.read(arguments); + return Point.create(this.x / point.x, this.y / point.y); + }, + + modulo: function(point) { + point = Point.read(arguments); + return Point.create(this.x % point.x, this.y % point.y); + }, + + negate: function() { + return Point.create(-this.x, -this.y); + }, + + transform: function(matrix) { + return matrix ? matrix._transformPoint(this) : this; + }, + + getDistance: function(point, squared) { + point = Point.read(arguments); + var x = point.x - this.x, + y = point.y - this.y, + d = x * x + y * y; + return squared ? d : Math.sqrt(d); + }, + + getLength: function() { + var l = this.x * this.x + this.y * this.y; + return arguments[0] ? l : Math.sqrt(l); + }, + + setLength: function(length) { + if (this.isZero()) { + var angle = this._angle || 0; + this.set( + Math.cos(angle) * length, + Math.sin(angle) * length + ); + } else { + var scale = length / this.getLength(); + if (scale == 0) + this.getAngle(); + this.set( + this.x * scale, + this.y * scale + ); + } + return this; + }, + + normalize: function(length) { + if (length === undefined) + length = 1; + var current = this.getLength(), + scale = current != 0 ? length / current : 0, + point = Point.create(this.x * scale, this.y * scale); + point._angle = this._angle; + return point; + }, + + getAngle: function() { + return this.getAngleInRadians(arguments[0]) * 180 / Math.PI; + }, + + setAngle: function(angle) { + angle = this._angle = angle * Math.PI / 180; + if (!this.isZero()) { + var length = this.getLength(); + this.set( + Math.cos(angle) * length, + Math.sin(angle) * length + ); + } + return this; + }, + + getAngleInRadians: function() { + if (arguments[0] === undefined) { + if (this._angle == null) + this._angle = Math.atan2(this.y, this.x); + return this._angle; + } else { + var point = Point.read(arguments), + div = this.getLength() * point.getLength(); + if (div == 0) { + return NaN; + } else { + return Math.acos(this.dot(point) / div); + } + } + }, + + getAngleInDegrees: function() { + return this.getAngle(arguments[0]); + }, + + getQuadrant: function() { + return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3; + }, + + getDirectedAngle: function(point) { + point = Point.read(arguments); + return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI; + }, + + rotate: function(angle, center) { + angle = angle * Math.PI / 180; + var point = center ? this.subtract(center) : this, + s = Math.sin(angle), + c = Math.cos(angle); + point = Point.create( + point.x * c - point.y * s, + point.y * c + point.x * s + ); + return center ? point.add(center) : point; + }, + + equals: function(point) { + point = Point.read(arguments); + return this.x == point.x && this.y == point.y; + }, + + isInside: function(rect) { + return rect.contains(this); + }, + + isClose: function(point, tolerance) { + return this.getDistance(point) < tolerance; + }, + + isColinear: function(point) { + return this.cross(point) < Numerical.TOLERANCE; + }, + + isOrthogonal: function(point) { + return this.dot(point) < Numerical.TOLERANCE; + }, + + isZero: function() { + return this.x == 0 && this.y == 0; + }, + + isNaN: function() { + return isNaN(this.x) || isNaN(this.y); + }, + + dot: function(point) { + point = Point.read(arguments); + return this.x * point.x + this.y * point.y; + }, + + cross: function(point) { + point = Point.read(arguments); + return this.x * point.y - this.y * point.x; + }, + + project: function(point) { + point = Point.read(arguments); + if (point.isZero()) { + return Point.create(0, 0); + } else { + var scale = this.dot(point) / point.dot(point); + return Point.create( + point.x * scale, + point.y * scale + ); + } + }, + + statics: { + create: function(x, y) { + var point = new Point(Point.dont); + point.x = x; + point.y = y; + return point; + }, + + min: function(point1, point2) { + point1 = Point.read(arguments, 0, 1); + point2 = Point.read(arguments, 1, 1); + return Point.create( + Math.min(point1.x, point2.x), + Math.min(point1.y, point2.y) + ); + }, + + max: function(point1, point2) { + point1 = Point.read(arguments, 0, 1); + point2 = Point.read(arguments, 1, 1); + return Point.create( + Math.max(point1.x, point2.x), + Math.max(point1.y, point2.y) + ); + }, + + random: function() { + return Point.create(Math.random(), Math.random()); + } + } +}, new function() { + + return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) { + var op = Math[name]; + this[name] = function() { + return Point.create(op(this.x), op(this.y)); + }; + }, {}); +}); + +var LinkedPoint = Point.extend({ + set: function(x, y, dontNotify) { + this._x = x; + this._y = y; + if (!dontNotify) + this._owner[this._setter](this); + return this; + }, + + getX: function() { + return this._x; + }, + + setX: function(x) { + this._x = x; + this._owner[this._setter](this); + }, + + getY: function() { + return this._y; + }, + + setY: function(y) { + this._y = y; + this._owner[this._setter](this); + }, + + statics: { + create: function(owner, setter, x, y, dontLink) { + if (dontLink) + return Point.create(x, y); + var point = new LinkedPoint(LinkedPoint.dont); + point._x = x; + point._y = y; + point._owner = owner; + point._setter = setter; + return point; + } + } +}); + +var Size = this.Size = Base.extend({ + initialize: function(arg0, arg1) { + if (arg1 !== undefined) { + this.width = arg0; + this.height = arg1; + } else if (arg0 !== undefined) { + if (arg0 == null) { + this.width = this.height = 0; + } else if (arg0.width !== undefined) { + this.width = arg0.width; + this.height = arg0.height; + } else if (arg0.x !== undefined) { + this.width = arg0.x; + this.height = arg0.y; + } else if (Array.isArray(arg0)) { + this.width = arg0[0]; + this.height = arg0.length > 1 ? arg0[1] : arg0[0]; + } else if (typeof arg0 === 'number') { + this.width = this.height = arg0; + } else { + this.width = this.height = 0; + } + } else { + this.width = this.height = 0; + } + }, + + toString: function() { + var format = Base.formatNumber; + return '{ width: ' + format(this.width) + + ', height: ' + format(this.height) + ' }'; + }, + + set: function(width, height) { + this.width = width; + this.height = height; + return this; + }, + + clone: function() { + return Size.create(this.width, this.height); + }, + + add: function(size) { + size = Size.read(arguments); + return Size.create(this.width + size.width, this.height + size.height); + }, + + subtract: function(size) { + size = Size.read(arguments); + return Size.create(this.width - size.width, this.height - size.height); + }, + + multiply: function(size) { + size = Size.read(arguments); + return Size.create(this.width * size.width, this.height * size.height); + }, + + divide: function(size) { + size = Size.read(arguments); + return Size.create(this.width / size.width, this.height / size.height); + }, + + modulo: function(size) { + size = Size.read(arguments); + return Size.create(this.width % size.width, this.height % size.height); + }, + + negate: function() { + return Size.create(-this.width, -this.height); + }, + + equals: function(size) { + size = Size.read(arguments); + return this.width == size.width && this.height == size.height; + }, + + isZero: function() { + return this.width == 0 && this.height == 0; + }, + + isNaN: function() { + return isNaN(this.width) || isNaN(this.height); + }, + + statics: { + create: function(width, height) { + return new Size(Size.dont).set(width, height); + }, + + min: function(size1, size2) { + return Size.create( + Math.min(size1.width, size2.width), + Math.min(size1.height, size2.height)); + }, + + max: function(size1, size2) { + return Size.create( + Math.max(size1.width, size2.width), + Math.max(size1.height, size2.height)); + }, + + random: function() { + return Size.create(Math.random(), Math.random()); + } + } +}, new function() { + + return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) { + var op = Math[name]; + this[name] = function() { + return Size.create(op(this.width), op(this.height)); + }; + }, {}); +}); + +var LinkedSize = Size.extend({ + set: function(width, height, dontNotify) { + this._width = width; + this._height = height; + if (!dontNotify) + this._owner[this._setter](this); + return this; + }, + + getWidth: function() { + return this._width; + }, + + setWidth: function(width) { + this._width = width; + this._owner[this._setter](this); + }, + + getHeight: function() { + return this._height; + }, + + setHeight: function(height) { + this._height = height; + this._owner[this._setter](this); + }, + + statics: { + create: function(owner, setter, width, height, dontLink) { + if (dontLink) + return Size.create(width, height); + var size = new LinkedSize(LinkedSize.dont); + size._width = width; + size._height = height; + size._owner = owner; + size._setter = setter; + return size; + } + } +}); + +var Rectangle = this.Rectangle = Base.extend({ + initialize: function(arg0, arg1, arg2, arg3) { + if (arguments.length == 4) { + this.x = arg0; + this.y = arg1; + this.width = arg2; + this.height = arg3; + } else if (arguments.length == 2) { + if (arg1 && arg1.x !== undefined) { + var point1 = Point.read(arguments, 0, 1); + var point2 = Point.read(arguments, 1, 1); + this.x = point1.x; + this.y = point1.y; + this.width = point2.x - point1.x; + this.height = point2.y - point1.y; + if (this.width < 0) { + this.x = point2.x; + this.width = -this.width; + } + if (this.height < 0) { + this.y = point2.y; + this.height = -this.height; + } + } else { + var point = Point.read(arguments, 0, 1); + var size = Size.read(arguments, 1, 1); + this.x = point.x; + this.y = point.y; + this.width = size.width; + this.height = size.height; + } + } else if (arg0) { + this.x = arg0.x || 0; + this.y = arg0.y || 0; + this.width = arg0.width || 0; + this.height = arg0.height || 0; + } else { + this.x = this.y = this.width = this.height = 0; + } + }, + + set: function(x, y, width, height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + return this; + }, + + getPoint: function() { + return LinkedPoint.create(this, 'setPoint', this.x, this.y, + arguments[0]); + }, + + setPoint: function(point) { + point = Point.read(arguments); + this.x = point.x; + this.y = point.y; + return this; + }, + + getSize: function() { + return LinkedSize.create(this, 'setSize', this.width, this.height, + arguments[0]); + }, + + setSize: function(size) { + size = Size.read(arguments); + this.width = size.width; + this.height = size.height; + return this; + }, + + getLeft: function() { + return this.x; + }, + + setLeft: function(left) { + this.width -= left - this.x; + this.x = left; + return this; + }, + + getTop: function() { + return this.y; + }, + + setTop: function(top) { + this.height -= top - this.y; + this.y = top; + return this; + }, + + getRight: function() { + return this.x + this.width; + }, + + setRight: function(right) { + this.width = right - this.x; + return this; + }, + + getBottom: function() { + return this.y + this.height; + }, + + setBottom: function(bottom) { + this.height = bottom - this.y; + return this; + }, + + getCenterX: function() { + return this.x + this.width * 0.5; + }, + + setCenterX: function(x) { + this.x = x - this.width * 0.5; + return this; + }, + + getCenterY: function() { + return this.y + this.height * 0.5; + }, + + setCenterY: function(y) { + this.y = y - this.height * 0.5; + return this; + }, + + getCenter: function() { + return LinkedPoint.create(this, 'setCenter', + this.getCenterX(), this.getCenterY(), arguments[0]); + }, + + setCenter: function(point) { + point = Point.read(arguments); + return this.setCenterX(point.x).setCenterY(point.y); + }, + + equals: function(rect) { + rect = Rectangle.read(arguments); + return this.x == rect.x && this.y == rect.y + && this.width == rect.width && this.height == rect.height; + }, + + isEmpty: function() { + return this.width == 0 || this.height == 0; + }, + + toString: function() { + var format = Base.formatNumber; + return '{ x: ' + format(this.x) + + ', y: ' + format(this.y) + + ', width: ' + format(this.width) + + ', height: ' + format(this.height) + + ' }'; + }, + + contains: function(arg) { + return arg && arg.width !== undefined + || (Array.isArray(arg) ? arg : arguments).length == 4 + ? this._containsRectangle(Rectangle.read(arguments)) + : this._containsPoint(Point.read(arguments)); + }, + + _containsPoint: function(point) { + var x = point.x, + y = point.y; + return x >= this.x && y >= this.y + && x <= this.x + this.width + && y <= this.y + this.height; + }, + + _containsRectangle: function(rect) { + var x = rect.x, + y = rect.y; + return x >= this.x && y >= this.y + && x + rect.width <= this.x + this.width + && y + rect.height <= this.y + this.height; + }, + + intersects: function(rect) { + rect = Rectangle.read(arguments); + return rect.x + rect.width > this.x + && rect.y + rect.height > this.y + && rect.x < this.x + this.width + && rect.y < this.y + this.height; + }, + + intersect: function(rect) { + rect = Rectangle.read(arguments); + var x1 = Math.max(this.x, rect.x), + y1 = Math.max(this.y, rect.y), + x2 = Math.min(this.x + this.width, rect.x + rect.width), + y2 = Math.min(this.y + this.height, rect.y + rect.height); + return Rectangle.create(x1, y1, x2 - x1, y2 - y1); + }, + + unite: function(rect) { + rect = Rectangle.read(arguments); + var x1 = Math.min(this.x, rect.x), + y1 = Math.min(this.y, rect.y), + x2 = Math.max(this.x + this.width, rect.x + rect.width), + y2 = Math.max(this.y + this.height, rect.y + rect.height); + return Rectangle.create(x1, y1, x2 - x1, y2 - y1); + }, + + include: function(point) { + point = Point.read(arguments); + var x1 = Math.min(this.x, point.x), + y1 = Math.min(this.y, point.y), + x2 = Math.max(this.x + this.width, point.x), + y2 = Math.max(this.y + this.height, point.y); + return Rectangle.create(x1, y1, x2 - x1, y2 - y1); + }, + + expand: function(hor, ver) { + if (ver === undefined) + ver = hor; + return Rectangle.create(this.x - hor / 2, this.y - ver / 2, + this.width + hor, this.height + ver); + }, + + scale: function(hor, ver) { + return this.expand(this.width * hor - this.width, + this.height * (ver === undefined ? hor : ver) - this.height); + }, + + statics: { + create: function(x, y, width, height) { + return new Rectangle(Rectangle.dont).set(x, y, width, height); + } + } +}, new function() { + return Base.each([ + ['Top', 'Left'], ['Top', 'Right'], + ['Bottom', 'Left'], ['Bottom', 'Right'], + ['Left', 'Center'], ['Top', 'Center'], + ['Right', 'Center'], ['Bottom', 'Center'] + ], + function(parts, index) { + var part = parts.join(''); + var xFirst = /^[RL]/.test(part); + if (index >= 4) + parts[1] += xFirst ? 'Y' : 'X'; + var x = parts[xFirst ? 0 : 1], + y = parts[xFirst ? 1 : 0], + getX = 'get' + x, + getY = 'get' + y, + setX = 'set' + x, + setY = 'set' + y, + get = 'get' + part, + set = 'set' + part; + this[get] = function() { + return LinkedPoint.create(this, set, + this[getX](), this[getY](), arguments[0]); + }; + this[set] = function(point) { + point = Point.read(arguments); + return this[setX](point.x)[setY](point.y); + }; + }, {}); +}); + +var LinkedRectangle = Rectangle.extend({ + set: function(x, y, width, height, dontNotify) { + this._x = x; + this._y = y; + this._width = width; + this._height = height; + if (!dontNotify) + this._owner[this._setter](this); + return this; + }, + + statics: { + create: function(owner, setter, x, y, width, height) { + var rect = new LinkedRectangle(LinkedRectangle.dont).set( + x, y, width, height, true); + rect._owner = owner; + rect._setter = setter; + return rect; + } + } +}, new function() { + var proto = Rectangle.prototype; + + return Base.each(['x', 'y', 'width', 'height'], function(key) { + var part = Base.capitalize(key); + var internal = '_' + key; + this['get' + part] = function() { + return this[internal]; + }; + + this['set' + part] = function(value) { + this[internal] = value; + if (!this._dontNotify) + this._owner[this._setter](this); + }; + }, Base.each(['Point', 'Size', 'Center', + 'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY', + 'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight', + 'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'], + function(key) { + var name = 'set' + key; + this[name] = function(value) { + this._dontNotify = true; + proto[name].apply(this, arguments); + delete this._dontNotify; + this._owner[this._setter](this); + return this; + }; + }, {}) + ); +}); + +var Matrix = this.Matrix = Base.extend({ + initialize: function(arg) { + var count = arguments.length, + ok = true; + if (count == 6) { + this.set.apply(this, arguments); + } else if (count == 1) { + if (arg instanceof Matrix) { + this.set(arg._a, arg._c, arg._b, arg._d, arg._tx, arg._ty); + } else if (Array.isArray(arg)) { + this.set.apply(this, arg); + } else { + ok = false; + } + } else if (count == 0) { + this._a = this._d = 1; + this._c = this._b = this._tx = this._ty = 0; + } else { + ok = false; + } + if (!ok) + throw new Error('Unsupported matrix parameters'); + }, + + clone: function() { + return Matrix.create(this._a, this._c, this._b, this._d, + this._tx, this._ty); + }, + + set: function(a, c, b, d, tx, ty) { + this._a = a; + this._c = c; + this._b = b; + this._d = d; + this._tx = tx; + this._ty = ty; + return this; + }, + + scale: function( hor, ver, center) { + if (arguments.length < 2 || typeof ver === 'object') { + center = Point.read(arguments, 1); + ver = hor; + } else { + center = Point.read(arguments, 2); + } + if (center) + this.translate(center); + this._a *= hor; + this._c *= hor; + this._b *= ver; + this._d *= ver; + if (center) + this.translate(center.negate()); + return this; + }, + + translate: function(point) { + point = Point.read(arguments); + var x = point.x, y = point.y; + this._tx += x * this._a + y * this._b; + this._ty += x * this._c + y * this._d; + return this; + }, + + rotate: function(angle, center) { + return this.concatenate( + Matrix.getRotateInstance.apply(Matrix, arguments)); + }, + + shear: function( hor, ver, center) { + if (arguments.length < 2 || typeof ver === 'object') { + center = Point.read(arguments, 1); + ver = hor; + } else { + center = Point.read(arguments, 2); + } + if (center) + this.translate(center); + var a = this._a, + c = this._c; + this._a += ver * this._b; + this._c += ver * this._d; + this._b += hor * a; + this._d += hor * c; + if (center) + this.translate(center.negate()); + return this; + }, + + toString: function() { + var format = Base.formatNumber; + return '[[' + [format(this._a), format(this._b), + format(this._tx)].join(', ') + '], [' + + [format(this._c), format(this._d), + format(this._ty)].join(', ') + ']]'; + }, + + getValues: function() { + return [ this._a, this._c, this._b, this._d, this._tx, this._ty ]; + }, + + concatenate: function(mx) { + var a = this._a, + b = this._b, + c = this._c, + d = this._d; + this._a = mx._a * a + mx._c * b; + this._b = mx._b * a + mx._d * b; + this._tx += mx._tx * a + mx._ty * b; + this._c = mx._a * c + mx._c * d; + this._d = mx._b * c + mx._d * d; + this._ty += mx._tx * c + mx._ty * d; + return this; + }, + + preConcatenate: function(mx) { + var a = this._a, + b = this._b, + c = this._c, + d = this._d, + tx = this._tx, + ty = this._ty; + this._a = mx._a * a + mx._b * c; + this._c = mx._c * a + mx._d * c; + this._b = mx._a * b + mx._b * d; + this._d = mx._c * b + mx._d * d; + this._tx = mx._a * tx + mx._b * ty + mx._tx; + this._ty = mx._c * tx + mx._d * ty + mx._ty; + return this; + }, + + transform: function( src, srcOff, dst, dstOff, numPts) { + return arguments.length < 5 + ? this._transformPoint(Point.read(arguments)) + : this._transformCoordinates(src, srcOff, dst, dstOff, numPts); + }, + + _transformPoint: function(point, dest, dontNotify) { + var x = point.x, + y = point.y; + if (!dest) + dest = new Point(Point.dont); + return dest.set( + x * this._a + y * this._b + this._tx, + x * this._c + y * this._d + this._ty, + dontNotify + ); + }, + + _transformCoordinates: function(src, srcOff, dst, dstOff, numPts) { + var i = srcOff, j = dstOff, + srcEnd = srcOff + 2 * numPts; + while (i < srcEnd) { + var x = src[i++]; + var y = src[i++]; + dst[j++] = x * this._a + y * this._b + this._tx; + dst[j++] = x * this._c + y * this._d + this._ty; + } + return dst; + }, + + _transformCorners: function(rect) { + var x1 = rect.x, + y1 = rect.y, + x2 = x1 + rect.width, + y2 = y1 + rect.height, + coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ]; + return this._transformCoordinates(coords, 0, coords, 0, 4); + }, + + _transformBounds: function(bounds) { + var coords = this._transformCorners(bounds), + min = coords.slice(0, 2), + max = coords.slice(0); + for (var i = 2; i < 8; i++) { + var val = coords[i], + j = i & 1; + if (val < min[j]) + min[j] = val; + else if (val > max[j]) + max[j] = val; + } + return Rectangle.create(min[0], min[1], + max[0] - min[0], max[1] - min[1]); + }, + + inverseTransform: function(point) { + return this._inverseTransform(Point.read(arguments)); + }, + + _getDeterminant: function() { + var det = this._a * this._d - this._b * this._c; + return isFinite(det) && Math.abs(det) > Numerical.EPSILON + && isFinite(this._tx) && isFinite(this._ty) + ? det : null; + }, + + _inverseTransform: function(point, dest, dontNotify) { + var det = this._getDeterminant(); + if (!det) + return null; + var x = point.x - this._tx, + y = point.y - this._ty; + if (!dest) + dest = new Point(Point.dont); + return dest.set( + (x * this._d - y * this._b) / det, + (y * this._a - x * this._c) / det, + dontNotify + ); + }, + + getTranslation: function() { + return new Point(this._tx, this._ty); + }, + + getScaling: function() { + var hor = Math.sqrt(this._a * this._a + this._c * this._c), + ver = Math.sqrt(this._b * this._b + this._d * this._d); + return new Point(this._a < 0 ? -hor : hor, this._b < 0 ? -ver : ver); + }, + + getRotation: function() { + var angle1 = -Math.atan2(this._b, this._d), + angle2 = Math.atan2(this._c, this._a); + return Math.abs(angle1 - angle2) < Numerical.TOLERANCE + ? angle1 * 180 / Math.PI : undefined; + }, + + isIdentity: function() { + return this._a == 1 && this._c == 0 && this._b == 0 && this._d == 1 + && this._tx == 0 && this._ty == 0; + }, + + isInvertible: function() { + return !!this._getDeterminant(); + }, + + isSingular: function() { + return !this._getDeterminant(); + }, + + createInverse: function() { + var det = this._getDeterminant(); + return det && Matrix.create( + this._d / det, + -this._c / det, + -this._b / det, + this._a / det, + (this._b * this._ty - this._d * this._tx) / det, + (this._c * this._tx - this._a * this._ty) / det); + }, + + createShiftless: function() { + return Matrix.create(this._a, this._c, this._b, this._d, 0, 0); + }, + + setToScale: function(hor, ver) { + return this.set(hor, 0, 0, ver, 0, 0); + }, + + setToTranslation: function(delta) { + delta = Point.read(arguments); + return this.set(1, 0, 0, 1, delta.x, delta.y); + }, + + setToShear: function(hor, ver) { + return this.set(1, ver, hor, 1, 0, 0); + }, + + setToRotation: function(angle, center) { + center = Point.read(arguments, 1); + angle = angle * Math.PI / 180; + var x = center.x, + y = center.y, + cos = Math.cos(angle), + sin = Math.sin(angle); + return this.set(cos, sin, -sin, cos, + x - x * cos + y * sin, + y - x * sin - y * cos); + }, + + applyToContext: function(ctx, reset) { + ctx[reset ? 'setTransform' : 'transform']( + this._a, this._c, this._b, this._d, this._tx, this._ty); + return this; + }, + + statics: { + create: function(a, c, b, d, tx, ty) { + return new Matrix(Matrix.dont).set(a, c, b, d, tx, ty); + }, + + getScaleInstance: function(hor, ver) { + var mx = new Matrix(); + return mx.setToScale.apply(mx, arguments); + }, + + getTranslateInstance: function(delta) { + var mx = new Matrix(); + return mx.setToTranslation.apply(mx, arguments); + }, + + getShearInstance: function(hor, ver, center) { + var mx = new Matrix(); + return mx.setToShear.apply(mx, arguments); + }, + + getRotateInstance: function(angle, center) { + var mx = new Matrix(); + return mx.setToRotation.apply(mx, arguments); + } + } +}, new function() { + return Base.each({ + scaleX: '_a', + scaleY: '_d', + translateX: '_tx', + translateY: '_ty', + shearX: '_b', + shearY: '_c' + }, function(prop, name) { + name = Base.capitalize(name); + this['get' + name] = function() { + return this[prop]; + }; + this['set' + name] = function(value) { + this[prop] = value; + }; + }, {}); +}); + +var Line = this.Line = Base.extend({ + initialize: function(point1, point2, infinite) { + point1 = Point.read(arguments, 0, 1); + point2 = Point.read(arguments, 1, 1); + if (arguments.length == 3) { + this.point = point1; + this.vector = point2.subtract(point1); + this.infinite = infinite; + } else { + this.point = point1; + this.vector = point2; + this.infinite = true; + } + }, + + intersect: function(line) { + var cross = this.vector.cross(line.vector); + if (Math.abs(cross) <= Numerical.EPSILON) + return null; + var v = line.point.subtract(this.point), + t1 = v.cross(line.vector) / cross, + t2 = v.cross(this.vector) / cross; + return (this.infinite || 0 <= t1 && t1 <= 1) + && (line.infinite || 0 <= t2 && t2 <= 1) + ? this.point.add(this.vector.multiply(t1)) : null; + }, + + getSide: function(point) { + var v1 = this.vector, + v2 = point.subtract(this.point), + ccw = v2.cross(v1); + if (ccw == 0) { + ccw = v2.dot(v1); + if (ccw > 0) { + ccw = v2.subtract(v1).dot(v1); + if (ccw < 0) + ccw = 0; + } + } + return ccw < 0 ? -1 : ccw > 0 ? 1 : 0; + }, + + getDistance: function(point) { + var m = this.vector.y / this.vector.x, + b = this.point.y - (m * this.point.x); + var dist = Math.abs(point.y - (m * point.x) - b) / Math.sqrt(m * m + 1); + return this.infinite ? dist : Math.min(dist, + point.getDistance(this.point), + point.getDistance(this.point.add(this.vector))); + } +}); + +var Project = this.Project = PaperScopeItem.extend({ + _list: 'projects', + _reference: 'project', + + initialize: function() { + this.base(true); + this._currentStyle = new PathStyle(); + this._selectedItems = {}; + this._selectedItemCount = 0; + this.layers = []; + this.symbols = []; + this.activeLayer = new Layer(); + }, + + _needsRedraw: function() { + if (this._scope) + this._scope._needsRedraw(); + }, + + getCurrentStyle: function() { + return this._currentStyle; + }, + + setCurrentStyle: function(style) { + this._currentStyle.initialize(style); + }, + + getIndex: function() { + return this._index; + }, + + getSelectedItems: function() { + var items = []; + Base.each(this._selectedItems, function(item) { + items.push(item); + }); + return items; + }, + + _updateSelection: function(item) { + if (item._selected) { + this._selectedItemCount++; + this._selectedItems[item.getId()] = item; + } else { + this._selectedItemCount--; + delete this._selectedItems[item.getId()]; + } + }, + + selectAll: function() { + for (var i = 0, l = this.layers.length; i < l; i++) + this.layers[i].setSelected(true); + }, + + deselectAll: function() { + for (var i in this._selectedItems) + this._selectedItems[i].setSelected(false); + }, + + hitTest: function(point, options) { + options = HitResult.getOptions(point, options); + point = options.point; + for (var i = this.layers.length - 1; i >= 0; i--) { + var res = this.layers[i].hitTest(point, options); + if (res) return res; + } + return null; + }, + + draw: function(ctx) { + ctx.save(); + var param = { offset: new Point(0, 0) }; + for (var i = 0, l = this.layers.length; i < l; i++) + Item.draw(this.layers[i], ctx, param); + ctx.restore(); + + if (this._selectedItemCount > 0) { + ctx.save(); + ctx.strokeWidth = 1; + ctx.strokeStyle = ctx.fillStyle = '#009dec'; + param = { selection: true }; + Base.each(this._selectedItems, function(item) { + item.draw(ctx, param); + }); + ctx.restore(); + } + } +}); + +var Symbol = this.Symbol = Base.extend({ + initialize: function(item) { + this.project = paper.project; + this.project.symbols.push(this); + this.setDefinition(item); + this._instances = {}; + }, + + _changed: function(flags) { + Base.each(this._instances, function(item) { + item._changed(flags); + }); + }, + + getDefinition: function() { + return this._definition; + }, + + setDefinition: function(item) { + if (item._parentSymbol) + item = item.clone(); + if (this._definition) + delete this._definition._parentSymbol; + this._definition = item; + item.remove(); + item.setPosition(new Point()); + item._parentSymbol = this; + this._changed(Change.GEOMETRY); + }, + + place: function(position) { + return new PlacedSymbol(this, position); + }, + + clone: function() { + return new Symbol(this._definition.clone()); + } +}); + +var ChangeFlag = { + APPEARANCE: 1, + HIERARCHY: 2, + GEOMETRY: 4, + STROKE: 8, + STYLE: 16, + ATTRIBUTE: 32, + CONTENT: 64, + PIXELS: 128, + CLIPPING: 256 +}; + +var Change = { + HIERARCHY: ChangeFlag.HIERARCHY | ChangeFlag.APPEARANCE, + GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE, + STROKE: ChangeFlag.STROKE | ChangeFlag.STYLE | ChangeFlag.APPEARANCE, + STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE, + ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE, + CONTENT: ChangeFlag.CONTENT | ChangeFlag.APPEARANCE, + PIXELS: ChangeFlag.PIXELS | ChangeFlag.APPEARANCE +}; + +var Item = this.Item = Base.extend({ + initialize: function() { + this._id = ++Item._id; + if (!this._project) + paper.project.activeLayer.addChild(this); + this._style = PathStyle.create(this); + this.setStyle(this._project.getCurrentStyle()); + }, + + _changed: function(flags) { + if (flags & ChangeFlag.GEOMETRY) { + delete this._bounds; + delete this._position; + } + if (flags & ChangeFlag.APPEARANCE) { + this._project._needsRedraw(); + } + if (this._parentSymbol) + this._parentSymbol._changed(flags); + if (this._project._changes) { + var entry = this._project._changesById[this._id]; + if (entry) { + entry.flags |= flags; + } else { + entry = { item: this, flags: flags }; + this._project._changesById[this._id] = entry; + this._project._changes.push(entry); + } + } + }, + + getId: function() { + return this._id; + }, + + getName: function() { + return this._name; + }, + + setName: function(name) { + + if (this._name) + this._removeFromNamed(); + this._name = name || undefined; + if (name) { + var children = this._parent._children, + namedChildren = this._parent._namedChildren; + (namedChildren[name] = namedChildren[name] || []).push(this); + children[name] = this; + } + this._changed(ChangeFlag.ATTRIBUTE); + }, + + getPosition: function() { + var pos = this._position + || (this._position = this.getBounds().getCenter()); + return LinkedPoint.create(this, 'setPosition', pos._x, pos._y); + }, + + setPosition: function(point) { + this.translate(Point.read(arguments).subtract(this.getPosition())); + }, + + getStyle: function() { + return this._style; + }, + + setStyle: function(style) { + this._style.initialize(style); + }, + + statics: { + _id: 0 + } +}, new function() { + return Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'], + function(name) { + var part = Base.capitalize(name), + name = '_' + name; + this['get' + part] = function() { + return this[name]; + }; + this['set' + part] = function(value) { + if (value != this[name]) { + this[name] = value; + this._changed(name === '_locked' + ? ChangeFlag.ATTRIBUTE : Change.ATTRIBUTE); + } + }; + }, {}); +}, { + + _locked: false, + + _visible: true, + + _blendMode: 'normal', + + _opacity: 1, + + _guide: false, + + isSelected: function() { + if (this._children) { + for (var i = 0, l = this._children.length; i < l; i++) + if (this._children[i].isSelected()) + return true; + } + return this._selected; + }, + + setSelected: function(selected) { + if (this._children) { + for (var i = 0, l = this._children.length; i < l; i++) { + this._children[i].setSelected(selected); + } + } else if ((selected = !!selected) != this._selected) { + this._selected = selected; + this._project._updateSelection(this); + this._changed(Change.ATTRIBUTE); + } + }, + + _selected: false, + + isFullySelected: function() { + if (this._children && this._selected) { + for (var i = 0, l = this._children.length; i < l; i++) + if (!this._children[i].isFullySelected()) + return false; + return true; + } + return this._selected; + }, + + setFullySelected: function(selected) { + if (this._children) { + for (var i = 0, l = this._children.length; i < l; i++) { + this._children[i].setFullySelected(selected); + } + } + this.setSelected(selected); + }, + + isClipMask: function() { + return this._clipMask; + }, + + setClipMask: function(clipMask) { + if (this._clipMask != (clipMask = !!clipMask)) { + this._clipMask = clipMask; + if (clipMask) { + this.setFillColor(null); + this.setStrokeColor(null); + } + this._changed(Change.ATTRIBUTE); + if (this._parent) + this._parent._changed(ChangeFlag.CLIPPING); + } + }, + + _clipMask: false, + + getProject: function() { + return this._project; + }, + + _setProject: function(project) { + if (this._project != project) { + this._project = project; + if (this._children) { + for (var i = 0, l = this._children.length; i < l; i++) { + this._children[i]._setProject(project); + } + } + } + }, + + getLayer: function() { + var parent = this; + while (parent = parent._parent) { + if (parent instanceof Layer) + return parent; + } + return null; + }, + + getParent: function() { + return this._parent; + }, + + getChildren: function() { + return this._children; + }, + + setChildren: function(items) { + this.removeChildren(); + this.addChildren(items); + }, + + getFirstChild: function() { + return this._children && this._children[0] || null; + }, + + getLastChild: function() { + return this._children && this._children[this._children.length - 1] + || null; + }, + + getNextSibling: function() { + return this._parent && this._parent._children[this._index + 1] || null; + }, + + getPreviousSibling: function() { + return this._parent && this._parent._children[this._index - 1] || null; + }, + + getIndex: function() { + return this._index; + }, + + clone: function() { + return this._clone(new this.constructor()); + }, + + _clone: function(copy) { + copy.setStyle(this._style); + if (this._children) { + for (var i = 0, l = this._children.length; i < l; i++) + copy.addChild(this._children[i].clone()); + } + var keys = ['_locked', '_visible', '_blendMode', '_opacity', + '_clipMask', '_guide']; + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + if (this.hasOwnProperty(key)) + copy[key] = this[key]; + } + copy.setSelected(this._selected); + if (this._name) + copy.setName(this._name); + return copy; + }, + + copyTo: function(itemOrProject) { + var copy = this.clone(); + if (itemOrProject.layers) { + itemOrProject.activeLayer.addChild(copy); + } else { + itemOrProject.addChild(copy); + } + return copy; + }, + + rasterize: function(resolution) { + var bounds = this.getStrokeBounds(), + scale = (resolution || 72) / 72, + canvas = CanvasProvider.getCanvas(bounds.getSize().multiply(scale)), + ctx = canvas.getContext('2d'), + matrix = new Matrix().scale(scale).translate(-bounds.x, -bounds.y); + matrix.applyToContext(ctx); + this.draw(ctx, {}); + var raster = new Raster(canvas); + raster.setBounds(bounds); + return raster; + }, + + hitTest: function(point, options, matrix) { + options = HitResult.getOptions(point, options); + point = options.point; + if (!this._children && !this.getRoughBounds(matrix) + .expand(options.tolerance)._containsPoint(point)) + return null; + if ((options.center || options.bounds) && + !(this instanceof Layer && !this._parent)) { + var bounds = this.getBounds(), + that = this, + points = ['TopLeft', 'TopRight', 'BottomLeft', 'BottomRight', + 'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'], + res; + function checkBounds(type, part) { + var pt = bounds['get' + part]().transform(matrix); + if (point.getDistance(pt) < options.tolerance) + return new HitResult(type, that, + { name: Base.hyphenate(part), point: pt }); + } + if (options.center && (res = checkBounds('center', 'Center'))) + return res; + if (options.bounds) { + for (var i = 0; i < 8; i++) + if (res = checkBounds('bounds', points[i])) + return res; + } + } + + return this._children || !(options.guides && !this._guide + || options.selected && !this._selected) + ? this._hitTest(point, options, matrix) : null; + }, + + _hitTest: function(point, options, matrix) { + if (this._children) { + for (var i = this._children.length - 1; i >= 0; i--) { + var res = this._children[i].hitTest(point, options, matrix); + if (res) return res; + } + } + }, + + addChild: function(item) { + return this.insertChild(undefined, item); + }, + + insertChild: function(index, item) { + if (this._children) { + item._remove(false, true); + Base.splice(this._children, [item], index, 0); + item._parent = this; + item._setProject(this._project); + if (item._name) + item.setName(item._name); + this._changed(Change.HIERARCHY); + return true; + } + return false; + }, + + addChildren: function(items) { + for (var i = 0, l = items && items.length; i < l; i++) + this.insertChild(undefined, items[i]); + }, + + insertChildren: function(index, items) { + for (var i = 0, l = items && items.length; i < l; i++) { + if (this.insertChild(index, items[i])) + index++; + } + }, + + insertAbove: function(item) { + return item._parent && item._parent.insertChild( + item._index + 1, this); + }, + + insertBelow: function(item) { + return item._parent && item._parent.insertChild( + item._index - 1, this); + }, + + appendTop: function(item) { + return this.addChild(item); + }, + + appendBottom: function(item) { + return this.insertChild(0, item); + }, + + moveAbove: function(item) { + return this.insertAbove(item); + }, + + moveBelow: function(item) { + return this.insertBelow(item); + }, + + _removeFromNamed: function() { + var children = this._parent._children, + namedChildren = this._parent._namedChildren, + name = this._name, + namedArray = namedChildren[name], + index = namedArray ? namedArray.indexOf(this) : -1; + if (index == -1) + return; + if (children[name] == this) + delete children[name]; + namedArray.splice(index, 1); + if (namedArray.length) { + children[name] = namedArray[namedArray.length - 1]; + } else { + delete namedChildren[name]; + } + }, + + _remove: function(deselect, notify) { + if (this._parent) { + if (deselect) + this.setSelected(false); + if (this._name) + this._removeFromNamed(); + Base.splice(this._parent._children, null, this._index, 1); + if (notify) + this._parent._changed(Change.HIERARCHY); + this._parent = null; + return true; + } + return false; + }, + + remove: function() { + return this._remove(true, true); + }, + + removeChildren: function(from, to) { + if (!this._children) + return null; + from = from || 0; + to = Base.pick(to, this._children.length); + var removed = this._children.splice(from, to - from); + for (var i = removed.length - 1; i >= 0; i--) + removed[i]._remove(true, false); + if (removed.length > 0) + this._changed(Change.HIERARCHY); + return removed; + }, + + reverseChildren: function() { + if (this._children) { + this._children.reverse(); + for (var i = 0, l = this._children.length; i < l; i++) + this._children[i]._index = i; + this._changed(Change.HIERARCHY); + } + }, + + isEditable: function() { + var item = this; + while (item) { + if (!item._visible || item._locked) + return false; + item = item._parent; + } + return true; + }, + + _getOrder: function(item) { + function getList(item) { + var list = []; + do { + list.unshift(item); + } while (item = item._parent) + return list; + } + var list1 = getList(this), + list2 = getList(item); + for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) { + if (list1[i] != list2[i]) { + return list1[i]._index < list2[i]._index ? 1 : -1; + } + } + return 0; + }, + + hasChildren: function() { + return this._children && this._children.length > 0; + }, + + isAbove: function(item) { + return this._getOrder(item) == -1; + }, + + isBelow: function(item) { + return this._getOrder(item) == 1; + }, + + isParent: function(item) { + return this._parent == item; + }, + + isChild: function(item) { + return item && item._parent == this; + }, + + isDescendant: function(item) { + var parent = this; + while (parent = parent._parent) { + if (parent == item) + return true; + } + return false; + }, + + isAncestor: function(item) { + return item ? item.isDescendant(this) : false; + }, + + isGroupedWith: function(item) { + var parent = this._parent; + while (parent) { + if (parent._parent + && (parent instanceof Group || parent instanceof CompoundPath) + && item.isDescendant(parent)) + return true; + parent = parent._parent; + } + return false; + }, + + _getBounds: function(getter, cacheName, args) { + var children = this._children; + if (!children || children.length == 0) + return new Rectangle(); + var x1 = Infinity, + x2 = -x1, + y1 = x1, + y2 = x2; + for (var i = 0, l = children.length; i < l; i++) { + var child = children[i]; + if (child._visible) { + var rect = child[getter](args[0]); + x1 = Math.min(rect.x, x1); + y1 = Math.min(rect.y, y1); + x2 = Math.max(rect.x + rect.width, x2); + y2 = Math.max(rect.y + rect.height, y2); + } + } + var bounds = Rectangle.create(x1, y1, x2 - x1, y2 - y1); + return getter == 'getBounds' ? this._createBounds(bounds) : bounds; + }, + + _createBounds: function(rect) { + return LinkedRectangle.create(this, 'setBounds', + rect.x, rect.y, rect.width, rect.height); + }, + + getBounds: function() { + return this._getBounds('getBounds', '_bounds', arguments); + }, + + setBounds: function(rect) { + rect = Rectangle.read(arguments); + var bounds = this.getBounds(), + matrix = new Matrix(), + center = rect.getCenter(); + matrix.translate(center); + if (rect.width != bounds.width || rect.height != bounds.height) { + matrix.scale( + bounds.width != 0 ? rect.width / bounds.width : 1, + bounds.height != 0 ? rect.height / bounds.height : 1); + } + center = bounds.getCenter(); + matrix.translate(-center.x, -center.y); + this.transform(matrix); + }, + + getStrokeBounds: function() { + return this._getBounds('getStrokeBounds', '_strokeBounds', arguments); + }, + + getHandleBounds: function() { + return this._getBounds('getHandleBounds', '_handleBounds', arguments); + }, + + getRoughBounds: function() { + return this._getBounds('getRoughBounds', '_roughBounds', arguments); + }, + + scale: function(hor, ver , center) { + if (arguments.length < 2 || typeof ver === 'object') { + center = ver; + ver = hor; + } + return this.transform(new Matrix().scale(hor, ver, + center || this.getPosition())); + }, + + translate: function(delta) { + var mx = new Matrix(); + return this.transform(mx.translate.apply(mx, arguments)); + }, + + rotate: function(angle, center) { + return this.transform(new Matrix().rotate(angle, + center || this.getPosition())); + }, + + shear: function(hor, ver, center) { + if (arguments.length < 2 || typeof ver === 'object') { + center = ver; + ver = hor; + } + return this.transform(new Matrix().shear(hor, ver, + center || this.getPosition())); + }, + + transform: function(matrix, flags) { + var bounds = this._bounds, + position = this._position, + children = this._children; + if (this._transform) { + this._transform(matrix, flags); + this._changed(Change.GEOMETRY); + } + if (bounds && matrix.getRotation() % 90 === 0) { + this._bounds = this._createBounds( + matrix._transformBounds(bounds)); + this._position = this._bounds.getCenter(); + } else if (position) { + this._position = matrix._transformPoint(position, position, true); + } + for (var i = 0, l = children && children.length; i < l; i++) + children[i].transform(matrix, flags); + return this; + }, + + fitBounds: function(rectangle, fill) { + rectangle = Rectangle.read(arguments); + var bounds = this.getBounds(), + itemRatio = bounds.height / bounds.width, + rectRatio = rectangle.height / rectangle.width, + scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio) + ? rectangle.width / bounds.width + : rectangle.height / bounds.height, + delta = rectangle.getCenter().subtract(bounds.getCenter()), + newBounds = new Rectangle(new Point(), + new Size(bounds.width * scale, bounds.height * scale)); + newBounds.setCenter(rectangle.getCenter()); + this.setBounds(newBounds); + }, + + toString: function() { + return (this.constructor._name || 'Item') + (this._name + ? " '" + this._name + "'" + : ' @' + this._id); + }, + + statics: { + drawSelectedBounds: function(bounds, ctx, matrix) { + var coords = matrix._transformCorners(bounds); + ctx.beginPath(); + for (var i = 0; i < 8; i++) + ctx[i == 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]); + ctx.closePath(); + ctx.stroke(); + for (var i = 0; i < 8; i++) { + ctx.beginPath(); + ctx.rect(coords[i] - 2, coords[++i] - 2, 4, 4); + ctx.fill(); + } + }, + + draw: function(item, ctx, param) { + if (!item._visible || item._opacity == 0) + return; + + var tempCanvas, parentCtx; + if (item._blendMode !== 'normal' + || item._opacity < 1 + && !(item._segments && (!item.getFillColor() + || !item.getStrokeColor()))) { + var bounds = item.getStrokeBounds() || item.getBounds(); + if (!bounds.width || !bounds.height) + return; + + var itemOffset = bounds.getTopLeft().floor(), + size = bounds.getSize().ceil().add(new Size(1, 1)); + tempCanvas = CanvasProvider.getCanvas(size); + + parentCtx = ctx; + + ctx = tempCanvas.getContext('2d'); + ctx.save(); + + ctx.translate(-itemOffset.x, -itemOffset.y); + } + var savedOffset; + if (itemOffset) { + savedOffset = param.offset; + param.offset = itemOffset; + } + item.draw(ctx, param); + if (itemOffset) + param.offset = savedOffset; + + if (tempCanvas) { + + ctx.restore(); + + if (item._blendMode !== 'normal') { + var pixelOffset = itemOffset.subtract(param.offset); + BlendMode.process(item._blendMode, ctx, parentCtx, + item._opacity, pixelOffset); + } else { + parentCtx.save(); + parentCtx.globalAlpha = item._opacity; + parentCtx.drawImage(tempCanvas, + itemOffset.x, itemOffset.y); + parentCtx.restore(); + } + + CanvasProvider.returnCanvas(tempCanvas); + } + } + } +}, new function() { + + var sets = { + down: {}, drag: {}, up: {}, move: {} + }; + + function removeAll(set) { + for (var id in set) { + var item = set[id]; + item.remove(); + for (var type in sets) { + var other = sets[type]; + if (other != set && other[item.getId()]) + delete other[item.getId()]; + } + } + } + + function installHandler(name) { + var handler = 'onMouse' + Base.capitalize(name); + var func = paper.tool[handler]; + if (!func || !func._installed) { + var hash = {}; + hash[handler] = function(event) { + if (name === 'up') + sets.drag = {}; + removeAll(sets[name]); + sets[name] = {}; + if (this.base) + this.base(event); + }; + paper.tool.inject(hash); + paper.tool[handler]._installed = true; + } + } + + return Base.each(['down', 'drag', 'up', 'move'], function(name) { + this['removeOn' + Base.capitalize(name)] = function() { + var hash = {}; + hash[name] = true; + return this.removeOn(hash); + }; + }, { + removeOn: function(obj) { + for (var name in obj) { + if (obj[name]) { + sets[name][this.getId()] = this; + if (name === 'drag') + installHandler('up'); + installHandler(name); + } + } + return this; + } + }); +}); + +var Group = this.Group = Item.extend({ + initialize: function(items) { + this.base(); + this._children = []; + this._namedChildren = {}; + this.addChildren(!items || !Array.isArray(items) + || typeof items[0] !== 'object' ? arguments : items); + }, + + _changed: function(flags) { + Item.prototype._changed.call(this, flags); + if (flags & (ChangeFlag.HIERARCHY | ChangeFlag.CLIPPING)) { + delete this._clipItem; + } + }, + + _getClipItem: function() { + if (this._clipItem !== undefined) + return this._clipItem; + for (var i = 0, l = this._children.length; i < l; i++) { + var child = this._children[i]; + if (child._clipMask) + return this._clipItem = child; + } + return this._clipItem = null; + }, + + isClipped: function() { + return !!this._getClipItem(); + }, + + setClipped: function(clipped) { + var child = this.getFirstChild(); + if (child) + child.setClipMask(clipped); + return this; + }, + + draw: function(ctx, param) { + var clipItem = this._getClipItem(); + if (clipItem) + Item.draw(clipItem, ctx, param); + for (var i = 0, l = this._children.length; i < l; i++) { + var item = this._children[i]; + if (item != clipItem) + Item.draw(item, ctx, param); + } + } +}); + +var Layer = this.Layer = Group.extend({ + initialize: function(items) { + this._project = paper.project; + this._index = this._project.layers.push(this) - 1; + this.base.apply(this, arguments); + this.activate(); + }, + + _remove: function(deselect, notify) { + if (this._parent) + return this.base(deselect, notify); + if (this._index != null) { + if (deselect) + this.setSelected(false); + Base.splice(this._project.layers, null, this._index, 1); + this._project._needsRedraw(); + return true; + } + return false; + }, + + getNextSibling: function() { + return this._parent ? this.base() + : this._project.layers[this._index + 1] || null; + }, + + getPreviousSibling: function() { + return this._parent ? this.base() + : this._project.layers[this._index - 1] || null; + }, + + activate: function() { + this._project.activeLayer = this; + } +}, new function () { + function insert(above) { + return function(item) { + if (item instanceof Layer && !item._parent + && this._remove(false, true)) { + Base.splice(item._project.layers, [this], + item._index + (above ? 1 : -1), 0); + this._setProject(item._project); + return true; + } + return this.base(item); + }; + } + + return { + insertAbove: insert(true), + + insertBelow: insert(false) + }; +}); + +var PlacedItem = this.PlacedItem = Item.extend({ + + _transform: function(matrix, flags) { + this._matrix.preConcatenate(matrix); + }, + + _changed: function(flags) { + Item.prototype._changed.call(this, flags); + if (flags & ChangeFlag.GEOMETRY) { + delete this._strokeBounds; + delete this._handleBounds; + delete this._roughBounds; + } + }, + + getMatrix: function() { + return this._matrix; + }, + + setMatrix: function(matrix) { + this._matrix = matrix.clone(); + this._changed(Change.GEOMETRY); + }, + + getBounds: function() { + var useCache = arguments[0] === undefined; + if (useCache && this._bounds) + return this._bounds; + var bounds = this.getStrokeBounds(arguments[0]); + if (useCache) + bounds = this._bounds = this._createBounds(bounds); + return bounds; + }, + + _getBounds: function(getter, cacheName, args) { + var matrix = args[0], + useCache = matrix === undefined; + if (useCache && this[cacheName]) + return this[cacheName]; + matrix = matrix ? matrix.clone().concatenate(this._matrix) + : this._matrix; + var bounds = this._calculateBounds(getter, matrix); + if (useCache) + this[cacheName] = bounds; + return bounds; + } +}); + +var Raster = this.Raster = PlacedItem.extend({ + initialize: function(object) { + this.base(); + if (object.getContext) { + this.setCanvas(object); + } else { + if (typeof object === 'string') + object = document.getElementById(object); + this.setImage(object); + } + this._matrix = new Matrix(); + }, + + clone: function() { + var image = this._image; + if (!image) { + image = CanvasProvider.getCanvas(this._size); + image.getContext('2d').drawImage(this._canvas, 0, 0); + } + var copy = new Raster(image); + copy._matrix = this._matrix.clone(); + return this._clone(copy); + }, + + getSize: function() { + return this._size; + }, + + setSize: function() { + var size = Size.read(arguments), + image = this.getImage(); + this.setCanvas(CanvasProvider.getCanvas(size)); + this.getContext(true).drawImage(image, 0, 0, size.width, size.height); + }, + + getWidth: function() { + return this._size.width; + }, + + getHeight: function() { + return this._size.height; + }, + + getPpi: function() { + var matrix = this._matrix, + orig = new Point(0, 0).transform(matrix), + u = new Point(1, 0).transform(matrix).subtract(orig), + v = new Point(0, 1).transform(matrix).subtract(orig); + return new Size( + 72 / u.getLength(), + 72 / v.getLength() + ); + }, + + getContext: function() { + if (!this._context) + this._context = this.getCanvas().getContext('2d'); + if (arguments[0]) + this._changed(Change.PIXELS); + return this._context; + }, + + setContext: function(context) { + this._context = context; + }, + + getCanvas: function() { + if (!this._canvas) { + this._canvas = CanvasProvider.getCanvas(this._size); + if (this._image) + this.getContext(true).drawImage(this._image, 0, 0); + } + return this._canvas; + }, + + setCanvas: function(canvas) { + if (this._canvas) + CanvasProvider.returnCanvas(this._canvas); + this._canvas = canvas; + this._size = new Size(canvas.width, canvas.height); + this._image = null; + this._context = null; + this._changed(Change.GEOMETRY); + }, + + getImage: function() { + return this._image || this.getCanvas(); + }, + + setImage: function(image) { + if (this._canvas) + CanvasProvider.returnCanvas(this._canvas); + this._image = image; + this._size = new Size(image.naturalWidth, image.naturalHeight); + this._canvas = null; + this._context = null; + this._changed(Change.GEOMETRY); + }, + + getSubImage: function(rect) { + rect = Rectangle.read(arguments); + var canvas = CanvasProvider.getCanvas(rect.getSize()); + canvas.getContext('2d').drawImage(this.getCanvas(), rect.x, rect.y, + canvas.width, canvas.height, 0, 0, canvas.width, canvas.height); + return canvas; + }, + + drawImage: function(image, point) { + point = Point.read(arguments, 1); + this.getContext(true).drawImage(image, point.x, point.y); + }, + + getAverageColor: function(object) { + if (!object) + object = this.getBounds(); + var bounds, path; + if (object instanceof PathItem) { + path = object; + bounds = object.getBounds(); + } else if (object.width) { + bounds = new Rectangle(object); + } else if (object.x) { + bounds = Rectangle.create(object.x - 0.5, object.y - 0.5, 1, 1); + } + var sampleSize = 32, + width = Math.min(bounds.width, sampleSize), + height = Math.min(bounds.height, sampleSize); + var ctx = Raster._sampleContext; + if (!ctx) { + ctx = Raster._sampleContext = CanvasProvider.getCanvas( + new Size(sampleSize)).getContext('2d'); + } else { + ctx.clearRect(0, 0, sampleSize, sampleSize); + } + ctx.save(); + ctx.scale(width / bounds.width, height / bounds.height); + ctx.translate(-bounds.x, -bounds.y); + if (path) + path.draw(ctx, { clip: true }); + this._matrix.applyToContext(ctx); + ctx.drawImage(this._canvas || this._image, + -this._size.width / 2, -this._size.height / 2); + ctx.restore(); + var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width), + Math.ceil(height)).data, + channels = [0, 0, 0], + total = 0; + for (var i = 0, l = pixels.length; i < l; i += 4) { + var alpha = pixels[i + 3]; + total += alpha; + alpha /= 255; + channels[0] += pixels[i] * alpha; + channels[1] += pixels[i + 1] * alpha; + channels[2] += pixels[i + 2] * alpha; + } + for (var i = 0; i < 3; i++) + channels[i] /= total; + return total ? Color.read(channels) : null; + }, + + getPixel: function(point) { + point = Point.read(arguments); + var pixels = this.getContext().getImageData(point.x, point.y, 1, 1).data, + channels = new Array(4); + for (var i = 0; i < 4; i++) + channels[i] = pixels[i] / 255; + return RgbColor.read(channels); + }, + + setPixel: function(point, color) { + var hasPoint = arguments.length == 2; + point = Point.read(arguments, 0, hasPoint ? 1 : 2); + color = Color.read(arguments, hasPoint ? 1 : 2); + var ctx = this.getContext(true), + imageData = ctx.createImageData(1, 1), + alpha = color.getAlpha(); + imageData.data[0] = color.getRed() * 255; + imageData.data[1] = color.getGreen() * 255; + imageData.data[2] = color.getBlue() * 255; + imageData.data[3] = alpha != null ? alpha * 255 : 255; + ctx.putImageData(imageData, point.x, point.y); + }, + + createData: function(size) { + size = Size.read(arguments); + return this.getContext().createImageData(size.width, size.height); + }, + + getData: function(rect) { + rect = Rectangle.read(arguments); + if (rect.isEmpty()) + rect = new Rectangle(this.getSize()); + return this.getContext().getImageData(rect.x, rect.y, + rect.width, rect.height); + }, + + setData: function(data, point) { + point = Point.read(arguments, 1); + this.getContext(true).putImageData(data, point.x, point.y); + }, + + _calculateBounds: function(getter, matrix) { + return matrix._transformBounds( + new Rectangle(this._size).setCenter(0, 0)); + }, + + getHandleBounds: function() { + return this.getStrokeBounds(arguments[0]); + }, + + getRoughBounds: function() { + return this.getStrokeBounds(arguments[0]); + }, + + draw: function(ctx, param) { + if (param.selection) { + var bounds = new Rectangle(this._size).setCenter(0, 0); + Item.drawSelectedBounds(bounds, ctx, this._matrix); + } else { + ctx.save(); + this._matrix.applyToContext(ctx); + ctx.drawImage(this._canvas || this._image, + -this._size.width / 2, -this._size.height / 2); + ctx.restore(); + } + } +}); + +var PlacedSymbol = this.PlacedSymbol = PlacedItem.extend({ + initialize: function(symbol, matrixOrOffset) { + this.base(); + this.setSymbol(symbol instanceof Symbol ? symbol : new Symbol(symbol)); + this._matrix = matrixOrOffset !== undefined + ? matrixOrOffset instanceof Matrix + ? matrixOrOffset + : new Matrix().translate(Point.read(arguments, 1)) + : new Matrix(); + }, + + getSymbol: function() { + return this._symbol; + }, + + setSymbol: function(symbol) { + if (this._symbol) + delete this._symbol._instances[this._id]; + this._symbol = symbol; + symbol._instances[this._id] = this; + }, + + clone: function() { + return this._clone(new PlacedSymbol(this.symbol, this._matrix.clone())); + }, + + _calculateBounds: function(getter, matrix) { + return this.symbol._definition[getter](matrix); + }, + + draw: function(ctx, param) { + if (param.selection) { + Item.drawSelectedBounds(this.symbol._definition.getStrokeBounds(), + ctx, this._matrix); + } else { + ctx.save(); + this._matrix.applyToContext(ctx); + Item.draw(this.symbol.getDefinition(), ctx, param); + ctx.restore(); + } + } + +}); + +HitResult = Base.extend({ + initialize: function(type, item, values) { + this.type = type; + this.item = item; + if (values) { + Base.each(values, function(value, key) { + this[key] = value; + }, this); + } + }, + + statics: { + getOptions: function(point, options) { + return options && options._merged ? options : Base.merge({ + point: Point.read(arguments, 0, 1), + type: null, + tolerance: 2, + fill: !options, + stroke: !options, + segments: !options, + handles: false, + ends: false, + center: false, + bounds: false, + guides: false, + selected: false, + _merged: true + }, options); + } + } +}); + +var Segment = this.Segment = Base.extend({ + initialize: function(arg0, arg1, arg2, arg3, arg4, arg5) { + var count = arguments.length, + createPoint = SegmentPoint.create, + point, handleIn, handleOut; + if (count == 0) { + } else if (count == 1) { + if (arg0.point) { + point = arg0.point; + handleIn = arg0.handleIn; + handleOut = arg0.handleOut; + } else { + point = arg0; + } + } else if (count < 6) { + if (count == 2 && arg1.x === undefined) { + point = [ arg0, arg1 ]; + } else { + point = arg0; + handleIn = arg1; + handleOut = arg2; + } + } else if (count == 6) { + point = [ arg0, arg1 ]; + handleIn = [ arg2, arg3 ]; + handleOut = [ arg4, arg5 ]; + } + createPoint(this, '_point', point); + createPoint(this, '_handleIn', handleIn); + createPoint(this, '_handleOut', handleOut); + }, + + _changed: function(point) { + if (!this._path) + return; + var curve = this._path._curves && this.getCurve(), other; + if (curve) { + curve._changed(); + if (other = (curve[point == this._point + || point == this._handleIn && curve._segment1 == this + ? 'getPrevious' : 'getNext']())) { + other._changed(); + } + } + this._path._changed(Change.GEOMETRY); + }, + + getPoint: function() { + return this._point; + }, + + setPoint: function(point) { + point = Point.read(arguments); + this._point.set(point.x, point.y); + }, + + getHandleIn: function() { + return this._handleIn; + }, + + setHandleIn: function(point) { + point = Point.read(arguments); + this._handleIn.set(point.x, point.y); + }, + + getHandleOut: function() { + return this._handleOut; + }, + + setHandleOut: function(point) { + point = Point.read(arguments); + this._handleOut.set(point.x, point.y); + }, + + _isSelected: function(point) { + var state = this._selectionState; + return point == this._point ? !!(state & SelectionState.POINT) + : point == this._handleIn ? !!(state & SelectionState.HANDLE_IN) + : point == this._handleOut ? !!(state & SelectionState.HANDLE_OUT) + : false; + }, + + _setSelected: function(point, selected) { + var path = this._path, + selected = !!selected, + state = this._selectionState || 0, + selection = [ + !!(state & SelectionState.POINT), + !!(state & SelectionState.HANDLE_IN), + !!(state & SelectionState.HANDLE_OUT) + ]; + if (point == this._point) { + if (selected) { + selection[1] = selection[2] = false; + } else { + var previous = this.getPrevious(), + next = this.getNext(); + selection[1] = previous && (previous._point.isSelected() + || previous._handleOut.isSelected()); + selection[2] = next && (next._point.isSelected() + || next._handleIn.isSelected()); + } + selection[0] = selected; + } else { + var index = point == this._handleIn ? 1 : 2; + if (selection[index] != selected) { + if (selected) + selection[0] = false; + selection[index] = selected; + path._changed(Change.ATTRIBUTE); + } + } + this._selectionState = (selection[0] ? SelectionState.POINT : 0) + | (selection[1] ? SelectionState.HANDLE_IN : 0) + | (selection[2] ? SelectionState.HANDLE_OUT : 0); + if (path && state != this._selectionState) + path._updateSelection(this, state, this._selectionState); + }, + + isSelected: function() { + return this._isSelected(this._point); + }, + + setSelected: function(selected) { + this._setSelected(this._point, selected); + }, + + getIndex: function() { + return this._index !== undefined ? this._index : null; + }, + + getPath: function() { + return this._path || null; + }, + + getCurve: function() { + if (this._path) { + var index = this._index; + if (!this._path._closed && index == this._path._segments.length - 1) + index--; + return this._path.getCurves()[index] || null; + } + return null; + }, + + getNext: function() { + var segments = this._path && this._path._segments; + return segments && (segments[this._index + 1] + || this._path._closed && segments[0]) || null; + }, + + getPrevious: function() { + var segments = this._path && this._path._segments; + return segments && (segments[this._index - 1] + || this._path._closed && segments[segments.length - 1]) || null; + }, + + reverse: function() { + return new Segment(this._point, this._handleOut, this._handleIn); + }, + + remove: function() { + return this._path ? !!this._path.removeSegment(this._index) : false; + }, + + toString: function() { + var parts = [ 'point: ' + this._point ]; + if (!this._handleIn.isZero()) + parts.push('handleIn: ' + this._handleIn); + if (!this._handleOut.isZero()) + parts.push('handleOut: ' + this._handleOut); + return '{ ' + parts.join(', ') + ' }'; + }, + + _transformCoordinates: function(matrix, coords, change) { + var point = this._point, + handleIn = !change || !this._handleIn.isZero() + ? this._handleIn : null, + handleOut = !change || !this._handleOut.isZero() + ? this._handleOut : null, + x = point._x, + y = point._y, + i = 2; + coords[0] = x; + coords[1] = y; + if (handleIn) { + coords[i++] = handleIn._x + x; + coords[i++] = handleIn._y + y; + } + if (handleOut) { + coords[i++] = handleOut._x + x; + coords[i++] = handleOut._y + y; + } + if (!matrix) + return; + matrix._transformCoordinates(coords, 0, coords, 0, i / 2); + x = coords[0]; + y = coords[1]; + if (change) { + point._x = x; + point._y = y; + i = 2; + if (handleIn) { + handleIn._x = coords[i++] - x; + handleIn._y = coords[i++] - y; + } + if (handleOut) { + handleOut._x = coords[i++] - x; + handleOut._y = coords[i++] - y; + } + } else { + if (!handleIn) { + coords[i++] = x; + coords[i++] = y; + } + if (!handleOut) { + coords[i++] = x; + coords[i++] = y; + } + } + } +}); + +var SegmentPoint = Point.extend({ + set: function(x, y) { + this._x = x; + this._y = y; + this._owner._changed(this); + return this; + }, + + getX: function() { + return this._x; + }, + + setX: function(x) { + this._x = x; + this._owner._changed(this); + }, + + getY: function() { + return this._y; + }, + + setY: function(y) { + this._y = y; + this._owner._changed(this); + }, + + isZero: function() { + return this._x == 0 && this._y == 0; + }, + + setSelected: function(selected) { + this._owner._setSelected(this, selected); + }, + + isSelected: function() { + return this._owner._isSelected(this); + }, + + statics: { + create: function(segment, key, pt) { + var point = new SegmentPoint(SegmentPoint.dont), + x, y, selected; + if (!pt) { + x = y = 0; + } else if ((x = pt[0]) !== undefined) { + y = pt[1]; + } else { + if ((x = pt.x) === undefined) { + pt = Point.read(arguments, 2, 1); + x = pt.x; + } + y = pt.y; + selected = pt.selected; + } + point._x = x; + point._y = y; + point._owner = segment; + segment[key] = point; + if (selected) + point.setSelected(true); + return point; + } + } +}); + +var SelectionState = { + HANDLE_IN: 1, + HANDLE_OUT: 2, + POINT: 4 +}; + +var Curve = this.Curve = Base.extend({ + initialize: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + var count = arguments.length; + if (count == 0) { + this._segment1 = new Segment(); + this._segment2 = new Segment(); + } else if (count == 1) { + this._segment1 = new Segment(arg0.segment1); + this._segment2 = new Segment(arg0.segment2); + } else if (count == 2) { + this._segment1 = new Segment(arg0); + this._segment2 = new Segment(arg1); + } else if (count == 4) { + this._segment1 = new Segment(arg0, null, arg1); + this._segment2 = new Segment(arg3, arg2, null); + } else if (count == 8) { + var p1 = Point.create(arg0, arg1), + p2 = Point.create(arg6, arg7); + this._segment1 = new Segment(p1, null, + Point.create(arg2, arg3).subtract(p1)); + this._segment2 = new Segment(p2, + Point.create(arg4, arg5).subtract(p2), null); + } + }, + + _changed: function() { + delete this._length; + }, + + getPoint1: function() { + return this._segment1._point; + }, + + setPoint1: function(point) { + point = Point.read(arguments); + this._segment1._point.set(point.x, point.y); + }, + + getPoint2: function() { + return this._segment2._point; + }, + + setPoint2: function(point) { + point = Point.read(arguments); + this._segment2._point.set(point.x, point.y); + }, + + getHandle1: function() { + return this._segment1._handleOut; + }, + + setHandle1: function(point) { + point = Point.read(arguments); + this._segment1._handleOut.set(point.x, point.y); + }, + + getHandle2: function() { + return this._segment2._handleIn; + }, + + setHandle2: function(point) { + point = Point.read(arguments); + this._segment2._handleIn.set(point.x, point.y); + }, + + getSegment1: function() { + return this._segment1; + }, + + getSegment2: function() { + return this._segment2; + }, + + getPath: function() { + return this._path; + }, + + getIndex: function() { + return this._segment1._index; + }, + + getNext: function() { + var curves = this._path && this._path._curves; + return curves && (curves[this._segment1._index + 1] + || this._path._closed && curves[0]) || null; + }, + + getPrevious: function() { + var curves = this._path && this._path._curves; + return curves && (curves[this._segment1._index - 1] + || this._path._closed && curves[curves.length - 1]) || null; + }, + + isSelected: function() { + return this.getHandle1().isSelected() && this.getHandle2().isSelected(); + }, + + setSelected: function(selected) { + this.getHandle1().setSelected(selected); + this.getHandle2().setSelected(selected); + }, + + getValues: function(matrix) { + return Curve.getValues(this._segment1, this._segment2, matrix); + }, + + getPoints: function(matrix) { + var coords = this.getValues(matrix), + points = []; + for (var i = 0; i < 8; i += 2) + points.push(Point.create(coords[i], coords[i + 1])); + return points; + }, + + getLength: function() { + var from = arguments[0], + to = arguments[1]; + fullLength = arguments.length == 0 || from == 0 && to == 1; + if (fullLength && this._length != null) + return this._length; + var length = Curve.getLength(this.getValues(), from, to); + if (fullLength) + this._length = length; + return length; + }, + + getPart: function(from, to) { + return new Curve(Curve.getPart(this.getValues(), from, to)); + }, + + isLinear: function() { + return this._segment1._handleOut.isZero() + && this._segment2._handleIn.isZero(); + }, + + getParameterAt: function(offset, start) { + return Curve.getParameterAt(this.getValues(), offset, + start !== undefined ? start : offset < 0 ? 1 : 0); + }, + + getPoint: function(parameter) { + return Curve.evaluate(this.getValues(), parameter, 0); + }, + + getTangent: function(parameter) { + return Curve.evaluate(this.getValues(), parameter, 1); + }, + + getNormal: function(parameter) { + return Curve.evaluate(this.getValues(), parameter, 2); + }, + + getParameter: function(point) { + point = Point.read(point); + return Curve.getParameter(this.getValues(), point.x, point.y); + }, + + getCrossings: function(point, matrix, roots) { + var vals = this.getValues(matrix), + num = Curve.solveCubic(vals, 1, point.y, roots), + crossings = 0; + for (var i = 0; i < num; i++) { + var t = roots[i]; + if (t >= 0 && t < 1 && Curve.evaluate(vals, t, 0).x > point.x) { + if (t < Numerical.TOLERANCE && Curve.evaluate( + this.getPrevious().getValues(matrix), 1, 1).y + * Curve.evaluate(vals, t, 1).y >= 0) + continue; + crossings++; + } + } + return crossings; + }, + + reverse: function() { + return new Curve(this._segment2.reverse(), this._segment1.reverse()); + }, + + clone: function() { + return new Curve(this._segment1, this._segment2); + }, + + toString: function() { + var parts = [ 'point1: ' + this._segment1._point ]; + if (!this._segment1._handleOut.isZero()) + parts.push('handle1: ' + this._segment1._handleOut); + if (!this._segment2._handleIn.isZero()) + parts.push('handle2: ' + this._segment2._handleIn); + parts.push('point2: ' + this._segment2._point); + return '{ ' + parts.join(', ') + ' }'; + }, + + statics: { + create: function(path, segment1, segment2) { + var curve = new Curve(Curve.dont); + curve._path = path; + curve._segment1 = segment1; + curve._segment2 = segment2; + return curve; + }, + + getValues: function(segment1, segment2, matrix) { + var p1 = segment1._point, + h1 = segment1._handleOut, + h2 = segment2._handleIn, + p2 = segment2._point, + coords = [ + p1._x, p1._y, + p1._x + h1._x, p1._y + h1._y, + p2._x + h2._x, p2._y + h2._y, + p2._x, p2._y + ]; + return matrix + ? matrix._transformCoordinates(coords, 0, coords, 0, 4) + : coords; + }, + + 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], + x, y; + + if (type == 0 && (t == 0 || t == 1)) { + x = t == 0 ? p1x : p2x; + y = t == 0 ? p1y : p2y; + } else { + var tMin = Numerical.TOLERANCE; + if (t < tMin && c1x == p1x && c1y == p1y) + t = tMin; + else if (t > 1 - tMin && c2x == p2x && c2y == p2y) + t = 1 - tMin; + 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; + + switch (type) { + case 0: + x = ((ax * t + bx) * t + cx) * t + p1x; + y = ((ay * t + by) * t + cy) * t + p1y; + break; + case 1: + case 2: + x = (3 * ax * t + 2 * bx) * t + cx; + y = (3 * ay * t + 2 * by) * t + cy; + break; + } + } + 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], + c2x = v[4], c2y = v[5], + p2x = v[6], p2y = v[7]; + if (t === undefined) + t = 0.5; + var u = 1 - t, + p3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y, + p4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y, + p5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y, + p6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y, + p7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y, + p8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y; + return [ + [p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y], + [p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y] + ]; + }, + + solveCubic: function (v, coord, val, roots) { + var p1 = v[coord], + c1 = v[coord + 2], + c2 = v[coord + 4], + p2 = v[coord + 6], + c = 3 * (c1 - p1), + b = 3 * (c2 - c1) - c, + a = p2 - p1 - c - b; + return Numerical.solveCubic(a, b, c, p1 - val, roots, + Numerical.TOLERANCE); + }, + + getParameter: function(v, x, y) { + var txs = [], + tys = [], + sx = Curve.solveCubic(v, 0, x, txs), + sy = Curve.solveCubic(v, 1, y, tys), + 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; + if (Math.abs(tx - ty) < Numerical.TOLERANCE) + return (tx + ty) * 0.5; + } + } + if (sx == -1) + break; + } + } + return null; + }, + + getPart: function(v, from, to) { + if (from > 0) + v = Curve.subdivide(v, from)[1]; + if (to < 1) + v = Curve.subdivide(v, (to - from) / (1 - from))[0]; + return v; + }, + + isFlatEnough: function(v) { + 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], + + a = p1y - p2y, + b = p2x - p1x, + c = p1x * p2y - p2x * p1y, + v1 = a * c1x + b * c1y + c, + v2 = a * c2x + b * c2y + c; + return Math.abs((v1 * v1 + v2 * v2) / (a * (a * a + b * b))) < 0.005; + } + } +}, new function() { + + function getLengthIntegrand(v) { + 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], + + ax = 9 * (c1x - c2x) + 3 * (p2x - p1x), + bx = 6 * (p1x + c2x) - 12 * c1x, + cx = 3 * (c1x - p1x), + + ay = 9 * (c1y - c2y) + 3 * (p2y - p1y), + by = 6 * (p1y + c2y) - 12 * c1y, + cy = 3 * (c1y - p1y); + + return function(t) { + var dx = (ax * t + bx) * t + cx, + dy = (ay * t + by) * t + cy; + return Math.sqrt(dx * dx + dy * dy); + }; + } + + function getIterations(a, b) { + return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32))); + } + + return { + statics: true, + + getLength: function(v, a, b) { + if (a === undefined) + a = 0; + if (b === undefined) + b = 1; + if (v[0] == v[2] && v[1] == v[3] && v[6] == v[4] && v[7] == v[5]) { + var dx = v[6] - v[0], + dy = v[7] - v[1]; + return (b - a) * Math.sqrt(dx * dx + dy * dy); + } + var ds = getLengthIntegrand(v); + return Numerical.integrate(ds, a, b, getIterations(a, b)); + }, + + getParameterAt: function(v, offset, start) { + if (offset == 0) + return start; + var forward = offset > 0, + a = forward ? start : 0, + b = forward ? 1 : start, + offset = Math.abs(offset), + ds = getLengthIntegrand(v), + rangeLength = Numerical.integrate(ds, a, b, + getIterations(a, b)); + if (offset >= rangeLength) + return forward ? b : a; + var guess = offset / rangeLength, + length = 0; + function f(t) { + var count = getIterations(start, t); + length += start < t + ? Numerical.integrate(ds, start, t, count) + : -Numerical.integrate(ds, t, start, count); + start = t; + return length - offset; + } + return Numerical.findRoot(f, ds, + forward ? a + guess : b - guess, + a, b, 16, Numerical.TOLERANCE); + } + }; +}, new function() { + + var maxDepth = 32, + epsilon = Math.pow(2, -maxDepth - 1); + + var zCubic = [ + [1.0, 0.6, 0.3, 0.1], + [0.4, 0.6, 0.6, 0.4], + [0.1, 0.3, 0.6, 1.0] + ]; + + var xAxis = new Line(new Point(0, 0), new Point(1, 0)); + + function toBezierForm(v, point) { + var n = 3, + degree = 5, + c = [], + d = [], + cd = [], + w = []; + for(var i = 0; i <= n; i++) { + c[i] = v[i].subtract(point); + if (i < n) + d[i] = v[i + 1].subtract(v[i]).multiply(n); + } + + for (var row = 0; row < n; row++) { + cd[row] = []; + for (var column = 0; column <= n; column++) + cd[row][column] = d[row].dot(c[column]); + } + + for (var i = 0; i <= degree; i++) + w[i] = new Point(i / degree, 0); + + for (k = 0; k <= degree; k++) { + var lb = Math.max(0, k - n + 1), + ub = Math.min(k, n); + for (var i = lb; i <= ub; i++) { + var j = k - i; + w[k].y += cd[j][i] * zCubic[j][i]; + } + } + + return w; + } + + function findRoots(w, depth) { + switch (countCrossings(w)) { + case 0: + return []; + case 1: + if (depth >= maxDepth) + return [0.5 * (w[0].x + w[5].x)]; + if (isFlatEnough(w)) { + var line = new Line(w[0], w[5], true); + return [ line.vector.getLength(true) <= Numerical.EPSILON + ? line.point.x + : xAxis.intersect(line).x ]; + } + } + + var p = [[]], + left = [], + right = []; + for (var j = 0; j <= 5; j++) + p[0][j] = new Point(w[j]); + + for (var i = 1; i <= 5; i++) { + p[i] = []; + for (var j = 0 ; j <= 5 - i; j++) + p[i][j] = p[i - 1][j].add(p[i - 1][j + 1]).multiply(0.5); + } + for (var j = 0; j <= 5; j++) { + left[j] = p[j][0]; + right[j] = p[5 - j][j]; + } + + return findRoots(left, depth + 1).concat(findRoots(right, depth + 1)); + } + + function countCrossings(v) { + var crossings = 0, + prevSign = null; + for (var i = 0, l = v.length; i < l; i++) { + var sign = v[i].y < 0 ? -1 : 1; + if (prevSign != null && sign != prevSign) + crossings++; + prevSign = sign; + } + return crossings; + } + + function isFlatEnough(v) { + + var n = v.length - 1, + a = v[0].y - v[n].y, + b = v[n].x - v[0].x, + c = v[0].x * v[n].y - v[n].x * v[0].y, + maxAbove = 0, + maxBelow = 0; + for (var i = 1; i < n; i++) { + var val = a * v[i].x + b * v[i].y + c, + dist = val * val; + if (val < 0 && dist > maxBelow) { + maxBelow = dist; + } else if (dist > maxAbove) { + maxAbove = dist; + } + } + return Math.abs((maxAbove + maxBelow) / (2 * a * (a * a + b * b))) + < epsilon; + } + + return { + getNearestLocation: function(point, matrix) { + var w = toBezierForm(this.getPoints(matrix), point); + var roots = findRoots(w, 0).concat([0, 1]); + var minDist = Infinity, + minT, + minPoint; + for (var i = 0; i < roots.length; i++) { + var pt = this.getPoint(roots[i]), + dist = point.getDistance(pt, true); + if (dist < minDist) { + minDist = dist; + minT = roots[i]; + minPoint = pt; + } + } + return new CurveLocation(this, minT, minPoint, Math.sqrt(minDist)); + }, + + getNearestPoint: function(point, matrix) { + return this.getNearestLocation(point, matrix).getPoint(); + } + }; +}); + +CurveLocation = Base.extend({ + initialize: function(curve, parameter, point, distance) { + this._curve = curve; + this._parameter = parameter; + this._point = point; + this._distance = distance; + }, + + getSegment: function() { + if (!this._segment) { + var curve = this._curve, + parameter = this.getParameter(); + if (parameter == 0) { + this._segment = curve._segment1; + } else if (parameter == 1) { + this._segment = curve._segment2; + } else if (parameter == null) { + return null; + } else { + this._segment = curve.getLength(0, parameter) + < curve.getLength(parameter, 1) + ? curve._segment1 + : curve._segment2; + } + } + return this._segment; + }, + + getCurve: function() { + return this._curve; + }, + + getPath: function() { + return this._curve && this._curve._path; + }, + + getIndex: function() { + return this._curve && this._curve.getIndex(); + }, + + getOffset: function() { + var path = this._curve && this._curve._path; + return path && path._getOffset(this); + }, + + getCurveOffset: function() { + var parameter = this.getParameter(); + return parameter != null && this._curve + && this._curve.getLength(0, parameter); + }, + + getParameter: function() { + if (this._parameter == null && this._curve && this._point) + this._parameter = this._curve.getParameterAt(this._point); + return this._parameter; + }, + + getPoint: function() { + if (!this._point && this._curve && this._parameter != null) + this._point = this._curve.getPoint(this._parameter); + return this._point; + }, + + getTangent: function() { + var parameter = this.getParameter(); + return parameter != null && this._curve + && this._curve.getTangent(parameter); + }, + + getNormal: function() { + var parameter = this.getParameter(); + return parameter != null && this._curve + && this._curve.getNormal(parameter); + }, + + getDistance: function() { + return this._distance; + }, + + toString: function() { + var parts = [], + point = this.getPoint(); + if (point) + parts.push('point: ' + point); + var index = this.getIndex(); + if (index != null) + parts.push('index: ' + index); + var parameter = this.getParameter(); + if (parameter != null) + parts.push('parameter: ' + Base.formatNumber(parameter)); + if (this._distance != null) + parts.push('distance: ' + Base.formatNumber(this._distance)); + return '{ ' + parts.join(', ') + ' }'; + } +}); + +var PathItem = this.PathItem = Item.extend({ + +}); + +var Path = this.Path = PathItem.extend({ + initialize: function(segments) { + this.base(); + this._closed = false; + this._selectedSegmentState = 0; + this.setSegments(!segments || !Array.isArray(segments) + || typeof segments[0] !== 'object' ? arguments : segments); + }, + + clone: function() { + var copy = this._clone(new Path(this._segments)); + copy._closed = this._closed; + if (this._clockwise !== undefined) + copy._clockwise = this._clockwise; + return copy; + }, + + _changed: function(flags) { + Item.prototype._changed.call(this, flags); + if (flags & ChangeFlag.GEOMETRY) { + delete this._strokeBounds; + delete this._handleBounds; + delete this._roughBounds; + delete this._length; + delete this._clockwise; + } else if (flags & ChangeFlag.STROKE) { + delete this._strokeBounds; + } + }, + + getSegments: function() { + return this._segments; + }, + + setSegments: function(segments) { + if (!this._segments) { + this._segments = []; + } else { + this._selectedSegmentState = 0; + this._segments.length = 0; + if (this._curves) + delete this._curves; + } + this._add(Segment.readAll(segments)); + }, + + getFirstSegment: function() { + return this._segments[0]; + }, + + getLastSegment: function() { + return this._segments[this._segments.length - 1]; + }, + + getCurves: function() { + if (!this._curves) { + var segments = this._segments, + length = segments.length; + if (!this._closed && length > 0) + length--; + this._curves = new Array(length); + for (var i = 0; i < length; i++) + this._curves[i] = Curve.create(this, segments[i], + segments[i + 1] || segments[0]); + } + return this._curves; + }, + + getFirstCurve: function() { + return this.getCurves()[0]; + }, + + getLastCurve: function() { + var curves = this.getCurves(); + return curves[curves.length - 1]; + }, + + getClosed: function() { + return this._closed; + }, + + setClosed: function(closed) { + if (this._closed != (closed = !!closed)) { + this._closed = closed; + if (this._curves) { + var length = this._segments.length, + i; + if (!closed && length > 0) + length--; + this._curves.length = length; + if (closed) + this._curves[i = length - 1] = Curve.create(this, + this._segments[i], this._segments[0]); + } + this._changed(Change.GEOMETRY); + } + }, + + _transform: function(matrix, flags) { + if (!matrix.isIdentity()) { + var coords = new Array(6); + for (var i = 0, l = this._segments.length; i < l; i++) { + this._segments[i]._transformCoordinates(matrix, coords, true); + } + var fillColor = this.getFillColor(), + strokeColor = this.getStrokeColor(); + if (fillColor && fillColor.transform) + fillColor.transform(matrix); + if (strokeColor && strokeColor.transform) + strokeColor.transform(matrix); + } + }, + + _add: function(segs, index) { + var segments = this._segments, + curves = this._curves, + amount = segs.length, + append = index == null, + index = append ? segments.length : index, + fullySelected = this.isFullySelected(); + for (var i = 0; i < amount; i++) { + var segment = segs[i]; + if (segment._path) { + segment = segs[i] = new Segment(segment); + } + segment._path = this; + segment._index = index + i; + if (fullySelected) + segment._selectionState = SelectionState.POINT; + if (segment._selectionState) + this._updateSelection(segment, 0, segment._selectionState); + } + if (append) { + segments.push.apply(segments, segs); + } else { + segments.splice.apply(segments, [index, 0].concat(segs)); + for (var i = index + amount, l = segments.length; i < l; i++) { + segments[i]._index = i; + } + } + if (curves && --index >= 0) { + curves.splice(index, 0, Curve.create(this, segments[index], + segments[index + 1])); + var curve = curves[index + amount]; + if (curve) { + curve._segment1 = segments[index + amount]; + } + } + this._changed(Change.GEOMETRY); + return segs; + }, + + add: function(segment1 ) { + return arguments.length > 1 && typeof segment1 !== 'number' + ? this._add(Segment.readAll(arguments)) + : this._add([ Segment.read(arguments) ])[0]; + }, + + insert: function(index, segment1 ) { + return arguments.length > 2 && typeof segment1 !== 'number' + ? this._add(Segment.readAll(arguments, 1), index) + : this._add([ Segment.read(arguments, 1) ], index)[0]; + }, + + addSegment: function(segment) { + return this._add([ Segment.read(arguments) ])[0]; + }, + + insertSegment: function(index, segment) { + return this._add([ Segment.read(arguments, 1) ], index)[0]; + }, + + addSegments: function(segments) { + return this._add(Segment.readAll(segments)); + }, + + insertSegments: function(index, segments) { + return this._add(Segment.readAll(segments), index); + }, + + removeSegment: function(index) { + var segments = this.removeSegments(index, index + 1); + return segments[0] || null; + }, + + removeSegments: function(from, to) { + from = from || 0; + to = Base.pick(to, this._segments.length); + var segments = this._segments, + curves = this._curves, + last = to >= segments.length, + removed = segments.splice(from, to - from), + amount = removed.length; + if (!amount) + return removed; + for (var i = 0; i < amount; i++) { + var segment = removed[i]; + if (segment._selectionState) + this._updateSelection(segment, segment._selectionState, 0); + removed._index = removed._path = undefined; + } + for (var i = from, l = segments.length; i < l; i++) + segments[i]._index = i; + if (curves) { + curves.splice(from, amount); + var curve; + if (curve = curves[from - 1]) + curve._segment2 = segments[from]; + if (curve = curves[from]) + curve._segment1 = segments[from]; + if (last && this._closed && (curve = curves[curves.length - 1])) + curve._segment2 = segments[0]; + } + this._changed(Change.GEOMETRY); + return removed; + }, + + isFullySelected: function() { + return this._selected && this._selectedSegmentState + == this._segments.length * SelectionState.POINT; + }, + + setFullySelected: function(selected) { + var length = this._segments.length; + this._selectedSegmentState = selected + ? length * SelectionState.POINT : 0; + for (var i = 0; i < length; i++) + this._segments[i]._selectionState = selected + ? SelectionState.POINT : 0; + this.setSelected(selected); + }, + + _updateSelection: function(segment, oldState, newState) { + segment._selectionState = newState; + var total = this._selectedSegmentState += newState - oldState; + if (total > 0) + this.setSelected(true); + }, + + flatten: function(maxDistance) { + var flattener = new PathFlattener(this), + pos = 0, + step = flattener.length / Math.ceil(flattener.length / maxDistance), + end = flattener.length + (this._closed ? -step : step) / 2; + var segments = []; + while (pos <= end) { + segments.push(new Segment(flattener.evaluate(pos, 0))); + pos += step; + } + this.setSegments(segments); + }, + + simplify: function(tolerance) { + if (this._segments.length > 2) { + var fitter = new PathFitter(this, tolerance || 2.5); + this.setSegments(fitter.fit()); + } + }, + + isClockwise: function() { + if (this._clockwise !== undefined) + return this._clockwise; + var sum = 0, + xPre, yPre; + function edge(x, y) { + if (xPre !== undefined) + sum += (xPre - x) * (y + yPre); + xPre = x; + yPre = y; + } + for (var i = 0, l = this._segments.length; i < l; i++) { + var seg1 = this._segments[i], + seg2 = this._segments[i + 1 < l ? i + 1 : 0], + point1 = seg1._point, + handle1 = seg1._handleOut, + handle2 = seg2._handleIn, + point2 = seg2._point; + edge(point1._x, point1._y); + edge(point1._x + handle1._x, point1._y + handle1._y); + edge(point2._x + handle2._x, point2._y + handle2._y); + edge(point2._x, point2._y); + } + return sum > 0; + }, + + setClockwise: function(clockwise) { + if (this.isClockwise() != (clockwise = !!clockwise)) { + this.reverse(); + this._clockwise = clockwise; + } + }, + + reverse: function() { + this._segments.reverse(); + for (var i = 0, l = this._segments.length; i < l; i++) { + var segment = this._segments[i]; + var handleIn = segment._handleIn; + segment._handleIn = segment._handleOut; + segment._handleOut = handleIn; + } + if (this._clockwise !== undefined) + this._clockwise = !this._clockwise; + }, + + join: function(path) { + if (path) { + var segments = path._segments, + last1 = this.getLastSegment(), + last2 = path.getLastSegment(); + if (last1._point.equals(last2._point)) + path.reverse(); + var first2 = path.getFirstSegment(); + if (last1._point.equals(first2._point)) { + last1.setHandleOut(first2._handleOut); + this._add(segments.slice(1)); + } else { + var first1 = this.getFirstSegment(); + if (first1._point.equals(first2._point)) + path.reverse(); + last2 = path.getLastSegment(); + if (first1._point.equals(last2._point)) { + first1.setHandleIn(last2._handleIn); + this._add(segments.slice(0, segments.length - 1), 0); + } else { + this._add(segments.slice(0)); + } + } + path.remove(); + var first1 = this.getFirstSegment(); + last1 = this.getLastSegment(); + if (last1._point.equals(first1._point)) { + first1.setHandleIn(last1._handleIn); + last1.remove(); + this.setClosed(true); + } + this._changed(Change.GEOMETRY); + return true; + } + return false; + }, + + getLength: function() { + if (this._length == null) { + var curves = this.getCurves(); + this._length = 0; + for (var i = 0, l = curves.length; i < l; i++) + this._length += curves[i].getLength(); + } + return this._length; + }, + + _getOffset: function(location) { + var index = location && location.getIndex(); + if (index != null) { + var curves = this.getCurves(), + offset = 0; + for (var i = 0; i < index; i++) + offset += curves[i].getLength(); + var curve = curves[index]; + return offset + curve.getLength(0, location.getParameter()); + } + return null; + }, + + getLocation: function(point) { + var curves = this.getCurves(); + for (var i = 0, l = curves.length; i < l; i++) { + var curve = curves[i]; + var t = curve.getParameter(point); + if (t != null) + return new CurveLocation(curve, t); + } + return null; + }, + + getLocationAt: function(offset, isParameter) { + var curves = this.getCurves(), + length = 0; + if (isParameter) { + var index = ~~offset; + return new CurveLocation(curves[index], offset - index); + } + for (var i = 0, l = curves.length; i < l; i++) { + var start = length, + curve = curves[i]; + length += curve.getLength(); + if (length >= offset) { + return new CurveLocation(curve, + curve.getParameterAt(offset - start)); + } + } + if (offset <= this.getLength()) + return new CurveLocation(curves[curves.length - 1], 1); + return null; + }, + + getPointAt: function(offset, isParameter) { + var loc = this.getLocationAt(offset, isParameter); + return loc && loc.getPoint(); + }, + + getTangentAt: function(offset, isParameter) { + var loc = this.getLocationAt(offset, isParameter); + return loc && loc.getTangent(); + }, + + getNormalAt: function(offset, isParameter) { + var loc = this.getLocationAt(offset, isParameter); + return loc && loc.getNormal(); + }, + + getNearestLocation: function(point, matrix) { + var curves = this.getCurves(), + minDist = Infinity, + minLoc = null; + for (var i = 0, l = curves.length; i < l; i++) { + var loc = curves[i].getNearestLocation(point, matrix); + if (loc._distance < minDist) { + minDist = loc._distance; + minLoc = loc; + } + } + return minLoc; + }, + + getNearestPoint: function(point, matrix) { + return this.getNearestLocation(point, matrix).getPoint(); + }, + + contains: function(point, matrix) { + point = Point.read(arguments); + if (!this._closed || !this.getRoughBounds(matrix)._containsPoint(point)) + return false; + var curves = this.getCurves(), + crossings = 0, + roots = []; + for (var i = 0, l = curves.length; i < l; i++) + crossings += curves[i].getCrossings(point, matrix, roots); + return (crossings & 1) == 1; + }, + + _hitTest: function(point, options, matrix) { + var tolerance = options.tolerance || 0, + radius = (options.stroke ? this.getStrokeWidth() / 2 : 0) + tolerance, + loc, + res; + var coords = [], + that = this; + function checkSegment(segment, ends) { + segment._transformCoordinates(matrix, coords); + for (var j = ends || options.segments ? 0 : 2, + m = !ends && options.handles ? 6 : 2; j < m; j += 2) { + if (point.getDistance(coords[j], coords[j + 1]) < tolerance) + return new HitResult(j == 0 ? 'segment' + : 'handle-' + (j == 2 ? 'in' : 'out'), + that, { segment: segment }); + } + } + if (options.ends && !options.segments && !this._closed) { + if (res = checkSegment(this.getFirstSegment(), true) + || checkSegment(this.getLastSegment(), true)) + return res; + } else if (options.segments || options.handles) { + for (var i = 0, l = this._segments.length; i < l; i++) { + if (res = checkSegment(this._segments[i])) + return res; + } + } + if (options.stroke && radius > 0) + loc = this.getNearestLocation(point, matrix); + if (!(loc && loc._distance <= radius) && options.fill + && this.getFillColor() && this.contains(point, matrix)) + return new HitResult('fill', this); + if (!loc && options.stroke && radius > 0) + loc = this.getNearestLocation(point, matrix); + if (loc && loc._distance <= radius) + return options.stroke + ? new HitResult('stroke', this, { location: loc }) + : new HitResult('fill', this); + } + +}, new function() { + + function drawHandles(ctx, segments) { + for (var i = 0, l = segments.length; i < l; i++) { + var segment = segments[i], + point = segment._point, + state = segment._selectionState, + selected = state & SelectionState.POINT; + if (selected || (state & SelectionState.HANDLE_IN)) + drawHandle(ctx, point, segment._handleIn); + if (selected || (state & SelectionState.HANDLE_OUT)) + drawHandle(ctx, point, segment._handleOut); + ctx.save(); + ctx.beginPath(); + ctx.rect(point._x - 2, point._y - 2, 4, 4); + ctx.fill(); + if (!selected) { + ctx.beginPath(); + ctx.rect(point._x - 1, point._y - 1, 2, 2); + ctx.fillStyle = '#ffffff'; + ctx.fill(); + } + ctx.restore(); + } + } + + function drawHandle(ctx, point, handle) { + if (!handle.isZero()) { + var handleX = point._x + handle._x, + handleY = point._y + handle._y; + ctx.beginPath(); + ctx.moveTo(point._x, point._y); + ctx.lineTo(handleX, handleY); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(handleX, handleY, 1.75, 0, Math.PI * 2, true); + ctx.fill(); + } + } + + function drawSegments(ctx, path) { + var segments = path._segments, + length = segments.length, + handleOut, outX, outY; + + function drawSegment(i) { + var segment = segments[i], + point = segment._point, + x = point._x, + y = point._y, + handleIn = segment._handleIn; + if (!handleOut) { + ctx.moveTo(x, y); + } else { + if (handleIn.isZero() && handleOut.isZero()) { + ctx.lineTo(x, y); + } else { + ctx.bezierCurveTo(outX, outY, + handleIn._x + x, handleIn._y + y, x, y); + } + } + handleOut = segment._handleOut; + outX = handleOut._x + x; + outY = handleOut._y + y; + } + + for (var i = 0; i < length; i++) + drawSegment(i); + if (path._closed && length > 1) + drawSegment(0); + } + + function drawDashes(ctx, path, dashArray, dashOffset) { + var flattener = new PathFlattener(path), + from = dashOffset, to, + i = 0; + while (from < flattener.length) { + to = from + dashArray[(i++) % dashArray.length]; + flattener.drawPart(ctx, from, to); + from = to + dashArray[(i++) % dashArray.length]; + } + } + + return { + draw: function(ctx, param) { + if (!param.compound) + ctx.beginPath(); + + var fillColor = this.getFillColor(), + strokeColor = this.getStrokeColor(), + dashArray = this.getDashArray() || [], + hasDash = !!dashArray.length; + + if (param.compound || param.selection || this._clipMask || fillColor + || strokeColor && !hasDash) { + drawSegments(ctx, this); + } + + if (param.selection) { + ctx.stroke(); + drawHandles(ctx, this._segments); + } else if (this._clipMask) { + ctx.clip(); + } else if (!param.compound && (fillColor || strokeColor)) { + ctx.save(); + this._setStyles(ctx); + if (!fillColor || !strokeColor) + ctx.globalAlpha = this._opacity; + if (fillColor) { + ctx.fillStyle = fillColor.getCanvasStyle(ctx); + ctx.fill(); + } + if (strokeColor) { + ctx.strokeStyle = strokeColor.getCanvasStyle(ctx); + if (hasDash) { + ctx.beginPath(); + drawDashes(ctx, this, dashArray, this.getDashOffset()); + } + ctx.stroke(); + } + ctx.restore(); + } + } + }; +}, new function() { + + function getFirstControlPoints(rhs) { + var n = rhs.length, + x = [], + tmp = [], + b = 2; + x[0] = rhs[0] / b; + for (var i = 1; i < n; i++) { + tmp[i] = 1 / b; + b = (i < n - 1 ? 4 : 2) - tmp[i]; + x[i] = (rhs[i] - x[i - 1]) / b; + } + for (var i = 1; i < n; i++) { + x[n - i - 1] -= tmp[n - i] * x[n - i]; + } + return x; + }; + + var styles = { + getStrokeWidth: 'lineWidth', + getStrokeJoin: 'lineJoin', + getStrokeCap: 'lineCap', + getMiterLimit: 'miterLimit' + }; + + return { + _setStyles: function(ctx) { + for (var i in styles) { + var style = this._style[i](); + if (style) + ctx[styles[i]] = style; + } + }, + + smooth: function() { + var segments = this._segments, + size = segments.length, + n = size, + overlap; + + if (size <= 2) + return; + + if (this._closed) { + overlap = Math.min(size, 4); + n += Math.min(size, overlap) * 2; + } else { + overlap = 0; + } + var knots = []; + for (var i = 0; i < size; i++) + knots[i + overlap] = segments[i]._point; + if (this._closed) { + for (var i = 0; i < overlap; i++) { + knots[i] = segments[i + size - overlap]._point; + knots[i + size + overlap] = segments[i]._point; + } + } else { + n--; + } + var rhs = []; + + for (var i = 1; i < n - 1; i++) + rhs[i] = 4 * knots[i]._x + 2 * knots[i + 1]._x; + rhs[0] = knots[0]._x + 2 * knots[1]._x; + rhs[n - 1] = 3 * knots[n - 1]._x; + var x = getFirstControlPoints(rhs); + + for (var i = 1; i < n - 1; i++) + rhs[i] = 4 * knots[i]._y + 2 * knots[i + 1]._y; + rhs[0] = knots[0]._y + 2 * knots[1]._y; + rhs[n - 1] = 3 * knots[n - 1]._y; + var y = getFirstControlPoints(rhs); + + if (this._closed) { + for (var i = 0, j = size; i < overlap; i++, j++) { + var f1 = (i / overlap); + var f2 = 1 - f1; + x[j] = x[i] * f1 + x[j] * f2; + y[j] = y[i] * f1 + y[j] * f2; + var ie = i + overlap, je = j + overlap; + x[je] = x[ie] * f2 + x[je] * f1; + y[je] = y[ie] * f2 + y[je] * f1; + } + n--; + } + var handleIn = null; + for (var i = overlap; i <= n - overlap; i++) { + var segment = segments[i - overlap]; + if (handleIn) + segment.setHandleIn(handleIn.subtract(segment._point)); + if (i < n) { + segment.setHandleOut( + new Point(x[i], y[i]).subtract(segment._point)); + if (i < n - 1) + handleIn = new Point( + 2 * knots[i + 1]._x - x[i + 1], + 2 * knots[i + 1]._y - y[i + 1]); + else + handleIn = new Point( + (knots[n]._x + x[n - 1]) / 2, + (knots[n]._y + y[n - 1]) / 2); + } + } + if (this._closed && handleIn) { + var segment = this._segments[0]; + segment.setHandleIn(handleIn.subtract(segment._point)); + } + } + }; +}, new function() { + function getCurrentSegment(that) { + var segments = that._segments; + if (segments.length == 0) + throw new Error('Use a moveTo() command first'); + return segments[segments.length - 1]; + } + + return { + moveTo: function(point) { + if (!this._segments.length) + this._add([ new Segment(Point.read(arguments)) ]); + }, + + moveBy: function(point) { + throw new Error('moveBy() is unsupported on Path items.'); + }, + + lineTo: function(point) { + this._add([ new Segment(Point.read(arguments)) ]); + }, + + cubicCurveTo: function(handle1, handle2, to) { + handle1 = Point.read(arguments, 0, 1); + handle2 = Point.read(arguments, 1, 1); + to = Point.read(arguments, 2, 1); + var current = getCurrentSegment(this); + current.setHandleOut(handle1.subtract(current._point)); + this._add([ new Segment(to, handle2.subtract(to)) ]); + }, + + quadraticCurveTo: function(handle, to) { + handle = Point.read(arguments, 0, 1); + to = Point.read(arguments, 1, 1); + var current = getCurrentSegment(this)._point; + this.cubicCurveTo( + handle.add(current.subtract(handle).multiply(1/3)), + handle.add(to.subtract(handle).multiply(1/3)), + to + ); + }, + + curveTo: function(through, to, parameter) { + through = Point.read(arguments, 0, 1); + to = Point.read(arguments, 1, 1); + var t = Base.pick(parameter, 0.5), + t1 = 1 - t, + current = getCurrentSegment(this)._point, + handle = through.subtract(current.multiply(t1 * t1)) + .subtract(to.multiply(t * t)).divide(2 * t * t1); + if (handle.isNaN()) + throw new Error( + 'Cannot put a curve through points with parameter = ' + t); + this.quadraticCurveTo(handle, to); + }, + + arcTo: function(to, clockwise ) { + var current = getCurrentSegment(this), + from = current._point, + through; + if (clockwise === undefined) + clockwise = true; + if (typeof clockwise === 'boolean') { + to = Point.read(arguments, 0, 1); + var middle = from.add(to).divide(2), + through = middle.add(middle.subtract(from).rotate( + clockwise ? -90 : 90)); + } else { + through = Point.read(arguments, 0, 1); + to = Point.read(arguments, 1, 1); + } + var l1 = new Line(from.add(through).divide(2), + through.subtract(from).rotate(90)), + l2 = new Line(through.add(to).divide(2), + to.subtract(through).rotate(90)), + center = l1.intersect(l2), + line = new Line(from, to, true), + throughSide = line.getSide(through); + if (!center) { + if (!throughSide) + return this.lineTo(to); + throw new Error("Cannot put an arc through the given points: " + + [from, through, to]); + } + var vector = from.subtract(center), + radius = vector.getLength(), + extent = vector.getDirectedAngle(to.subtract(center)), + centerSide = line.getSide(center); + if (centerSide == 0) { + extent = throughSide * Math.abs(extent); + } else if (throughSide == centerSide) { + extent -= 360 * (extent < 0 ? -1 : 1); + } + var ext = Math.abs(extent), + count = ext >= 360 ? 4 : Math.ceil(ext / 90), + inc = extent / count, + half = inc * Math.PI / 360, + z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)), + segments = []; + for (var i = 0; i <= count; i++) { + var pt = i < count ? center.add(vector) : to; + var out = i < count ? vector.rotate(90).multiply(z) : null; + if (i == 0) { + current.setHandleOut(out); + } else { + segments.push( + new Segment(pt, vector.rotate(-90).multiply(z), out)); + } + vector = vector.rotate(inc); + } + this._add(segments); + }, + + lineBy: function(vector) { + vector = Point.read(arguments); + var current = getCurrentSegment(this); + this.lineTo(current._point.add(vector)); + }, + + curveBy: function(throughVector, toVector, parameter) { + throughVector = Point.read(throughVector); + toVector = Point.read(toVector); + var current = getCurrentSegment(this)._point; + this.curveTo(current.add(throughVector), current.add(toVector), + parameter); + }, + + arcBy: function(throughVector, toVector) { + throughVector = Point.read(throughVector); + toVector = Point.read(toVector); + var current = getCurrentSegment(this)._point; + this.arcBy(current.add(throughVector), current.add(toVector)); + }, + + closePath: function() { + this.setClosed(true); + } + }; +}, new function() { + + function getBounds(that, matrix, strokePadding) { + var segments = that._segments, + first = segments[0]; + if (!first) + return null; + var coords = new Array(6), + prevCoords = new Array(6); + if (matrix && matrix.isIdentity()) + matrix = null; + first._transformCoordinates(matrix, prevCoords, false); + var min = prevCoords.slice(0, 2), + max = min.slice(0), + tMin = Numerical.TOLERANCE, + tMax = 1 - tMin; + function processSegment(segment) { + segment._transformCoordinates(matrix, coords, false); + + for (var i = 0; i < 2; i++) { + var v0 = prevCoords[i], + v1 = prevCoords[i + 4], + v2 = coords[i + 2], + v3 = coords[i]; + + function add(value, t) { + var padding = 0; + if (value == null) { + var u = 1 - t; + value = u * u * u * v0 + + 3 * u * u * t * v1 + + 3 * u * t * t * v2 + + t * t * t * v3; + padding = strokePadding ? strokePadding[i] : 0; + } + var left = value - padding, + right = value + padding; + if (left < min[i]) + min[i] = left; + if (right > max[i]) + max[i] = right; + + } + add(v3, null); + + var a = 3 * (v1 - v2) - v0 + v3, + b = 2 * (v0 + v2) - 4 * v1, + c = v1 - v0; + + if (a == 0) { + if (b == 0) + continue; + var t = -c / b; + if (tMin < t && t < tMax) + add(null, t); + continue; + } + + var q = b * b - 4 * a * c; + if (q < 0) + continue; + var sqrt = Math.sqrt(q), + f = -0.5 / a, + t1 = (b - sqrt) * f, + t2 = (b + sqrt) * f; + if (tMin < t1 && t1 < tMax) + add(null, t1); + if (tMin < t2 && t2 < tMax) + add(null, t2); + } + var tmp = prevCoords; + prevCoords = coords; + coords = tmp; + } + for (var i = 1, l = segments.length; i < l; i++) + processSegment(segments[i]); + if (that._closed) + processSegment(first); + return Rectangle.create(min[0], min[1], + max[0] - min[0], max[1] - min[1]); + } + + function getPenPadding(radius, matrix) { + if (!matrix) + return [radius, radius]; + var mx = matrix.createShiftless(), + hor = mx.transform(new Point(radius, 0)), + ver = mx.transform(new Point(0, radius)), + phi = hor.getAngleInRadians(), + a = hor.getLength(), + b = ver.getLength(); + var tx = - Math.atan(b * Math.tan(phi)), + ty = + Math.atan(b / Math.tan(phi)), + x = a * Math.cos(tx) * Math.cos(phi) + - b * Math.sin(tx) * Math.sin(phi), + y = b * Math.sin(ty) * Math.cos(phi) + + a * Math.cos(ty) * Math.sin(phi); + return [Math.abs(x), Math.abs(y)]; + } + + return { + getBounds: function() { + var useCache = arguments[0] === undefined; + if (useCache && this._bounds) + return this._bounds; + var bounds = this._createBounds(getBounds(this, arguments[0])); + if (useCache) + this._bounds = bounds; + return bounds; + }, + + getStrokeBounds: function() { + if (!this._style._strokeColor || !this._style._strokeWidth) + return this.getBounds.apply(this, arguments); + var useCache = arguments[0] === undefined; + if (useCache && this._strokeBounds) + return this._strokeBounds; + var matrix = arguments[0], + width = this.getStrokeWidth(), + radius = width / 2, + padding = getPenPadding(radius, matrix), + join = this.getStrokeJoin(), + cap = this.getStrokeCap(), + miter = this.getMiterLimit() * width / 2, + segments = this._segments, + length = segments.length, + bounds = getBounds(this, matrix, getPenPadding(radius)); + var joinBounds = new Rectangle(new Size(padding).multiply(2)); + + function add(point) { + bounds = bounds.include(matrix + ? matrix.transform(point) : point); + } + + function addBevelJoin(curve, t) { + var point = curve.getPoint(t), + normal = curve.getNormal(t).normalize(radius); + add(point.add(normal)); + add(point.subtract(normal)); + } + + function addJoin(segment, join) { + if (join === 'round' || !segment._handleIn.isZero() + && !segment._handleOut.isZero()) { + bounds = bounds.unite(joinBounds.setCenter(matrix + ? matrix.transform(segment._point) : segment._point)); + } else if (join == 'bevel') { + var curve = segment.getCurve(); + addBevelJoin(curve, 0); + addBevelJoin(curve.getPrevious(), 1); + } else if (join == 'miter') { + var curve2 = segment.getCurve(), + curve1 = curve2.getPrevious(), + point = curve2.getPoint(0), + normal1 = curve1.getNormal(1).normalize(radius), + normal2 = curve2.getNormal(0).normalize(radius), + line1 = new Line(point.subtract(normal1), + new Point(-normal1.y, normal1.x)), + line2 = new Line(point.subtract(normal2), + new Point(-normal2.y, normal2.x)), + corner = line1.intersect(line2); + if (!corner || point.getDistance(corner) > miter) { + addJoin(segment, 'bevel'); + } else { + add(corner); + } + } + } + + function addCap(segment, cap, t) { + switch (cap) { + case 'round': + return addJoin(segment, cap); + case 'butt': + case 'square': + var curve = segment.getCurve(), + point = curve.getPoint(t), + normal = curve.getNormal(t).normalize(radius); + if (cap === 'square') + point = point.add(normal.y, -normal.x); + add(point.add(normal)); + add(point.subtract(normal)); + break; + } + } + + for (var i = 1, l = length - (this._closed ? 0 : 1); i < l; i++) { + addJoin(segments[i], join); + } + if (this._closed) { + addJoin(segments[0], join); + } else { + addCap(segments[0], cap, 0); + addCap(segments[length - 1], cap, 1); + } + if (useCache) + this._strokeBounds = bounds; + return bounds; + }, + + getHandleBounds: function() { + var matrix = arguments[0], + useCache = matrix === undefined; + if (useCache && this._handleBounds) + return this._handleBounds; + var coords = new Array(6), + stroke = arguments[1] / 2 || 0, + join = arguments[2] / 2 || 0, + open = !this._closed, + x1 = Infinity, + x2 = -x1, + y1 = x1, + y2 = x2; + for (var i = 0, l = this._segments.length; i < l; i++) { + var segment = this._segments[i]; + segment._transformCoordinates(matrix, coords, false); + for (var j = 0; j < 6; j += 2) { + var padding = j == 0 ? join : stroke, + x = coords[j], + y = coords[j + 1], + xn = x - padding, + xx = x + padding, + yn = y - padding, + yx = y + padding; + if (xn < x1) x1 = xn; + if (xx > x2) x2 = xx; + if (yn < y1) y1 = yn; + if (yx > y2) y2 = yx; + } + } + var bounds = Rectangle.create(x1, y1, x2 - x1, y2 - y1); + if (useCache) + this._handleBounds = bounds; + return bounds; + }, + + getRoughBounds: function() { + var useCache = arguments[0] === undefined; + if (useCache && this._roughBounds) + return this._roughBounds; + var bounds = this.getHandleBounds(arguments[0], this.strokeWidth, + this.getStrokeJoin() == 'miter' + ? this.strokeWidth * this.getMiterLimit() + : this.strokeWidth); + if (useCache) + this._roughBounds = bounds; + return bounds; + } + }; +}); + +Path.inject({ statics: new function() { + var kappa = 2 / 3 * (Math.sqrt(2) - 1); + + var ovalSegments = [ + new Segment([0, 0.5], [0, kappa ], [0, -kappa]), + new Segment([0.5, 0], [-kappa, 0], [kappa, 0 ]), + new Segment([1, 0.5], [0, -kappa], [0, kappa ]), + new Segment([0.5, 1], [kappa, 0 ], [-kappa, 0]) + ]; + + return { + Line: function() { + var step = Math.floor(arguments.length / 2); + return new Path( + Segment.read(arguments, 0, step), + Segment.read(arguments, step, step) + ); + }, + + Rectangle: function(rect) { + rect = Rectangle.read(arguments); + var left = rect.x, + top = rect.y + right = left + rect.width, + bottom = top + rect.height, + path = new Path(); + path._add([ + new Segment(Point.create(left, bottom)), + new Segment(Point.create(left, top)), + new Segment(Point.create(right, top)), + new Segment(Point.create(right, bottom)) + ]); + path._closed = true; + return path; + }, + + RoundRectangle: function(rect, size) { + if (arguments.length == 2) { + rect = Rectangle.read(arguments, 0, 1); + size = Size.read(arguments, 1, 1); + } else if (arguments.length == 6) { + rect = Rectangle.read(arguments, 0, 4); + size = Size.read(arguments, 4, 2); + } + size = Size.min(size, rect.getSize(true).divide(2)); + var path = new Path(), + uSize = size.multiply(kappa * 2), + bl = rect.getBottomLeft(true), + tl = rect.getTopLeft(true), + tr = rect.getTopRight(true), + br = rect.getBottomRight(true); + path._add([ + new Segment(bl.add(size.width, 0), null, [-uSize.width, 0]), + new Segment(bl.subtract(0, size.height), [0, uSize.height], null), + + new Segment(tl.add(0, size.height), null, [0, -uSize.height]), + new Segment(tl.add(size.width, 0), [-uSize.width, 0], null), + + new Segment(tr.subtract(size.width, 0), null, [uSize.width, 0]), + new Segment(tr.add(0, size.height), [0, -uSize.height], null), + + new Segment(br.subtract(0, size.height), null, [0, uSize.height]), + new Segment(br.subtract(size.width, 0), [uSize.width, 0], null) + ]); + path._closed = true; + return path; + }, + + Oval: function(rect) { + rect = Rectangle.read(arguments); + var path = new Path(), + point = rect.getPoint(true), + size = rect.getSize(true), + segments = new Array(4); + for (var i = 0; i < 4; i++) { + var segment = ovalSegments[i]; + segments[i] = new Segment( + segment._point.multiply(size).add(point), + segment._handleIn.multiply(size), + segment._handleOut.multiply(size) + ); + } + path._add(segments); + path._closed = true; + return path; + }, + + Circle: function(center, radius) { + if (arguments.length == 3) { + center = Point.read(arguments, 0, 2); + radius = arguments[2]; + } else { + center = Point.read(arguments, 0, 1); + } + return Path.Oval(new Rectangle(center.subtract(radius), + Size.create(radius * 2, radius * 2))); + }, + + Arc: function(from, through, to) { + var path = new Path(); + path.moveTo(from); + path.arcTo(through, to); + return path; + }, + + RegularPolygon: function(center, numSides, radius) { + center = Point.read(arguments, 0, 1); + var path = new Path(), + step = 360 / numSides, + three = !(numSides % 3), + vector = new Point(0, three ? -radius : radius), + offset = three ? -1 : 0.5, + segments = new Array(numSides); + for (var i = 0; i < numSides; i++) { + segments[i] = new Segment(center.add( + vector.rotate((i + offset) * step))); + } + path._add(segments); + path._closed = true; + return path; + }, + + Star: function(center, numPoints, radius1, radius2) { + center = Point.read(arguments, 0, 1); + numPoints *= 2; + var path = new Path(), + step = 360 / numPoints, + vector = new Point(0, -1), + segments = new Array(numPoints); + for (var i = 0; i < numPoints; i++) { + segments[i] = new Segment(center.add( + vector.rotate(step * i).multiply(i % 2 ? radius2 : radius1))); + } + path._add(segments); + path._closed = true; + return path; + } + }; +}}); + +var CompoundPath = this.CompoundPath = PathItem.extend({ + initialize: function(paths) { + this.base(); + this._children = []; + this._namedChildren = {}; + var items = !paths || !Array.isArray(paths) + || typeof paths[0] !== 'object' ? arguments : paths; + this.addChildren(items); + }, + + insertChild: function(index, item) { + this.base(index, item); + if (item._clockwise === undefined) + item.setClockwise(item._index == 0); + }, + + simplify: function() { + if (this._children.length == 1) { + var child = this._children[0]; + child.insertAbove(this); + this.remove(); + return child; + } + return this; + }, + + smooth: function() { + for (var i = 0, l = this._children.length; i < l; i++) + this._children[i].smooth(); + }, + + draw: function(ctx, param) { + var l = this._children.length; + if (l == 0) { + return; + } + var firstChild = this._children[0]; + ctx.beginPath(); + param.compound = true; + for (var i = 0; i < l; i++) + Item.draw(this._children[i], ctx, param); + firstChild._setStyles(ctx); + var fillColor = firstChild.getFillColor(), + strokeColor = firstChild.getStrokeColor(); + if (fillColor) { + ctx.fillStyle = fillColor.getCanvasStyle(ctx); + ctx.fill(); + } + if (strokeColor) { + ctx.strokeStyle = strokeColor.getCanvasStyle(ctx); + ctx.stroke(); + } + param.compound = false; + } +}, new function() { + function getCurrentPath(that) { + if (!that._children.length) + throw new Error('Use a moveTo() command first'); + return that._children[that._children.length - 1]; + } + + var fields = { + moveTo: function(point) { + var path = new Path(); + this.addChild(path); + path.moveTo.apply(path, arguments); + }, + + moveBy: function(point) { + this.moveTo(getCurrentPath(this).getLastSegment()._point.add( + Point.read(arguments))); + }, + + closePath: function() { + getCurrentPath(this).setClosed(true); + } + }; + + Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', + 'arcTo', 'lineBy', 'curveBy', 'arcBy'], function(key) { + fields[key] = function() { + var path = getCurrentPath(this); + path[key].apply(path, arguments); + }; + }); + + return fields; +}); + +var PathFlattener = Base.extend({ + initialize: function(path) { + this.curves = []; + this.parts = []; + this.length = 0; + this.index = 0; + + var segments = path._segments, + segment1 = segments[0], + segment2, + that = this; + + function addCurve(segment1, segment2) { + var curve = Curve.getValues(segment1, segment2); + that.curves.push(curve); + that._computeParts(curve, segment1._index, 0, 1); + } + + for (var i = 1, l = segments.length; i < l; i++) { + segment2 = segments[i]; + addCurve(segment1, segment2); + segment1 = segment2; + } + if (path._closed) + addCurve(segment2, segments[0]); + }, + + _computeParts: function(curve, index, minT, maxT) { + if ((maxT - minT) > 1 / 32 && !Curve.isFlatEnough(curve)) { + var curves = Curve.subdivide(curve); + var halfT = (minT + maxT) / 2; + this._computeParts(curves[0], index, minT, halfT); + this._computeParts(curves[1], index, halfT, maxT); + } else { + var x = curve[6] - curve[0], + y = curve[7] - curve[1], + dist = Math.sqrt(x * x + y * y); + if (dist > Numerical.TOLERANCE) { + this.length += dist; + this.parts.push({ + offset: this.length, + value: maxT, + index: index + }); + } + } + }, + + getParameterAt: function(offset) { + var i, j = this.index; + for (;;) { + i = j; + if (j == 0 || this.parts[--j].offset < offset) + break; + } + for (var l = this.parts.length; i < l; i++) { + var part = this.parts[i]; + if (part.offset >= offset) { + this.index = i; + var prev = this.parts[i - 1]; + var prevVal = prev && prev.index == part.index ? prev.value : 0, + prevLen = prev ? prev.offset : 0; + return { + value: prevVal + (part.value - prevVal) + * (offset - prevLen) / (part.offset - prevLen), + index: part.index + }; + } + } + var part = this.parts[this.parts.length - 1]; + return { + value: 1, + index: part.index + }; + }, + + 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); + for (var i = from.index; i <= to.index; i++) { + var curve = Curve.getPart(this.curves[i], + i == from.index ? from.value : 0, + i == to.index ? to.value : 1); + if (i == from.index) + ctx.moveTo(curve[0], curve[1]); + ctx.bezierCurveTo.apply(ctx, curve.slice(2)); + } + } +}); + +var PathFitter = Base.extend({ + initialize: function(path, error) { + this.points = []; + var segments = path._segments, + prev; + for (var i = 0, l = segments.length; i < l; i++) { + var point = segments[i].point.clone(); + if (!prev || !prev.equals(point)) { + this.points.push(point); + prev = point; + } + } + this.error = error; + }, + + fit: function() { + this.segments = [new Segment(this.points[0])]; + this.fitCubic(0, this.points.length - 1, + this.points[1].subtract(this.points[0]).normalize(), + this.points[this.points.length - 2].subtract( + this.points[this.points.length - 1]).normalize()); + return this.segments; + }, + + fitCubic: function(first, last, tan1, tan2) { + if (last - first == 1) { + var pt1 = this.points[first], + pt2 = this.points[last], + dist = pt1.getDistance(pt2) / 3; + this.addCurve([pt1, pt1.add(tan1.normalize(dist)), + pt2.add(tan2.normalize(dist)), pt2]); + return; + } + var uPrime = this.chordLengthParameterize(first, last), + maxError = Math.max(this.error, this.error * this.error), + error, + split; + 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) { + this.addCurve(curve); + return; + } + split = max.index; + if (max.error >= maxError) + break; + this.reparameterize(first, last, uPrime, curve); + maxError = max.error; + } + var V1 = this.points[split - 1].subtract(this.points[split]), + V2 = this.points[split].subtract(this.points[split + 1]), + tanCenter = V1.add(V2).divide(2).normalize(); + this.fitCubic(first, split, tan1, tanCenter); + this.fitCubic(split, last, tanCenter.negate(), tan2); + }, + + addCurve: function(curve) { + var prev = this.segments[this.segments.length - 1]; + prev.setHandleOut(curve[1].subtract(curve[0])); + this.segments.push( + new Segment(curve[3], curve[2].subtract(curve[3]))); + }, + + generateBezier: function(first, last, uPrime, tan1, tan2) { + var epsilon = Numerical.EPSILON, + pt1 = this.points[first], + pt2 = this.points[last], + C = [[0, 0], [0, 0]], + X = [0, 0]; + + for (var i = 0, l = last - first + 1; i < l; i++) { + var u = uPrime[i], + t = 1 - u, + b = 3 * u * t, + b0 = t * t * t, + b1 = b * t, + b2 = b * u, + b3 = u * u * u, + a1 = tan1.normalize(b1), + a2 = tan2.normalize(b2), + tmp = this.points[first + i] + .subtract(pt1.multiply(b0 + b1)) + .subtract(pt2.multiply(b2 + b3)); + C[0][0] += a1.dot(a1); + C[0][1] += a1.dot(a2); + C[1][0] = C[0][1]; + C[1][1] += a2.dot(a2); + X[0] += a1.dot(tmp); + X[1] += a2.dot(tmp); + } + + var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1], + alpha1, alpha2; + if (Math.abs(detC0C1) > epsilon) { + var detC0X = C[0][0] * X[1] - C[1][0] * X[0], + detXC1 = X[0] * C[1][1] - X[1] * C[0][1]; + alpha1 = detXC1 / detC0C1; + alpha2 = detC0X / detC0C1; + } else { + var c0 = C[0][0] + C[0][1], + c1 = C[1][0] + C[1][1]; + if (Math.abs(c0) > epsilon) { + alpha1 = alpha2 = X[0] / c0; + } else if (Math.abs(c0) > epsilon) { + alpha1 = alpha2 = X[1] / c1; + } else { + alpha1 = alpha2 = 0.; + } + } + + var segLength = pt2.getDistance(pt1); + epsilon *= segLength; + if (alpha1 < epsilon || alpha2 < epsilon) { + alpha1 = alpha2 = segLength / 3; + } + + return [pt1, pt1.add(tan1.normalize(alpha1)), + pt2.add(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]); + } + }, + + findRoot: function(curve, point, u) { + var curve1 = [], + curve2 = []; + for (var i = 0; i <= 2; i++) { + curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3); + } + for (var i = 0; i <= 1; i++) { + curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2); + } + var pt = this.evaluate(3, curve, u), + pt1 = this.evaluate(2, curve1, u), + pt2 = this.evaluate(1, curve2, u), + diff = pt.subtract(point), + df = pt1.dot(pt1) + diff.dot(pt2); + if (Math.abs(df) < Numerical.TOLERANCE) + return u; + return u - diff.dot(pt1) / df; + }, + + evaluate: function(degree, curve, t) { + var tmp = curve.slice(); + for (var i = 1; i <= degree; i++) { + for (var j = 0; j <= degree - i; j++) { + tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t)); + } + } + return tmp[0]; + }, + + chordLengthParameterize: function(first, last) { + var u = [0]; + for (var i = first + 1; i <= last; i++) { + u[i - first] = u[i - first - 1] + + this.points[i].getDistance(this.points[i - 1]); + } + for (var i = 1, m = last - first; i <= m; i++) { + u[i] /= u[m]; + } + return u; + }, + + findMaxError: function(first, last, curve, u) { + var index = Math.floor((last - first + 1) / 2), + maxDist = 0; + for (var i = first + 1; i < last; i++) { + var P = this.evaluate(3, curve, u[i - first]); + var v = P.subtract(this.points[i]); + var dist = v.x * v.x + v.y * v.y; + if (dist >= maxDist) { + maxDist = dist; + index = i; + } + } + return { + error: maxDist, + index: index + }; + } +}); + +var TextItem = this.TextItem = Item.extend({ + initialize: function() { + this.base(); + this._content = ''; + this._characterStyle = CharacterStyle.create(this); + this.setCharacterStyle(this._project.getCurrentStyle()); + this._paragraphStyle = ParagraphStyle.create(this); + this.setParagraphStyle(); + }, + + _clone: function(copy) { + copy._content = this._content; + copy.setCharacterStyle(this._characterStyle); + copy.setParagraphStyle(this._paragraphStyle); + return this.base(copy); + }, + + getContent: function() { + return this._content; + }, + + setContent: function(content) { + this._changed(Change.CONTENT); + this._content = '' + content; + }, + + getCharacterStyle: function() { + return this._characterStyle; + }, + + setCharacterStyle: function(style) { + this._characterStyle.initialize(style); + }, + + getParagraphStyle: function() { + return this._paragraphStyle; + }, + + setParagraphStyle: function(style) { + this._paragraphStyle.initialize(style); + } +}); + +var PointText = this.PointText = TextItem.extend({ + initialize: function(point) { + this.base(); + this._point = Point.read(arguments).clone(); + this._matrix = new Matrix().translate(this._point); + }, + + clone: function() { + var copy = this._clone(new PointText(this._point)); + copy._matrix.initialize(this._matrix); + return copy; + }, + + getPoint: function() { + return LinkedPoint.create(this, 'setPoint', + this._point.x, this._point.y); + }, + + setPoint: function(point) { + this.translate(Point.read(arguments).subtract(this._point)); + }, + + getPosition: function() { + return this.getPoint(); + }, + + setPosition: function(point) { + this.setPoint.apply(this, arguments); + }, + + _transform: function(matrix, flags) { + this._matrix.preConcatenate(matrix); + matrix._transformPoint(this._point, this._point); + }, + + draw: function(ctx) { + if (!this._content) + return; + ctx.save(); + ctx.font = this.getFontSize() + 'pt ' + this.getFont(); + ctx.textAlign = this.getJustification(); + this._matrix.applyToContext(ctx); + + var fillColor = this.getFillColor(); + var strokeColor = this.getStrokeColor(); + if (!fillColor || !strokeColor) + ctx.globalAlpha = this._opacity; + if (fillColor) { + ctx.fillStyle = fillColor.getCanvasStyle(ctx); + ctx.fillText(this._content, 0, 0); + } + if (strokeColor) { + ctx.strokeStyle = strokeColor.getCanvasStyle(ctx); + ctx.strokeText(this._content, 0, 0); + } + ctx.restore(); + } +}); + +var Style = Item.extend({ + initialize: function(style) { + var clone = style instanceof Style; + return Base.each(this._defaults, function(value, key) { + value = style && style[key] || value; + this[key] = value && clone && value.clone + ? value.clone() : value; + }, this); + }, + + statics: { + create: function(item) { + var style = new this(this.dont); + style._item = item; + return style; + }, + + extend: function(src) { + var styleKey = src._style, + flags = src._flags || {}; + src._owner.inject(Base.each(src._defaults, function(value, key) { + var isColor = !!key.match(/Color$/), + part = Base.capitalize(key), + set = 'set' + part, + get = 'get' + part; + src[set] = function(value) { + var children = this._item && this._item._children; + value = isColor ? Color.read(arguments) : value; + if (children) { + for (var i = 0, l = children.length; i < l; i++) + children[i][styleKey][set](value); + } else { + var old = this['_' + key]; + if (old != value && !(old && old.equals + && old.equals(value))) { + this['_' + key] = value; + if (isColor) { + if (old) + old._removeOwner(this._item); + if (value) + value._addOwner(this._item); + } + if (this._item) + this._item._changed(flags[key] || Change.STYLE); + } + } + return this; + }; + src[get] = function() { + var children = this._item && this._item._children, + style; + if (!children) + return this['_' + key]; + for (var i = 0, l = children.length; i < l; i++) { + var childStyle = children[i][styleKey][get](); + if (!style) { + style = childStyle; + } else if (style != childStyle && !(style + && style.equals && style.equals(childStyle))) { + return undefined; + } + } + return style; + }; + this[set] = function(value) { + this[styleKey][set](value); + return this; + }; + this[get] = function() { + return this[styleKey][get](); + }; + }, {})); + return this.base(src); + } + } +}); + +var PathStyle = this.PathStyle = Style.extend({ + _defaults: { + fillColor: undefined, + strokeColor: undefined, + strokeWidth: 1, + strokeCap: 'butt', + strokeJoin: 'miter', + miterLimit: 10, + dashOffset: 0, + dashArray: [] + }, + _flags: { + strokeWidth: Change.STROKE, + strokeCap: Change.STROKE, + strokeJoin: Change.STROKE, + miterLimit: Change.STROKE + }, + _owner: Item, + _style: '_style' + +}); + +var ParagraphStyle = this.ParagraphStyle = Style.extend({ + _defaults: { + justification: 'left' + }, + _owner: TextItem, + _style: '_paragraphStyle' + +}); + +var CharacterStyle = this.CharacterStyle = PathStyle.extend({ + _defaults: Base.merge(PathStyle.prototype._defaults, { + fillColor: 'black', + fontSize: 10, + font: 'sans-serif' + }), + _owner: TextItem, + _style: '_characterStyle' + +}); + +var Color = this.Color = Base.extend(new function() { + + var components = { + gray: ['gray'], + rgb: ['red', 'green', 'blue'], + hsb: ['hue', 'saturation', 'brightness'], + hsl: ['hue', 'saturation', 'lightness'] + }; + + var colorCache = {}, + colorContext; + + function nameToRgbColor(name) { + var color = colorCache[name]; + if (color) + return color.clone(); + if (!colorContext) { + var canvas = CanvasProvider.getCanvas(Size.create(1, 1)); + colorContext = canvas.getContext('2d'); + colorContext.globalCompositeOperation = 'copy'; + } + colorContext.fillStyle = 'rgba(0,0,0,0)'; + colorContext.fillStyle = name; + colorContext.fillRect(0, 0, 1, 1); + var data = colorContext.getImageData(0, 0, 1, 1).data, + rgb = [data[0] / 255, data[1] / 255, data[2] / 255]; + return (colorCache[name] = RgbColor.read(rgb)).clone(); + } + + function hexToRgbColor(string) { + var hex = string.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); + if (hex.length >= 4) { + var rgb = new Array(3); + for (var i = 0; i < 3; i++) { + var channel = hex[i + 1]; + rgb[i] = parseInt(channel.length == 1 + ? channel + channel : channel, 16) / 255; + } + return RgbColor.read(rgb); + } + } + + var hsbIndices = [ + [0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2] + ]; + + var converters = { + 'rgb-hsb': function(color) { + var r = color._red, + g = color._green, + b = color._blue, + max = Math.max(r, g, b), + min = Math.min(r, g, b), + delta = max - min, + h = delta == 0 ? 0 + : ( max == r ? (g - b) / delta + (g < b ? 6 : 0) + : max == g ? (b - r) / delta + 2 + : (r - g) / delta + 4) * 60, + s = max == 0 ? 0 : delta / max, + v = max; + return new HsbColor(h, s, v, color._alpha); + }, + + 'hsb-rgb': function(color) { + var h = (color._hue / 60) % 6, + s = color._saturation, + b = color._brightness, + i = Math.floor(h), + f = h - i, + i = hsbIndices[i], + v = [ + b, + b * (1 - s), + b * (1 - s * f), + b * (1 - s * (1 - f)) + ]; + return new RgbColor(v[i[0]], v[i[1]], v[i[2]], color._alpha); + }, + + 'rgb-hsl': function(color) { + var r = color._red, + g = color._green, + b = color._blue, + max = Math.max(r, g, b), + min = Math.min(r, g, b), + delta = max - min, + achromatic = delta == 0, + h = achromatic ? 0 + : ( max == r ? (g - b) / delta + (g < b ? 6 : 0) + : max == g ? (b - r) / delta + 2 + : (r - g) / delta + 4) * 60, + l = (max + min) / 2, + s = achromatic ? 0 : l < 0.5 + ? delta / (max + min) + : delta / (2 - max - min); + return new HslColor(h, s, l, color._alpha); + }, + + 'hsl-rgb': function(color) { + var s = color._saturation, + h = color._hue / 360, + l = color._lightness, + t1, t2, c; + if (s == 0) + return new RgbColor(l, l, l, color._alpha); + var t3s = [ h + 1 / 3, h, h - 1 / 3 ], + t2 = l < 0.5 ? l * (1 + s) : l + s - l * s, + t1 = 2 * l - t2, + c = []; + for (var i = 0; i < 3; i++) { + var t3 = t3s[i]; + if (t3 < 0) t3 += 1; + if (t3 > 1) t3 -= 1; + c[i] = 6 * t3 < 1 + ? t1 + (t2 - t1) * 6 * t3 + : 2 * t3 < 1 + ? t2 + : 3 * t3 < 2 + ? t1 + (t2 - t1) * ((2 / 3) - t3) * 6 + : t1; + } + return new RgbColor(c[0], c[1], c[2], color._alpha); + }, + + 'rgb-gray': function(color) { + return new GrayColor(1 - (color._red * 0.2989 + color._green * 0.587 + + color._blue * 0.114), color._alpha); + }, + + 'gray-rgb': function(color) { + var comp = 1 - color._gray; + return new RgbColor(comp, comp, comp, color._alpha); + }, + + 'gray-hsb': function(color) { + return new HsbColor(0, 0, 1 - color._gray, color._alpha); + }, + + 'gray-hsl': function(color) { + return new HslColor(0, 0, 1 - color._gray, color._alpha); + } + }; + + var fields = { + _readNull: true, + + initialize: function(arg) { + var isArray = Array.isArray(arg), + type = this._colorType; + if (typeof arg === 'object' && !isArray) { + if (!type) { + return arg.red !== undefined + ? new RgbColor(arg.red, arg.green, arg.blue, arg.alpha) + : arg.gray !== undefined + ? new GrayColor(arg.gray, arg.alpha) + : arg.lightness !== undefined + ? new HslColor(arg.hue, arg.saturation, arg.lightness, + arg.alpha) + : arg.hue !== undefined + ? new HsbColor(arg.hue, arg.saturation, arg.brightness, + arg.alpha) + : new RgbColor(); + } else { + return Color.read(arguments).convert(type); + } + } else if (typeof arg === 'string') { + var rgbColor = arg.match(/^#[0-9a-f]{3,6}$/i) + ? hexToRgbColor(arg) + : nameToRgbColor(arg); + return type + ? rgbColor.convert(type) + : rgbColor; + } else { + var components = isArray ? arg + : Array.prototype.slice.call(arguments); + if (!type) { + if (components.length >= 3) + return new RgbColor(components); + return new GrayColor(components); + } else { + Base.each(this._components, + function(name, i) { + var value = components[i]; + this['_' + name] = value !== undefined + ? value : null; + }, + this); + } + } + }, + + clone: function() { + var ctor = this.constructor, + copy = new ctor(ctor.dont), + components = this._components; + for (var i = 0, l = components.length; i < l; i++) { + var key = '_' + components[i]; + copy[key] = this[key]; + } + return copy; + }, + + convert: function(type) { + var converter; + return this._colorType == type + ? this.clone() + : (converter = converters[this._colorType + '-' + type]) + ? converter(this) + : converters['rgb-' + type]( + converters[this._colorType + '-rgb'](this)); + }, + + statics: { + extend: function(src) { + src.beans = true; + if (src._colorType) { + var comps = components[src._colorType]; + src._components = comps.concat(['alpha']); + Base.each(comps, function(name) { + var isHue = name === 'hue', + part = Base.capitalize(name), + name = '_' + name; + this['get' + part] = function() { + return this[name]; + }; + this['set' + part] = function(value) { + this[name] = isHue + ? ((value % 360) + 360) % 360 + : Math.min(Math.max(value, 0), 1); + this._changed(); + return this; + }; + }, src); + } + return this.base(src); + } + } + }; + + Base.each(components, function(comps, type) { + Base.each(comps, function(component) { + var part = Base.capitalize(component); + fields['get' + part] = function() { + return this.convert(type)[component]; + }; + fields['set' + part] = function(value) { + var color = this.convert(type); + color[component] = value; + color = color.convert(this._colorType); + for (var i = 0, l = this._components.length; i < l; i++) { + var key = this._components[i]; + this[key] = color[key]; + } + }; + }); + }); + + return fields; +}, { + + _changed: function() { + this._cssString = null; + for (var i = 0, l = this._owners && this._owners.length; i < l; i++) + this._owners[i]._changed(Change.STYLE); + }, + + _addOwner: function(item) { + if (!this._owners) + this._owners = []; + this._owners.push(item); + }, + + _removeOwner: function(item) { + var index = this._owners ? this._owners.indexOf(item) : -1; + if (index != -1) { + this._owners.splice(index, 1); + if (this._owners.length == 0) + delete this._owners; + } + }, + + getType: function() { + return this._colorType; + }, + + getComponents: function() { + var length = this._components.length; + var comps = new Array(length); + for (var i = 0; i < length; i++) + comps[i] = this['_' + this._components[i]]; + return comps; + }, + + getAlpha: function() { + return this._alpha != null ? this._alpha : 1; + }, + + setAlpha: function(alpha) { + this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1); + this._changed(); + return this; + }, + + hasAlpha: function() { + return this._alpha != null; + }, + + equals: function(color) { + if (color && color._colorType === this._colorType) { + for (var i = 0, l = this._components.length; i < l; i++) { + var component = '_' + this._components[i]; + if (this[component] !== color[component]) + return false; + } + return true; + } + return false; + }, + + toString: function() { + var parts = [], + format = Base.formatNumber; + for (var i = 0, l = this._components.length; i < l; i++) { + var component = this._components[i], + value = this['_' + component]; + if (component === 'alpha' && value == null) + value = 1; + parts.push(component + ': ' + format(value)); + } + return '{ ' + parts.join(', ') + ' }'; + }, + + toCssString: function() { + if (!this._cssString) { + var color = this.convert('rgb'), + alpha = color.getAlpha(), + components = [ + Math.round(color._red * 255), + Math.round(color._green * 255), + Math.round(color._blue * 255), + alpha != null ? alpha : 1 + ]; + this._cssString = 'rgba(' + components.join(', ') + ')'; + } + return this._cssString; + }, + + getCanvasStyle: function() { + return this.toCssString(); + } + +}); + +var GrayColor = this.GrayColor = Color.extend({ + + _colorType: 'gray' +}); + +var RgbColor = this.RgbColor = this.RGBColor = Color.extend({ + + _colorType: 'rgb' +}); + +var HsbColor = this.HsbColor = this.HSBColor = Color.extend({ + + _colorType: 'hsb' +}); + +var HslColor = this.HslColor = this.HSLColor = Color.extend({ + + _colorType: 'hsl' +}); + +var GradientColor = this.GradientColor = Color.extend({ + + initialize: function(gradient, origin, destination, hilite) { + this.gradient = gradient || new Gradient(); + this.setOrigin(origin); + this.setDestination(destination); + if (hilite) + this.setHilite(hilite); + }, + + clone: function() { + return new GradientColor(this.gradient, this._origin, this._destination, + this._hilite); + }, + + getOrigin: function() { + return this._origin; + }, + + setOrigin: function(origin) { + origin = Point.read(arguments).clone(); + this._origin = origin; + if (this._destination) + this._radius = this._destination.getDistance(this._origin); + this._changed(); + return this; + }, + + getDestination: function() { + return this._destination; + }, + + setDestination: function(destination) { + destination = Point.read(arguments).clone(); + this._destination = destination; + this._radius = this._destination.getDistance(this._origin); + this._changed(); + return this; + }, + + getHilite: function() { + return this._hilite; + }, + + setHilite: function(hilite) { + hilite = Point.read(arguments).clone(); + var vector = hilite.subtract(this._origin); + if (vector.getLength() > this._radius) { + this._hilite = this._origin.add( + vector.normalize(this._radius - 0.1)); + } else { + this._hilite = hilite; + } + this._changed(); + return this; + }, + + getCanvasStyle: function(ctx) { + var gradient; + if (this.gradient.type === 'linear') { + gradient = ctx.createLinearGradient(this._origin.x, this._origin.y, + this._destination.x, this._destination.y); + } else { + var origin = this._hilite || this._origin; + gradient = ctx.createRadialGradient(origin.x, origin.y, + 0, this._origin.x, this._origin.y, this._radius); + } + for (var i = 0, l = this.gradient._stops.length; i < l; i++) { + var stop = this.gradient._stops[i]; + gradient.addColorStop(stop._rampPoint, stop._color.toCssString()); + } + return gradient; + }, + + equals: function(color) { + return color == this || color && color._colorType === this._colorType + && this.gradient.equals(color.gradient) + && this._origin.equals(color._origin) + && this._destination.equals(color._destination); + }, + + transform: function(matrix) { + matrix._transformPoint(this._origin, this._origin, true); + matrix._transformPoint(this._destination, this._destination, true); + if (this._hilite) + matrix._transformPoint(this._hilite, this._hilite, true); + this._radius = this._destination.getDistance(this._origin); + } +}); + +var Gradient = this.Gradient = Base.extend({ + initialize: function(stops, type) { + this.setStops(stops || ['white', 'black']); + this.type = type || 'linear'; + }, + + clone: function() { + var stops = []; + for (var i = 0, l = this._stops.length; i < l; i++) + stops[i] = this._stops[i].clone(); + return new Gradient(stops, this.type); + }, + + getStops: function() { + return this._stops; + }, + + setStops: function(stops) { + if (stops.length < 2) + throw new Error( + 'Gradient stop list needs to contain at least two stops.'); + this._stops = GradientStop.readAll(stops); + for (var i = 0, l = this._stops.length; i < l; i++) { + var stop = this._stops[i]; + if (stop._defaultRamp) + stop.setRampPoint(i / (l - 1)); + } + }, + + equals: function(gradient) { + if (gradient.type != this.type) + return false; + if (this._stops.length == gradient._stops.length) { + for (var i = 0, l = this._stops.length; i < l; i++) { + if (!this._stops[i].equals(gradient._stops[i])) + return false; + } + return true; + } + return false; + } +}); + +var GradientStop = this.GradientStop = Base.extend({ + initialize: function(arg0, arg1) { + if (arg1 === undefined && Array.isArray(arg0)) { + this.setColor(arg0[0]); + this.setRampPoint(arg0[1]); + } else if (arg0.color) { + this.setColor(arg0.color); + this.setRampPoint(arg0.rampPoint); + } else { + this.setColor(arg0); + this.setRampPoint(arg1); + } + }, + + clone: function() { + return new GradientStop(this._color.clone(), this._rampPoint); + }, + + getRampPoint: function() { + return this._rampPoint; + }, + + setRampPoint: function(rampPoint) { + this._defaultRamp = rampPoint == null; + this._rampPoint = rampPoint || 0; + }, + + getColor: function() { + return this._color; + }, + + setColor: function(color) { + this._color = Color.read(arguments); + }, + + equals: function(stop) { + return stop == this || stop instanceof GradientStop + && this._color.equals(stop._color) + && this._rampPoint == stop._rampPoint; + } +}); + +var DomElement = { + getBounds: function(el, viewport) { + var rect = el.getBoundingClientRect(), + doc = el.ownerDocument, + body = doc.body, + docEl = doc.documentElement, + x = rect.left - (docEl.clientLeft || body.clientLeft || 0), + y = rect.top - (docEl.clientTop || body.clientTop || 0); + if (!viewport) { + var win = DomElement.getViewport(doc); + x += win.pageXOffset || docEl.scrollLeft || body.scrollLeft; + y += win.pageYOffset || docEl.scrollTop || body.scrollTop; + } + return new Rectangle(x, y, rect.width, rect.height); + }, + + getOffset: function(el, viewport) { + return this.getBounds(el, viewport).getPoint(); + }, + + getSize: function(el) { + return this.getBounds(el, true).getSize(); + }, + + isInvisible: function(el) { + return this.getSize(el).equals([0, 0]); + }, + + isVisible: function(el) { + return !this.isInvisible(el) && this.getViewportBounds(el).intersects( + this.getBounds(el, true)); + }, + + getViewport: function(doc) { + return doc.defaultView || doc.parentWindow; + }, + + getViewportBounds: function(el) { + var doc = el.ownerDocument, + view = this.getViewport(doc), + body = doc.getElementsByTagName( + doc.compatMode === 'CSS1Compat' ? 'html' : 'body')[0]; + return Rectangle.create(0, 0, + view.innerWidth || body.clientWidth, + view.innerHeight || body.clientHeight + ); + }, + + getComputedStyle: function(el, name) { + if (el.currentStyle) + return el.currentStyle[Base.camelize(name)]; + var style = this.getViewport(el.ownerDocument) + .getComputedStyle(el, null); + return style ? style.getPropertyValue(Base.hyphenate(name)) : null; + } +}; + +var DomEvent = { + add: function(el, events) { + for (var type in events) { + var func = events[type]; + if (el.addEventListener) { + el.addEventListener(type, func, false); + } else if (el.attachEvent) { + el.attachEvent('on' + type, func.bound = function() { + func.call(el, window.event); + }); + } + } + }, + + remove: function(el, events) { + for (var type in events) { + var func = events[type]; + if (el.removeEventListener) { + el.removeEventListener(type, func, false); + } else if (el.detachEvent) { + el.detachEvent('on' + type, func.bound); + } + } + }, + + getPoint: function(event) { + var pos = event.targetTouches + ? event.targetTouches.length + ? event.targetTouches[0] + : event.changedTouches[0] + : event; + return Point.create( + pos.pageX || pos.clientX + document.documentElement.scrollLeft, + pos.pageY || pos.clientY + document.documentElement.scrollTop + ); + }, + + getTarget: function(event) { + return event.target || event.srcElement; + }, + + getOffset: function(event, target) { + return DomEvent.getPoint(event).subtract(DomElement.getOffset( + target || DomEvent.getTarget(event))); + }, + + preventDefault: function(event) { + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; + } + }, + + stopPropagation: function(event) { + if (event.stopPropagation) { + event.stopPropagation(); + } else { + event.cancelBubble = true; + } + }, + + stop: function(event) { + DomEvent.stopPropagation(event); + DomEvent.preventDefault(event); + } +}; + +DomEvent.requestAnimationFrame = new function() { + var part = 'equestAnimationFrame', + request = window['r' + part] || window['webkitR' + part] + || window['mozR' + part] || window['oR' + part] + || window['msR' + part]; + if (request) { + request(function(time) { + if (time == undefined) + request = null; + }); + } + + var callbacks = [], + focused = true, + timer; + + DomEvent.add(window, { + focus: function() { + focused = true; + }, + blur: function() { + focused = false; + } + }); + + return function(callback, element) { + if (request) + return request(callback, element); + callbacks.push([callback, element]); + if (timer) + return; + timer = window.setInterval(function() { + for (var i = callbacks.length - 1; i >= 0; i--) { + var entry = callbacks[i], + func = entry[0], + el = entry[1]; + if (!el || (PaperScript.getAttribute(el, 'keepalive') == 'true' + || focused) && DomElement.isVisible(el)) { + callbacks.splice(i, 1); + func(Date.now()); + } + } + }, 1000 / 60); + }; +}; + +var View = this.View = PaperScopeItem.extend({ + _list: 'views', + _reference: 'view', + + initialize: function(canvas) { + this.base(); + var size; + + if (typeof canvas === 'string') + canvas = document.getElementById(canvas); + if (canvas instanceof HTMLCanvasElement) { + this._canvas = canvas; + if (PaperScript.hasAttribute(canvas, 'resize')) { + var offset = DomElement.getOffset(canvas, true), + that = this; + size = DomElement.getViewportBounds(canvas) + .getSize().subtract(offset); + canvas.width = size.width; + canvas.height = size.height; + DomEvent.add(window, { + resize: function(event) { + if (!DomElement.isInvisible(canvas)) + offset = DomElement.getOffset(canvas, true); + that.setViewSize(DomElement.getViewportBounds(canvas) + .getSize().subtract(offset)); + } + }); + } else { + size = DomElement.isInvisible(canvas) + ? Size.create(parseInt(canvas.getAttribute('width')), + parseInt(canvas.getAttribute('height'))) + : DomElement.getSize(canvas); + } + if (PaperScript.hasAttribute(canvas, 'stats')) { + this._stats = new Stats(); + var element = this._stats.domElement, + style = element.style, + offset = DomElement.getOffset(canvas); + style.position = 'absolute'; + style.left = offset.x + 'px'; + style.top = offset.y + 'px'; + document.body.appendChild(element); + } + } else { + size = Size.read(arguments, 1); + if (size.isZero()) + size = new Size(1024, 768); + this._canvas = CanvasProvider.getCanvas(size); + } + this._id = this._canvas.getAttribute('id'); + if (this._id == null) + this._canvas.setAttribute('id', this._id = 'canvas-' + View._id++); + + View._views[this._id] = this; + this._viewSize = LinkedSize.create(this, 'setViewSize', + size.width, size.height); + this._context = this._canvas.getContext('2d'); + this._matrix = new Matrix(); + this._zoom = 1; + + this._events = this._createEvents(); + DomEvent.add(this._canvas, this._events); + if (!View._focused) + View._focused = this; + + this._scope._redrawNotified = false; + }, + + remove: function() { + if (!this.base()) + return false; + if (View._focused == this) + View._focused = null; + delete View._views[this._id]; + DomEvent.remove(this._canvas, this._events); + this._canvas = this._events = this._onFrame = null; + return true; + }, + + _redraw: function() { + this._redrawNeeded = true; + if (this._onFrameCallback) { + this._onFrameCallback(0, true); + } else { + this.draw(); + } + }, + + _transform: function(matrix, flags) { + this._matrix.preConcatenate(matrix); + this._bounds = null; + this._inverse = null; + this._redraw(); + }, + + getCanvas: function() { + return this._canvas; + }, + + getViewSize: function() { + return this._viewSize; + }, + + setViewSize: function(size) { + size = Size.read(arguments); + var delta = size.subtract(this._viewSize); + if (delta.isZero()) + return; + this._canvas.width = size.width; + this._canvas.height = size.height; + this._viewSize.set(size.width, size.height, true); + this._bounds = null; + this._redrawNeeded = true; + if (this.onResize) { + this.onResize({ + size: size, + delta: delta + }); + } + this._redraw(); + }, + + getBounds: function() { + if (!this._bounds) + this._bounds = this._getInverse()._transformBounds( + new Rectangle(new Point(), this._viewSize)); + return this._bounds; + }, + + getSize: function() { + return this.getBounds().getSize(); + }, + + getCenter: function() { + return this.getBounds().getCenter(); + }, + + setCenter: function(center) { + this.scrollBy(Point.read(arguments).subtract(this.getCenter())); + }, + + getZoom: function() { + return this._zoom; + }, + + setZoom: function(zoom) { + this._transform(new Matrix().scale(zoom / this._zoom, this.getCenter())); + this._zoom = zoom; + }, + + isVisible: function() { + return DomElement.isVisible(this._canvas); + }, + + scrollBy: function(point) { + this._transform(new Matrix().translate(Point.read(arguments).negate())); + }, + + draw: function(checkRedraw) { + if (checkRedraw && !this._redrawNeeded) + return false; + if (this._stats) + this._stats.update(); + var ctx = this._context, + size = this._viewSize; + ctx.clearRect(0, 0, size._width + 1, size._height + 1); + + ctx.save(); + this._matrix.applyToContext(ctx); + this._scope.project.draw(ctx); + ctx.restore(); + if (this._redrawNeeded) { + this._redrawNeeded = false; + this._scope._redrawNotified = false; + } + return true; + }, + + projectToView: function(point) { + return this._matrix._transformPoint(Point.read(arguments)); + }, + + viewToProject: function(point) { + return this._getInverse()._transformPoint(Point.read(arguments)); + }, + + _getInverse: function() { + if (!this._inverse) + this._inverse = this._matrix.createInverse(); + return this._inverse; + }, + + getOnFrame: function() { + return this._onFrame; + }, + + setOnFrame: function(onFrame) { + this._onFrame = onFrame; + if (!onFrame) { + delete this._onFrameCallback; + return; + } + var that = this, + requested = false, + before, + time = 0, + count = 0; + this._onFrameCallback = function(param, dontRequest) { + requested = false; + if (!that._onFrame) + return; + paper = that._scope; + requested = true; + if (!dontRequest) { + DomEvent.requestAnimationFrame(that._onFrameCallback, + that._canvas); + } + var now = Date.now() / 1000, + delta = before ? now - before : 0; + that._onFrame(Base.merge({ + delta: delta, + time: time += delta, + count: count++ + })); + before = now; + that.draw(true); + }; + if (!requested) + this._onFrameCallback(); + }, + + onResize: null +}, { + statics: { + _views: {}, + _id: 0 + } +}, new function() { + var tool, + timer, + curPoint, + tempFocus, + dragging = false; + + function viewToProject(view, event) { + return view.viewToProject(DomEvent.getOffset(event, view._canvas)); + } + + function updateFocus() { + if (!View._focused || !View._focused.isVisible()) { + PaperScope.each(function(scope) { + for (var i = 0, l = scope.views.length; i < l; i++) { + var view = scope.views[i]; + if (view.isVisible()) { + View._focused = tempFocus = view; + throw Base.stop; + } + } + }); + } + } + + function mousemove(event) { + var view; + if (!dragging) { + view = View._views[DomEvent.getTarget(event).getAttribute('id')]; + if (view) { + View._focused = tempFocus = view; + } else if (tempFocus && tempFocus == View._focused) { + View._focused = null; + updateFocus(); + } + } + if (!(view = view || View._focused) || !(tool = view._scope.tool)) + return; + var point = event && viewToProject(view, event); + var onlyMove = !!(!tool.onMouseDrag && tool.onMouseMove); + if (dragging && !onlyMove) { + curPoint = point || curPoint; + if (curPoint && tool.onHandleEvent('mousedrag', curPoint, event)) { + view.draw(true); + DomEvent.stop(event); + } + } else if ((!dragging || onlyMove) + && tool.onHandleEvent('mousemove', point, event)) { + view.draw(true); + DomEvent.stop(event); + } + } + + function mouseup(event) { + var view = View._focused; + if (!view || !dragging) + return; + dragging = false; + curPoint = null; + if (tool) { + if (timer != null) + timer = clearInterval(timer); + if (tool.onHandleEvent('mouseup', viewToProject(view, event), event)) { + view.draw(true); + DomEvent.stop(event); + } + } + } + + function selectstart(event) { + if (dragging) + DomEvent.stop(event); + } + + DomEvent.add(document, { + mousemove: mousemove, + mouseup: mouseup, + touchmove: mousemove, + touchend: mouseup, + selectstart: selectstart, + scroll: updateFocus + }); + + DomEvent.add(window, { + load: updateFocus + }); + + return { + _createEvents: function() { + var view = this; + + function mousedown(event) { + View._focused = view; + if (!(tool = view._scope.tool)) + return; + curPoint = viewToProject(view, event); + if (tool.onHandleEvent('mousedown', curPoint, event)) + view.draw(true); + if (tool.eventInterval != null) + timer = setInterval(mousemove, tool.eventInterval); + dragging = true; + } + + return { + mousedown: mousedown, + touchstart: mousedown, + selectstart: selectstart + }; + }, + + statics: { + + updateFocus: updateFocus + } + }; +}); + +var Event = this.Event = Base.extend({ + initialize: function(event) { + this.event = event; + }, + + preventDefault: function() { + DomEvent.preventDefault(this.event); + }, + + stopPropagation: function() { + DomEvent.stopPropagation(this.event); + }, + + stop: function() { + DomEvent.stop(this.event); + }, + + getModifiers: function() { + return Key.modifiers; + } +}); + +var KeyEvent = this.KeyEvent = Event.extend(new function() { + return { + initialize: function(down, key, character, event) { + this.base(event); + this.type = down ? 'keydown' : 'keyup'; + this.key = key; + this.character = character; + }, + + toString: function() { + return '{ type: ' + this.type + + ', key: ' + this.key + + ', character: ' + this.character + + ', modifiers: ' + this.getModifiers() + + ' }'; + } + }; +}); + +var Key = this.Key = new function() { + + var keys = { + 8: 'backspace', + 13: 'enter', + 16: 'shift', + 17: 'control', + 18: 'option', + 19: 'pause', + 20: 'caps-lock', + 27: 'escape', + 32: 'space', + 35: 'end', + 36: 'home', + 37: 'left', + 38: 'up', + 39: 'right', + 40: 'down', + 46: 'delete', + 91: 'command', + 93: 'command', + 224: 'command' + }, + + modifiers = Base.merge({ + shift: false, + control: false, + option: false, + command: false, + capsLock: false + }), + + charCodeMap = {}, + keyMap = {}, + downCode; + + function handleKey(down, keyCode, charCode, event) { + var character = String.fromCharCode(charCode), + key = keys[keyCode] || character.toLowerCase(), + handler = down ? 'onKeyDown' : 'onKeyUp', + view = View._focused, + scope = view && view.isVisible() && view._scope, + tool = scope && scope.tool; + keyMap[key] = down; + if (tool && tool[handler]) { + var keyEvent = new KeyEvent(down, key, character, event); + if (tool[handler](keyEvent) === false) + keyEvent.preventDefault(); + if (view) + view.draw(true); + } + } + + DomEvent.add(document, { + keydown: function(event) { + var code = event.which || event.keyCode; + var key = keys[code], name; + if (key) { + if ((name = Base.camelize(key)) in modifiers) + modifiers[name] = true; + charCodeMap[code] = 0; + handleKey(true, code, null, event); + } else { + downCode = code; + } + }, + + keypress: function(event) { + if (downCode != null) { + var code = event.which || event.keyCode; + charCodeMap[downCode] = code; + handleKey(true, downCode, code, event); + downCode = null; + } + }, + + keyup: function(event) { + var code = event.which || event.keyCode, + key = keys[code], name; + if (key && (name = Base.camelize(key)) in modifiers) + modifiers[name] = false; + if (charCodeMap[code] != null) { + handleKey(false, code, charCodeMap[code], event); + delete charCodeMap[code]; + } + } + }); + + return { + modifiers: modifiers, + + isDown: function(key) { + return !!keyMap[key]; + } + }; +}; + +var ToolEvent = this.ToolEvent = Event.extend({ + initialize: function(tool, type, event) { + this.tool = tool; + this.type = type; + this.event = event; + }, + + _choosePoint: function(point, toolPoint) { + return point ? point : toolPoint ? toolPoint.clone() : null; + }, + + getPoint: function() { + return this._choosePoint(this._point, this.tool._point); + }, + + setPoint: function(point) { + this._point = point; + }, + + getLastPoint: function() { + return this._choosePoint(this._lastPoint, this.tool._lastPoint); + }, + + setLastPoint: function(lastPoint) { + this._lastPoint = lastPoint; + }, + + getDownPoint: function() { + return this._choosePoint(this._downPoint, this.tool._downPoint); + }, + + setDownPoint: function(downPoint) { + this._downPoint = downPoint; + }, + + getMiddlePoint: function() { + if (!this._middlePoint && this.tool._lastPoint) { + return this.tool._point.add(this.tool._lastPoint).divide(2); + } + return this.middlePoint; + }, + + setMiddlePoint: function(middlePoint) { + this._middlePoint = middlePoint; + }, + + getDelta: function() { + return !this._delta && this.tool._lastPoint + ? this.tool._point.subtract(this.tool._lastPoint) + : this._delta; + }, + + setDelta: function(delta) { + this._delta = delta; + }, + + getCount: function() { + return /^mouse(down|up)$/.test(this.type) + ? this.tool._downCount + : this.tool._count; + }, + + setCount: function(count) { + this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count'] + = count; + }, + + getItem: function() { + if (!this._item) { + var result = this.tool._scope.project.hitTest(this.getPoint()); + if (result) { + var item = result.item, + parent = item._parent; + while ((parent instanceof Group && !(parent instanceof Layer)) + || parent instanceof CompoundPath) { + item = parent; + parent = parent._parent; + } + this._item = item; + } + } + return this._item; + }, + setItem: function(item) { + this._item = item; + }, + + toString: function() { + return '{ type: ' + this.type + + ', point: ' + this.getPoint() + + ', count: ' + this.getCount() + + ', modifiers: ' + this.getModifiers() + + ' }'; + } +}); + +var Tool = this.Tool = PaperScopeItem.extend({ + _list: 'tools', + _reference: 'tool', + + initialize: function() { + this.base(); + this._firstMove = true; + this._count = 0; + this._downCount = 0; + }, + + eventInterval: null, + + getMinDistance: function() { + return this._minDistance; + }, + + setMinDistance: function(minDistance) { + this._minDistance = minDistance; + if (this._minDistance != null && this._maxDistance != null + && this._minDistance > this._maxDistance) { + this._maxDistance = this._minDistance; + } + }, + + getMaxDistance: function() { + return this._maxDistance; + }, + + setMaxDistance: function(maxDistance) { + this._maxDistance = maxDistance; + if (this._minDistance != null && this._maxDistance != null + && this._maxDistance < this._minDistance) { + this._minDistance = maxDistance; + } + }, + + getFixedDistance: function() { + return this._minDistance == this._maxDistance + ? this._minDistance : null; + }, + + setFixedDistance: function(distance) { + this._minDistance = distance; + this._maxDistance = distance; + }, + + updateEvent: function(type, pt, minDistance, maxDistance, start, + needsChange, matchMaxDistance) { + if (!start) { + if (minDistance != null || maxDistance != null) { + var minDist = minDistance != null ? minDistance : 0; + var vector = pt.subtract(this._point); + var distance = vector.getLength(); + if (distance < minDist) + return false; + var maxDist = maxDistance != null ? maxDistance : 0; + if (maxDist != 0) { + if (distance > maxDist) { + pt = this._point.add(vector.normalize(maxDist)); + } else if (matchMaxDistance) { + return false; + } + } + } + if (needsChange && pt.equals(this._point)) + return false; + } + this._lastPoint = start && type == 'mousemove' ? pt : this._point; + this._point = pt; + switch (type) { + case 'mousedown': + this._lastPoint = this._downPoint; + this._downPoint = this._point; + this._downCount++; + break; + case 'mouseup': + this._lastPoint = this._downPoint; + break; + } + this._count = start ? 0 : this._count + 1; + return true; + }, + + onHandleEvent: function(type, pt, event) { + paper = this._scope; + var called = false; + switch (type) { + case 'mousedown': + this.updateEvent(type, pt, null, null, true, false, false); + if (this.onMouseDown) { + this.onMouseDown(new ToolEvent(this, type, event)); + called = true; + } + break; + case 'mousedrag': + var needsChange = false, + matchMaxDistance = false; + while (this.updateEvent(type, pt, this.minDistance, + this.maxDistance, false, needsChange, matchMaxDistance)) { + if (this.onMouseDrag) { + this.onMouseDrag(new ToolEvent(this, type, event)); + called = true; + } + needsChange = true; + matchMaxDistance = true; + } + break; + case 'mouseup': + if ((this._point.x != pt.x || this._point.y != pt.y) + && this.updateEvent('mousedrag', pt, this.minDistance, + this.maxDistance, false, false, false)) { + if (this.onMouseDrag) { + this.onMouseDrag(new ToolEvent(this, type, event)); + called = true; + } + } + this.updateEvent(type, pt, null, this.maxDistance, false, + false, false); + if (this.onMouseUp) { + this.onMouseUp(new ToolEvent(this, type, event)); + called = true; + } + this.updateEvent(type, pt, null, null, true, false, false); + this._firstMove = true; + break; + case 'mousemove': + while (this.updateEvent(type, pt, this.minDistance, + this.maxDistance, this._firstMove, true, false)) { + if (this.onMouseMove) { + this.onMouseMove(new ToolEvent(this, type, event)); + called = true; + } + this._firstMove = false; + } + break; + } + return called; + } +}); + +var CanvasProvider = { + canvases: [], + getCanvas: function(size) { + if (this.canvases.length) { + var canvas = this.canvases.pop(); + if ((canvas.width != size.width) + || (canvas.height != size.height)) { + canvas.width = size.width; + canvas.height = size.height; + } else { + canvas.getContext('2d').clearRect(0, 0, + size.width + 1, size.height + 1); + } + return canvas; + } else { + var canvas = document.createElement('canvas'); + canvas.width = size.width; + canvas.height = size.height; + return canvas; + } + }, + + returnCanvas: function(canvas) { + this.canvases.push(canvas); + } +}; + +var Numerical = new function() { + + var abscissas = [ + [ 0.5773502691896257645091488], + [0,0.7745966692414833770358531], + [ 0.3399810435848562648026658,0.8611363115940525752239465], + [0,0.5384693101056830910363144,0.9061798459386639927976269], + [ 0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016], + [0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897], + [ 0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609], + [0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762], + [ 0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640], + [0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380], + [ 0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491], + [0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294], + [ 0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973], + [0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657], + [ 0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542] + ]; + + var weights = [ + [1], + [0.8888888888888888888888889,0.5555555555555555555555556], + [0.6521451548625461426269361,0.3478548451374538573730639], + [0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640], + [0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961], + [0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114], + [0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314], + [0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922], + [0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688], + [0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537], + [0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160], + [0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216], + [0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329], + [0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284], + [0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806] + ]; + + var abs = Math.abs, + sqrt = Math.sqrt, + cos = Math.cos, + PI = Math.PI; + + return { + TOLERANCE: 10e-6, + EPSILON: 10e-12, + + integrate: function(f, a, b, n) { + var x = abscissas[n - 2], + w = weights[n - 2], + A = 0.5 * (b - a), + B = A + a, + i = 0, + m = (n + 1) >> 1, + sum = n & 1 ? w[i++] * f(B) : 0; + while (i < m) { + var Ax = A * x[i]; + sum += w[i++] * (f(B + Ax) + f(B - Ax)); + } + return A * sum; + }, + + findRoot: function(f, df, x, a, b, n, tolerance) { + for (var i = 0; i < n; i++) { + var fx = f(x), + dx = fx / df(x); + if (abs(dx) < tolerance) + return x; + var nx = x - dx; + if (fx > 0) { + b = x; + x = nx <= a ? 0.5 * (a + b) : nx; + } else { + a = x; + x = nx >= b ? 0.5 * (a + b) : nx; + } + } + }, + + solveQuadratic: function(a, b, c, roots, tolerance) { + if (abs(a) < tolerance) { + if (abs(b) >= tolerance) { + roots[0] = -c / b; + return 1; + } + if (abs(c) < tolerance) + return -1; + return 0; + } + var q = b * b - 4 * a * c; + if (q < 0) + return 0; + q = sqrt(q); + if (b < 0) + q = -q; + q = (b + q) * -0.5; + var n = 0; + if (abs(q) >= tolerance) + roots[n++] = c / q; + if (abs(a) >= tolerance) + roots[n++] = q / a; + return n; + }, + + solveCubic: function(a, b, c, d, roots, tolerance) { + if (abs(a) < tolerance) + return Numerical.solveQuadratic(b, c, d, roots, tolerance); + b /= a; + c /= a; + d /= a; + var Q = (b * b - 3 * c) / 9, + R = (2 * b * b * b - 9 * b * c + 27 * d) / 54, + Q3 = Q * Q * Q, + R2 = R * R; + b /= 3; + if (R2 < Q3) { + var theta = Math.acos(R / sqrt(Q3)), + q = -2 * sqrt(Q); + roots[0] = q * cos(theta / 3) - b; + roots[1] = q * cos((theta + 2 * PI) / 3) - b; + roots[2] = q * cos((theta - 2 * PI) / 3) - b; + return 3; + } else { + var A = -Math.pow(abs(R) + sqrt(R2 - Q3), 1 / 3); + if (R < 0) A = -A; + var B = (abs(A) < tolerance) ? 0 : Q / A; + roots[0] = (A + B) - b; + return 1; + } + return 0; + } + }; +}; + +var BlendMode = { + process: function(blendMode, srcContext, dstContext, alpha, offset) { + var srcCanvas = srcContext.canvas, + dstData = dstContext.getImageData(offset.x, offset.y, + srcCanvas.width, srcCanvas.height), + dst = dstData.data, + src = srcContext.getImageData(0, 0, + srcCanvas.width, srcCanvas.height).data, + min = Math.min, + max = Math.max, + abs = Math.abs, + sr, sg, sb, sa, + br, bg, bb, ba, + dr, dg, db; + + function getLum(r, g, b) { + return 0.2989 * r + 0.587 * g + 0.114 * b; + } + + function setLum(r, g, b, l) { + var d = l - getLum(r, g, b); + dr = r + d; + dg = g + d; + db = b + d; + var l = getLum(dr, dg, db), + mn = min(dr, dg, db), + mx = max(dr, dg, db); + if (mn < 0) { + var lmn = l - mn; + dr = l + (dr - l) * l / lmn; + dg = l + (dg - l) * l / lmn; + db = l + (db - l) * l / lmn; + } + if (mx > 255) { + var ln = 255 - l, mxl = mx - l; + dr = l + (dr - l) * ln / mxl; + dg = l + (dg - l) * ln / mxl; + db = l + (db - l) * ln / mxl; + } + } + + function getSat(r, g, b) { + return max(r, g, b) - min(r, g, b); + } + + function setSat(r, g, b, s) { + var col = [r, g, b], + mx = max(r, g, b), + mn = min(r, g, b), + md; + mn = mn == r ? 0 : mn == g ? 1 : 2; + mx = mx == r ? 0 : mx == g ? 1 : 2; + md = min(mn, mx) == 0 ? max(mn, mx) == 1 ? 2 : 1 : 0; + if (col[mx] > col[mn]) { + col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]); + col[mx] = s; + } else { + col[md] = col[mx] = 0; + } + col[mn] = 0; + dr = col[0]; + dg = col[1]; + db = col[2]; + } + + var modes = { + multiply: function() { + dr = br * sr / 255; + dg = bg * sg / 255; + db = bb * sb / 255; + }, + + screen: function() { + dr = 255 - (255 - br) * (255 - sr) / 255; + dg = 255 - (255 - bg) * (255 - sg) / 255; + db = 255 - (255 - bb) * (255 - sb) / 255; + }, + + overlay: function() { + dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255; + dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255; + db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255; + }, + + 'soft-light': function() { + var t = sr * br / 255; + dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255; + t = sg * bg / 255; + dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255; + t = sb * bb / 255; + db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255; + }, + + 'hard-light': function() { + dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255; + dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255; + db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255; + }, + + 'color-dodge': function() { + dr = sr == 255 ? sr : min(255, br * 255 / (255 - sr)); + dg = sg == 255 ? sg : min(255, bg * 255 / (255 - sg)); + db = sb == 255 ? sb : min(255, bb * 255 / (255 - sb)); + }, + + 'color-burn': function() { + dr = sr == 0 ? 0 : max(255 - ((255 - br) * 255) / sr, 0); + dg = sg == 0 ? 0 : max(255 - ((255 - bg) * 255) / sg, 0); + db = sb == 0 ? 0 : max(255 - ((255 - bb) * 255) / sb, 0); + }, + + darken: function() { + dr = br < sr ? br : sr; + dg = bg < sg ? bg : sg; + db = bb < sb ? bb : sb; + }, + + lighten: function() { + dr = br > sr ? br : sr; + dg = bg > sg ? bg : sg; + db = bb > sb ? bb : sb; + }, + + difference: function() { + dr = br - sr; + if (dr < 0) + dr = -dr; + dg = bg - sg; + if (dg < 0) + dg = -dg; + db = bb - sb; + if (db < 0) + db = -db; + }, + + exclusion: function() { + dr = br + sr * (255 - br - br) / 255; + dg = bg + sg * (255 - bg - bg) / 255; + db = bb + sb * (255 - bb - bb) / 255; + }, + + hue: function() { + setSat(sr, sg, sb, getSat(br, bg, bb)); + setLum(dr, dg, db, getLum(br, bg, bb)); + }, + + saturation: function() { + setSat(br, bg, bb, getSat(sr, sg, sb)); + setLum(dr, dg, db, getLum(br, bg, bb)); + }, + + luminosity: function() { + setLum(br, bg, bb, getLum(sr, sg, sb)); + }, + + color: function() { + setLum(sr, sg, sb, getLum(br, bg, bb)); + }, + + add: function() { + dr = min(br + sr, 255); + dg = min(bg + sg, 255); + db = min(bb + sb, 255); + }, + + subtract: function() { + dr = max(br - sr, 0); + dg = max(bg - sg, 0); + db = max(bb - sb, 0); + }, + + average: function() { + dr = (br + sr) / 2; + dg = (bg + sg) / 2; + db = (bb + sb) / 2; + }, + + negation: function() { + dr = 255 - abs(255 - sr - br); + dg = 255 - abs(255 - sg - bg); + db = 255 - abs(255 - sb - bb); + } + }; + + var process = modes[blendMode]; + if (!process) + return; + + for (var i = 0, l = dst.length; i < l; i += 4) { + sr = src[i]; + br = dst[i]; + sg = src[i + 1]; + bg = dst[i + 1]; + sb = src[i + 2]; + bb = dst[i + 2]; + sa = src[i + 3]; + ba = dst[i + 3]; + process(); + var a1 = sa * alpha / 255, + a2 = 1 - a1; + dst[i] = a1 * dr + a2 * br; + dst[i + 1] = a1 * dg + a2 * bg; + dst[i + 2] = a1 * db + a2 * bb; + dst[i + 3] = sa * alpha + a2 * ba; + } + dstContext.putImageData(dstData, offset.x, offset.y); + } +}; + +var PaperScript = this.PaperScript = new function() { +var parse_js=new function(){function W(a,b,c){var d=[];for(var e=0;e0,g=j(function(){return h(a[0]?k(["case",z(a[0])+":"]):"default:")},.5)+(f?e+j(function(){return u(a[1]).join(e)}):"");!c&&f&&d0?h(a):a}).join(e)},block:w,"var":function(a){return"var "+l(W(a,x))+";"},"const":function(a){return"const "+l(W(a,x))+";"},"try":function(a,b,c){var d=["try",w(a)];b&&d.push("catch","("+b[0]+")",w(b[1])),c&&d.push("finally",w(c));return k(d)},"throw":function(a){return k(["throw",z(a)])+";"},"new":function(a,b){b=b.length>0?"("+l(W(b,z))+")":"";return k(["new",m(a,"seq","binary","conditional","assign",function(a){var b=N(),c={};try{b.with_walkers({call:function(){throw c},"function":function(){return this}},function(){b.walk(a)})}catch(d){if(d===c)return!0;throw d}})+b])},"switch":function(a,b){return k(["switch","("+z(a)+")",v(b)])},"break":function(a){var b="break";a!=null&&(b+=" "+g(a));return b+";"},"continue":function(a){var b="continue";a!=null&&(b+=" "+g(a));return b+";"},conditional:function(a,b,c){return k([m(a,"assign","seq","conditional"),"?",m(b,"seq"),":",m(c,"seq")])},assign:function(a,b,c){a&&a!==!0?a+="=":a="=";return k([z(b),a,m(c,"seq")])},dot:function(a){var b=z(a),c=1;a[0]=="num"?/\./.test(a[1])||(b+="."):o(a)&&(b="("+b+")");while(cB[b[1]])d="("+d+")";if(L(c[0],["assign","conditional","seq"])||c[0]=="binary"&&B[a]>=B[c[1]]&&(c[1]!=a||!L(a,["&&","||","*"])))e="("+e+")";return k([d,a,e])},"unary-prefix":function(a,b){var c=z(b);b[0]=="num"||b[0]=="unary-prefix"&&!M(i,a+b[1])||!o(b)||(c="("+c+")");return a+(p(a.charAt(0))?" ":"")+c},"unary-postfix":function(a,b){var c=z(b);b[0]=="num"||b[0]=="unary-postfix"&&!M(i,a+b[1])||!o(b)||(c="("+c+")");return c+a},sub:function(a,b){var c=z(a);o(a)&&(c="("+c+")");return c+"["+z(b)+"]"},object:function(a){return a.length==0?"{}":"{"+e+j(function(){return W(a,function(a){if(a.length==3)return h(t(a[0],a[1][2],a[1][3],a[2]));var d=a[0],e=z(a[1]);b.quote_keys?d=Q(d):(typeof d=="number"||!c&&+d+""==d)&&parseFloat(d)>=0?d=q(+d):V(d)||(d=Q(d));return h(k(c&&b.space_colon?[d,":",e]:[d+":",e]))}).join(","+e)})+e+h("}")},regexp:function(a,b){return"/"+a+"/"+b},array:function(a){return a.length==0?"[]":k(["[",l(W(a,function(a){return!c&&a[0]=="atom"&&a[1]=="undefined"?"":m(a,"seq")})),"]"])},stat:function(a){return z(a).replace(/;*\s*$/,";")},seq:function(){return l(W(J(arguments),z))},label:function(a,b){return k([g(a),":",z(b)])},"with":function(a,b){return k(["with","("+z(a)+")",z(b)])},atom:function(a){return g(a)}},y=[];return z(a)}function Q(a){var b=0,c=0;a=a.replace(/[\\\b\f\n\r\t\x22\x27]/g,function(a){switch(a){case"\\":return"\\\\";case"\b":return"\\b";case"\f":return"\\f";case"\n":return"\\n";case"\r":return"\\r";case"\t":return"\\t";case'"':++b;return'"';case"'":++c;return"'"}return a});return b>c?"'"+a.replace(/\x27/g,"\\'")+"'":'"'+a.replace(/\x22/g,'\\"')+'"'}function O(a){return!a||a[0]=="block"&&(!a[1]||a[1].length==0)}function N(){function g(a,b){var c={},e;for(e in a)M(a,e)&&(c[e]=d[e],d[e]=a[e]);var f=b();for(e in c)M(c,e)&&(c[e]?d[e]=c[e]:delete d[e]);return f}function f(a){if(a==null)return null;try{e.push(a);var b=a[0],f=d[b];if(f){var g=f.apply(a,a.slice(1));if(g!=null)return g}f=c[b];return f.apply(a,a.slice(1))}finally{e.pop()}}function b(a){var b=[this[0]];a!=null&&b.push(W(a,f));return b}function a(a){return[this[0],W(a,function(a){var b=[a[0]];a.length>1&&(b[1]=f(a[1]));return b})]}var c={string:function(a){return[this[0],a]},num:function(a){return[this[0],a]},name:function(a){return[this[0],a]},toplevel:function(a){return[this[0],W(a,f)]},block:b,splice:b,"var":a,"const":a,"try":function(a,b,c){return[this[0],W(a,f),b!=null?[b[0],W(b[1],f)]:null,c!=null?W(c,f):null]},"throw":function(a){return[this[0],f(a)]},"new":function(a,b){return[this[0],f(a),W(b,f)]},"switch":function(a,b){return[this[0],f(a),W(b,function(a){return[a[0]?f(a[0]):null,W(a[1],f)]})]},"break":function(a){return[this[0],a]},"continue":function(a){return[this[0],a]},conditional:function(a,b,c){return[this[0],f(a),f(b),f(c)]},assign:function(a,b,c){return[this[0],a,f(b),f(c)]},dot:function(a){return[this[0],f(a)].concat(J(arguments,1))},call:function(a,b){return[this[0],f(a),W(b,f)]},"function":function(a,b,c){return[this[0],a,b.slice(),W(c,f)]},defun:function(a,b,c){return[this[0],a,b.slice(),W(c,f)]},"if":function(a,b,c){return[this[0],f(a),f(b),f(c)]},"for":function(a,b,c,d){return[this[0],f(a),f(b),f(c),f(d)]},"for-in":function(a,b,c,d){return[this[0],f(a),f(b),f(c),f(d)]},"while":function(a,b){return[this[0],f(a),f(b)]},"do":function(a,b){return[this[0],f(a),f(b)]},"return":function(a){return[this[0],f(a)]},binary:function(a,b,c){return[this[0],a,f(b),f(c)]},"unary-prefix":function(a,b){return[this[0],a,f(b)]},"unary-postfix":function(a,b){return[this[0],a,f(b)]},sub:function(a,b){return[this[0],f(a),f(b)]},object:function(a){return[this[0],W(a,function(a){return a.length==2?[a[0],f(a[1])]:[a[0],f(a[1]),a[2]]})]},regexp:function(a,b){return[this[0],a,b]},array:function(a){return[this[0],W(a,f)]},stat:function(a){return[this[0],f(a)]},seq:function(){return[this[0]].concat(W(J(arguments),f))},label:function(a,b){return[this[0],a,f(b)]},"with":function(a,b){return[this[0],f(a),f(b)]},atom:function(a){return[this[0],a]}},d={},e=[];return{walk:f,with_walkers:g,parent:function(){return e[e.length-2]},stack:function(){return e}}}function M(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function L(a,b){for(var c=b.length;--c>=0;)if(b[c]===a)return!0;return!1}function K(a){return a.split("")}function J(a,b){return Array.prototype.slice.call(a,b||0)}function I(a){var b={};for(var c=0;c0;++b)arguments[b]();return a}function G(a){var b=J(arguments,1);return function(){return a.apply(this,b.concat(J(arguments)))}}function F(a,b,c){function bk(a){try{++d.in_loop;return a()}finally{--d.in_loop}}function bi(a){var b=bg(a),c=d.token.value;if(e("operator")&&M(A,c)){if(bh(b)){g();return p("assign",A[c],b,bi(a))}i("Invalid assignment")}return b}function bh(a){if(!b)return!0;switch(a[0]){case"dot":case"sub":case"new":case"call":return!0;case"name":return a[1]!="this"}}function bg(a){var b=bf(a);if(e("operator","?")){g();var c=bj(!1);m(":");return p("conditional",b,c,bj(!1,a))}return b}function bf(a){return be(Y(!0),0,a)}function be(a,b,c){var f=e("operator")?d.token.value:null;f&&f=="in"&&c&&(f=null);var h=f!=null?B[f]:null;if(h!=null&&h>b){g();var i=be(Y(!0),h,c);return be(p("binary",f,a,i),b,c)}return a}function bd(a,b,c){(b=="++"||b=="--")&&!bh(c)&&i("Invalid use of "+b+" operator");return p(a,b,c)}function bc(a,b){if(e("punc",".")){g();return bc(p("dot",a,bb()),b)}if(e("punc","[")){g();return bc(p("sub",a,H(bj,G(m,"]"))),b)}if(b&&e("punc","(")){g();return bc(p("call",a,Z(")")),!0)}return b&&e("operator")&&M(z,d.token.value)?H(G(bd,"unary-postfix",d.token.value,a),g):a}function bb(){switch(d.token.type){case"name":case"operator":case"keyword":case"atom":return H(d.token.value,g);default:k()}}function ba(){switch(d.token.type){case"num":case"string":return H(d.token.value,g)}return bb()}function _(){var a=!0,c=[];while(!e("punc","}")){a?a=!1:m(",");if(!b&&e("punc","}"))break;var f=d.token.type,h=ba();f!="name"||h!="get"&&h!="set"||!!e("punc",":")?(m(":"),c.push([h,bj(!1)])):c.push([bb(),P(!1),h])}g();return p("object",c)}function $(){return p("array",Z("]",!b,!0))}function Z(a,b,c){var d=!0,f=[];while(!e("punc",a)){d?d=!1:m(",");if(b&&e("punc",a))break;e("punc",",")&&c?f.push(["atom","undefined"]):f.push(bj(!1))}g();return f}function X(){var a=Y(!1),b;e("punc","(")?(g(),b=Z(")")):b=[];return bc(p("new",a,b),!0)}function W(){return p("const",U())}function V(a){return p("var",U(a))}function U(a){var b=[];for(;;){e("name")||k();var c=d.token.value;g(),e("operator","=")?(g(),b.push([c,bj(!1,a)])):b.push([c]);if(!e("punc",","))break;g()}return b}function T(){var a=R(),b,c;if(e("keyword","catch")){g(),m("("),e("name")||i("Name expected");var f=d.token.value;g(),m(")"),b=[f,R()]}e("keyword","finally")&&(g(),c=R()),!b&&!c&&i("Missing catch/finally blocks");return p("try",a,b,c)}function R(){m("{");var a=[];while(!e("punc","}"))e("eof")&&k(),a.push(t());g();return a}function Q(){var a=q(),b=t(),c;e("keyword","else")&&(g(),c=t());return p("if",a,b,c)}function O(a){var b=a[0]=="var"?p("name",a[1][0]):a;g();var c=bj();m(")");return p("for-in",a,b,c,bk(t))}function N(a){m(";");var b=e("punc",";")?null:bj();m(";");var c=e("punc",")")?null:bj();m(")");return p("for",a,b,c,bk(t))}function K(){m("(");var a=null;if(!e("punc",";")){a=e("keyword","var")?(g(),V(!0)):bj(!0,!0);if(e("operator","in"))return O(a)}return N(a)}function I(a){var b;n()||(b=e("name")?d.token.value:null),b!=null?(g(),L(b,d.labels)||i("Label "+b+" without matching loop or statement")):d.in_loop==0&&i(a+" not inside a loop or switch"),o();return p(a,b)}function F(){return p("stat",H(bj,o))}function w(a){d.labels.push(a);var c=d.token,e=t();b&&!M(C,e[0])&&k(c),d.labels.pop();return p("label",a,e)}function s(a){return c?function(){var b=d.token,c=a.apply(this,arguments);c[0]=r(c[0],b,h());return c}:a}function r(a,b,c){return a instanceof E?a:new E(a,b,c)}function q(){m("(");var a=bj();m(")");return a}function p(){return J(arguments)}function o(){e("punc",";")?g():n()||k()}function n(){return!b&&(d.token.nlb||e("eof")||e("punc","}"))}function m(a){return l("punc",a)}function l(a,b){if(e(a,b))return g();j(d.token,"Unexpected token "+d.token.type+", expected "+a)}function k(a){a==null&&(a=d.token),j(a,"Unexpected token: "+a.type+" ("+a.value+")")}function j(a,b){i(b,a.line,a.col)}function i(a,b,c,e){var f=d.input.context();u(a,b!=null?b:f.tokline,c!=null?c:f.tokcol,e!=null?e:f.tokpos)}function h(){return d.prev}function g(){d.prev=d.token,d.peeked?(d.token=d.peeked,d.peeked=null):d.token=d.input();return d.token}function f(){return d.peeked||(d.peeked=d.input())}function e(a,b){return v(d.token,a,b)}var d={input:typeof a=="string"?x(a,!0):a,token:null,prev:null,peeked:null,in_function:0,in_loop:0,labels:[]};d.token=g();var t=s(function(){e("operator","/")&&(d.peeked=null,d.token=d.input(!0));switch(d.token.type){case"num":case"string":case"regexp":case"operator":case"atom":return F();case"name":return v(f(),"punc",":")?w(H(d.token.value,g,g)):F();case"punc":switch(d.token.value){case"{":return p("block",R());case"[":case"(":return F();case";":g();return p("block");default:k()};case"keyword":switch(H(d.token.value,g)){case"break":return I("break");case"continue":return I("continue");case"debugger":o();return p("debugger");case"do":return function(a){l("keyword","while");return p("do",H(q,o),a)}(bk(t));case"for":return K();case"function":return P(!0);case"if":return Q();case"return":d.in_function==0&&i("'return' outside of function");return p("return",e("punc",";")?(g(),null):n()?null:H(bj,o));case"switch":return p("switch",q(),S());case"throw":return p("throw",H(bj,o));case"try":return T();case"var":return H(V,o);case"const":return H(W,o);case"while":return p("while",q(),bk(t));case"with":return p("with",q(),t());default:k()}}}),P=s(function(a){var b=e("name")?H(d.token.value,g):null;a&&!b&&k(),m("(");return p(a?"defun":"function",b,function(a,b){while(!e("punc",")"))a?a=!1:m(","),e("name")||k(),b.push(d.token.value),g();g();return b}(!0,[]),function(){++d.in_function;var a=d.in_loop;d.in_loop=0;var b=R();--d.in_function,d.in_loop=a;return b}())}),S=G(bk,function(){m("{");var a=[],b=null;while(!e("punc","}"))e("eof")&&k(),e("keyword","case")?(g(),b=[],a.push([bj(),b]),m(":")):e("keyword","default")?(g(),m(":"),b=[],a.push([null,b])):(b||k(),b.push(t()));g();return a}),Y=s(function(a){if(e("operator","new")){g();return X()}if(e("operator")&&M(y,d.token.value))return bd("unary-prefix",H(d.token.value,g),Y(a));if(e("punc")){switch(d.token.value){case"(":g();return bc(H(bj,G(m,")")),a);case"[":g();return bc($(),a);case"{":g();return bc(_(),a)}k()}if(e("keyword","function")){g();return bc(P(!1),a)}if(M(D,d.token.type)){var b=d.token.type=="regexp"?p("regexp",d.token.value[0],d.token.value[1]):p(d.token.type,d.token.value);return bc(H(b,g),a)}k()}),bj=s(function(a,b){arguments.length==0&&(a=!0);var c=bi(b);if(a&&e("punc",",")){g();return p("seq",c,bj(!0,b))}return c});return p("toplevel",function(a){while(!e("eof"))a.push(t());return a}([]))}function E(a,b,c){this.name=a,this.start=b,this.end=c}function x(b){function P(a){if(a)return I();y(),v();var b=g();if(!b)return x("eof");if(o(b))return C();if(b=='"'||b=="'")return F();if(M(l,b))return x("punc",h());if(b==".")return L();if(b=="/")return K();if(M(e,b))return J();if(b=="\\"||q(b))return N();B("Unexpected character '"+b+"'")}function O(a,b){try{return b()}catch(c){if(c===w)B(a);else throw c}}function N(){var b=A(r);return M(a,b)?M(i,b)?x("operator",b):M(d,b)?x("atom",b):x("keyword",b):x("name",b)}function L(){h();return o(g())?C("."):x("punc",".")}function K(){h();var a=f.regex_allowed;switch(g()){case"/":f.comments_before.push(G()),f.regex_allowed=a;return P();case"*":f.comments_before.push(H()),f.regex_allowed=a;return P()}return f.regex_allowed?I():J("/")}function J(a){function b(a){if(!g())return a;var c=a+g();if(M(i,c)){h();return b(c)}return a}return x("operator",b(a||h()))}function I(){return O("Unterminated regular expression",function(){var a=!1,b="",c,d=!1;while(c=h(!0))if(a)b+="\\"+c,a=!1;else if(c=="[")d=!0,b+=c;else if(c=="]"&&d)d=!1,b+=c;else{if(c=="/"&&!d)break;c=="\\"?a=!0:b+=c}var e=A(function(a){return M(m,a)});return x("regexp",[b,e])})}function H(){h();return O("Unterminated multiline comment",function(){var a=t("*/",!0),b=f.text.substring(f.pos,a),c=x("comment2",b,!0);f.pos=a+2,f.line+=b.split("\n").length-1,f.newline_before=b.indexOf("\n")>=0;return c})}function G(){h();var a=t("\n"),b;a==-1?(b=f.text.substr(f.pos),f.pos=f.text.length):(b=f.text.substring(f.pos,a),f.pos=a);return x("comment1",b,!0)}function F(){return O("Unterminated string constant",function(){var a=h(),b="";for(;;){var c=h(!0);if(c=="\\")c=D();else if(c==a)break;b+=c}return x("string",b)})}function E(a){var b=0;for(;a>0;--a){var c=parseInt(h(!0),16);isNaN(c)&&B("Invalid hex-character pattern in string"),b=b<<4|c}return b}function D(){var a=h(!0);switch(a){case"n":return"\n";case"r":return"\r";case"t":return"\t";case"b":return"\b";case"v":return" ";case"f":return"\f";case"0":return"";case"x":return String.fromCharCode(E(2));case"u":return String.fromCharCode(E(4));case"\n":return"";default:return a}}function C(a){var b=!1,c=!1,d=!1,e=a==".",f=A(function(f,g){if(f=="x"||f=="X")return d?!1:d=!0;if(!d&&(f=="E"||f=="e"))return b?!1:b=c=!0;if(f=="-")return c||g==0&&!a?!0:!1;if(f=="+")return c;c=!1;if(f==".")return!e&&!d?e=!0:!1;return p(f)});a&&(f=a+f);var g=s(f);if(!isNaN(g))return x("num",g);B("Invalid syntax: "+f)}function B(a){u(a,f.tokline,f.tokcol,f.tokpos)}function A(a){var b="",c=g(),d=0;while(c&&a(c,d++))b+=h(),c=g();return b}function y(){while(M(j,g()))h()}function x(a,b,d){f.regex_allowed=a=="operator"&&!M(z,b)||a=="keyword"&&M(c,b)||a=="punc"&&M(k,b);var e={type:a,value:b,line:f.tokline,col:f.tokcol,pos:f.tokpos,nlb:f.newline_before};d||(e.comments_before=f.comments_before,f.comments_before=[]),f.newline_before=!1;return e}function v(){f.tokline=f.line,f.tokcol=f.col,f.tokpos=f.pos}function t(a,b){var c=f.text.indexOf(a,f.pos);if(b&&c==-1)throw w;return c}function n(){return!f.peek()}function h(a){var b=f.text.charAt(f.pos++);if(a&&!b)throw w;b=="\n"?(f.newline_before=!0,++f.line,f.col=0):++f.col;return b}function g(){return f.text.charAt(f.pos)}var f={text:b.replace(/\r\n?|[\n\u2028\u2029]/g,"\n").replace(/^\uFEFF/,""),pos:0,tokpos:0,line:0,tokline:0,col:0,tokcol:0,newline_before:!1,regex_allowed:!1,comments_before:[]};P.context=function(a){a&&(f=a);return f};return P}function v(a,b,c){return a.type==b&&(c==null||a.value==c)}function u(a,b,c,d){throw new t(a,b,c,d)}function t(a,b,c,d){this.message=a,this.line=b,this.col=c,this.pos=d}function s(a){if(f.test(a))return parseInt(a.substr(2),16);if(g.test(a))return parseInt(a.substr(1),8);if(h.test(a))return parseFloat(a)}function r(a){return q(a)||o(a)}function q(a){return a=="$"||a=="_"||n(a)}function p(a){return o(a)||n(a)}function o(a){a=a.charCodeAt(0);return a>=48&&a<=57}function n(a){a=a.charCodeAt(0);return a>=65&&a<=90||a>=97&&a<=122}var a=I(["break","case","catch","const","continue","default","delete","do","else","finally","for","function","if","in","instanceof","new","return","switch","throw","try","typeof","var","void","while","with"]),b=I(["abstract","boolean","byte","char","class","debugger","double","enum","export","extends","final","float","goto","implements","import","int","interface","long","native","package","private","protected","public","short","static","super","synchronized","throws","transient","volatile"]),c=I(["return","new","delete","throw","else","case"]),d=I(["false","null","true","undefined"]),e=I(K("+-*&%=<>!?|~^")),f=/^0x[0-9a-f]+$/i,g=/^0[0-7]+$/,h=/^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i,i=I(["in","instanceof","typeof","new","void","delete","++","--","+","-","!","~","&","|","^","*","/","%",">>","<<",">>>","<",">","<=",">=","==","===","!=","!==","?","=","+=","-=","/=","*=","%=",">>=","<<=",">>>=","|=","^=","&=","&&","||"]),j=I(K(" \n\r\t")),k=I(K("[{}(,.;:")),l=I(K("[]{}(),;:")),m=I(K("gmsiy"));t.prototype.toString=function(){return this.message+" (line: "+this.line+", col: "+this.col+", pos: "+this.pos+")"};var w={},y=I(["typeof","void","delete","--","++","!","~","-","+"]),z=I(["--","++"]),A=function(a,b,c){while(c>=","<<=",">>>=","|=","^=","&="],{"=":!0},0),B=function(a,b){for(var c=0,d=1;c","<=",">=","in","instanceof"],[">>","<<",">>>"],["+","-"],["*","/","%"]],{}),C=I(["for","do","while","switch"]),D=I(["atom","num","string","regexp","name"]);E.prototype.toString=function(){return this.name};var P=I(["name","array","object","string","dot","sub","call","regexp"]),R=I(["if","while","do","for","for-in","with"]);return{parse:F,gen_code:S,tokenizer:x,ast_walker:N}} + + // Math Operators + + var operators = { + '+': 'add', + '-': 'subtract', + '*': 'multiply', + '/': 'divide', + '%': 'modulo', + '==': 'equals', + '!=': 'equals' + }; + + function $eval(left, operator, right) { + var handler = operators[operator]; + if (left && left[handler]) { + var res = left[handler](right); + return operator == '!=' ? !res : res; + } + switch (operator) { + case '+': return left + right; + case '-': return left - right; + case '*': return left * right; + case '/': return left / right; + case '%': return left % right; + case '==': return left == right; + case '!=': return left != right; + default: + throw new Error('Implement Operator: ' + operator); + } + }; + + // Sign Operators + + var signOperators = { + '-': 'negate' + }; + + function $sign(operator, value) { + var handler = signOperators[operator]; + if (value && value[handler]) { + return value[handler](); + } + switch (operator) { + case '+': return +value; + case '-': return -value; + default: + throw new Error('Implement Sign Operator: ' + operator); + } + } + + // AST Helpers + + function isDynamic(exp) { + var type = exp[0]; + return type != 'num' && type != 'string'; + } + + function handleOperator(operator, left, right) { + // Only replace operators with calls to $operator if the left hand side + // is potentially an object. + if (operators[operator] && isDynamic(left)) { + // Replace with call to $operator(left, operator, right): + return ['call', ['name', '$eval'], + [left, ['string', operator], right]]; + } + } + + /** + * Compiles PaperScript code into JavaScript code. + * + * @name PaperScript.compile + * @function + * @param {String} code The PaperScript code. + * @return {String} The compiled PaperScript as JavaScript code. + */ + function compile(code) { + // Use parse-js to translate the code into a AST structure which is then + // walked and parsed for operators to overload. The resulting AST is + // translated back to code and evaluated. + var ast = parse_js.parse(code), + walker = parse_js.ast_walker(), + walk = walker.walk; + + ast = walker.with_walkers({ + 'binary': function(operator, left, right) { + // Handle simple mathematical operators here: + return handleOperator(operator, left = walk(left), + right = walk(right)) + // Always return something since we're walking left and + || [this[0], operator, left, right]; + }, + + 'assign': function(operator, left, right) { + var res = handleOperator(operator, left = walk(left), + right = walk(right)); + if (res) + return [this[0], true, left, res]; + return [this[0], operator, left, right]; + }, + + 'unary-prefix': function(operator, exp) { + if (signOperators[operator] && isDynamic(exp)) { + return ['call', ['name', '$sign'], + [['string', operator], walk(exp)]]; + } + } + }, function() { + return walk(ast); + }); + + return parse_js.gen_code(ast, { + beautify: true + }); + } + + function evaluate(code, scope) { + paper = scope; + var view = scope.view, + tool = /on(?:Key|Mouse)(?:Up|Down|Move|Drag)/.test(code) + && new Tool(), + res; + with (scope) { + (function() { + var onEditOptions, onSelect, onDeselect, onReselect, onMouseDown, + onMouseUp, onMouseDrag, onMouseMove, onKeyDown, onKeyUp, + onFrame, onResize, + handlers = [ 'onEditOptions', 'onSelect', 'onDeselect', + 'onReselect', 'onMouseDown', 'onMouseUp', 'onMouseDrag', + 'onMouseMove', 'onKeyDown', 'onKeyUp']; + res = eval(compile(code)); + if (tool) { + Base.each(handlers, function(key) { + tool[key] = eval(key); + }); + } + if (view) { + view.onResize = onResize; + view.setOnFrame(onFrame); + view.draw(); + } + }).call(scope); + } + return res; + } + + function request(url, scope) { + var xhr = new (window.ActiveXObject || XMLHttpRequest)( + 'Microsoft.XMLHTTP'); + xhr.open('GET', url, true); + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + return evaluate(xhr.responseText, scope); + } + }; + return xhr.send(null); + } + + function load() { + var scripts = document.getElementsByTagName('script'); + for (var i = 0, l = scripts.length; i < l; i++) { + var script = scripts[i]; + if (/^text\/(?:x-|)paperscript$/.test(script.type) + && !script.getAttribute('data-paper-loaded')) { + var scope = new PaperScope(script); + scope.setup(PaperScript.getAttribute(script, 'canvas')); + if (script.src) { + request(script.src, scope); + } else { + evaluate(script.innerHTML, scope); + } + script.setAttribute('data-paper-loaded', true); + } + } + } + + DomEvent.add(window, { load: load }); + + function handleAttribute(name) { + name += 'Attribute'; + return function(el, attr) { + return el[name](attr) || el[name]('data-paper-' + attr); + }; + } + + return { + compile: compile, + evaluate: evaluate, + load: load, + getAttribute: handleAttribute('get'), + hasAttribute: handleAttribute('has') + }; + +}; + +this.load = PaperScript.load; + +Base.each(this, function(val, key) { + if (val && val.prototype instanceof Base) { + val._name = key; + } +}); + +this.enumerable = true; +return new (PaperScope.inject(this)); +}; \ No newline at end of file diff --git a/ajax/libs/paper.js/0.22/paper.min.js b/ajax/libs/paper.js/0.22/paper.min.js new file mode 100644 index 000000000..7bfea30a9 --- /dev/null +++ b/ajax/libs/paper.js/0.22/paper.min.js @@ -0,0 +1,5 @@ +var paper=new function(){var Base=new function(){function e(e,t,i){if(g)try{return delete e[t],g(e,t,i)}catch(n){}return(i.get||i.set)&&e.__defineGetter__?(i.get&&e.__defineGetter__(t,i.get),i.set&&e.__defineSetter__(t,i.set)):e[t]=i.value,e}function t(e,t){if(y)try{return y(e,t)}catch(i){}var n=e.__lookupGetter__&&e.__lookupGetter__(t);return n?{get:n,set:e.__lookupSetter__(t),enumerable:!0,configurable:!0}:c.call(e,t)?{value:e[t],enumerable:!0,configurable:!0,writable:!0}:null}function i(i,n,r,s,o,a){function h(a,l,h,f){var l=l||(l=t(n,a))&&(l.get?l:l.value),m="function"==typeof l,g=l,y=o||m?l&&l.get?a in i:i[a]:null;if(!f||!m||o&&f[a]||(f[a]=function(e){return e&&i[a].apply(e,p.call(arguments,1))}),(h||void 0!==l&&c.call(n,a))&&(!o||!y)){if(m){if(y&&/\bthis\.base\b/.test(l)){var v=s&&s[a]==y;g=function(){var i=t(this,"base");e(this,"base",{value:v?s[a]:y,configurable:!0});try{return l.apply(this,arguments)}finally{i?e(this,"base",i):delete this.base}},g.toString=function(){return""+l},g.valueOf=function(){return l.valueOf()}}u&&0==l.length&&(d=a.match(/^(get|is)(([A-Z])(.*))$/))&&u.push([d[3].toLowerCase()+d[4],d[2]])}(!g||m||!g.get&&!g.set)&&(g={value:g,writable:!0}),(t(i,a)||{configurable:!0}).configurable&&(g.configurable=!0,g.enumerable=r),e(i,a,g)}}var u,d;if(n){u=[];for(var f in n)c.call(n,f)&&!l.test(f)&&h(f,null,!0,a);h("toString"),h("valueOf");for(var m=0,g=u&&u.length;g>m;m++)try{var d=u[m],y=d[1];h(d[0],{get:i["get"+y]||i["is"+y],set:i["set"+y]},!0)}catch(v){}}return i}function n(t){var i=function(n){return a&&e(this,"__proto__",{value:t}),this.initialize&&n!==i.dont?this.initialize.apply(this,arguments):void 0};return i.prototype=t,i.toString=function(){return""+(this.prototype.initialize||function(){})},i}function r(e){return e?"function"!=typeof e?function(t){return t==e}:e:function(e){return e}}function s(e,t,i,n){try{e&&(n||void 0===n&&d(e)?f:m).call(e,r(t),i=i||e)}catch(s){if(s!==Base.stop)throw s}return i}function o(e){return s(e,function(e,t){this[t]=e},new e.constructor)}var a=!this.__proto__,l=/^(statics|generics|preserve|enumerable|prototype|__proto__|toString|valueOf)$/,h=Object.prototype,c=a?function(e){return"__proto__"!==e&&this.hasOwnProperty(e)}:h.hasOwnProperty,u=h.toString,h=Array.prototype,d=Array.isArray=Array.isArray||function(e){return"[object Array]"===u.call(e)},p=h.slice,f=h.forEach=h.forEach||function(e,t){for(var i=0,n=this.length;n>i;i++)e.call(t,this[i],i,this)},m=function(e,t){for(var i in this)this.hasOwnProperty(i)&&e.call(t,this[i],i,this)},g=Object.defineProperty,y=Object.getOwnPropertyDescriptor;return i(function(){},{inject:function(e){if(e){var t=this.prototype,n=t.__proto__&&t.__proto__.constructor,r=1==e.statics?e:e.statics;r!=e&&i(t,e,e.enumerable,n&&n.prototype,e.preserve,e.generics&&this),i(this,r,!0,n,e.preserve)}for(var s=1,o=arguments.length;o>s;s++)this.inject(arguments[s]);return this},extend:function(){var t=new this(this.dont),r=n(t);return e(t,"constructor",{value:r,writable:!0,configurable:!0}),r.dont={},i(r,this,!0),arguments.length?this.inject.apply(r,arguments):r}},!0).inject({has:c,each:s,inject:function(){for(var e=0,t=arguments.length;t>e;e++)i(this,arguments[e]);return this},extend:function(){var e=new(n(this));return e.inject.apply(e,arguments)},each:function(e,t){return s(this,e,t)},clone:function(){return o(this)},statics:{each:s,clone:o,define:e,describe:t,iterator:r,has:function(e,t){return c.call(e,t)},type:function(e){return(e||0===e)&&(e._type||typeof e)||null},check:function(e){return!(!e&&0!==e)},pick:function(){for(var e=0,t=arguments.length;t>e;e++)if(void 0!==arguments[e])return arguments[e];return null},stop:{}}})};this.Base=Base.inject({generics:!0,clone:function(){return new this.constructor(this)},toString:function(){return"{ "+Base.each(this,function(e,t){if("_"!=t.charAt(0)){var i=typeof e;this.push(t+": "+("number"===i?Base.formatNumber(e):"string"===i?"'"+e+"'":e))}},[]).join(", ")+" }"},statics:{read:function(e,t,i){var t=t||0,i=i||e.length-t,n=e[t];return n instanceof this||this.prototype._readNull&&null==n&&1>=i?n:(n=new this(this.dont),n.initialize.apply(n,t>0||e.length>i?Array.prototype.slice.call(e,t,t+i):e)||n)},readAll:function(e,t){for(var i,n=[],r=t||0,s=e.length;s>r;r++)n.push(Array.isArray(i=e[r])?this.read(i,0):this.read(e,r,1));return n},splice:function(e,t,i,n){var r=t&&t.length,s=void 0===i;i=s?e.length:i;for(var o=0;r>o;o++)t[o]._index=i+o;if(s)return e.push.apply(e,t),[];var a=[i,n];t&&a.push.apply(a,t);for(var l=e.splice.apply(e,a),o=0,h=l.length;h>o;o++)delete l[o]._index;for(var o=i+r,h=e.length;h>o;o++)e[o]._index=o;return l},merge:function(){return Base.each(arguments,function(e){Base.each(e,function(e,t){this[t]=e},this)},new Base,!0)},capitalize:function(e){return e.replace(/\b[a-z]/g,function(e){return e.toUpperCase()})},camelize:function(e){return e.replace(/-(\w)/g,function(e,t){return t.toUpperCase()})},hyphenate:function(e){return e.replace(/[a-z][A-Z0-9]|[0-9][a-zA-Z]|[A-Z]{2}[a-z]/g,function(e){return e.charAt(0)+"-"+e.substring(1)}).toLowerCase()},formatNumber:function(e){return""+Math.round(1e5*e)/1e5}}});var PaperScope=this.PaperScope=Base.extend({initialize:function(e){paper=this,this.view=null,this.views=[],this.project=null,this.projects=[],this.tool=null,this.tools=[],this._id=e&&(e.getAttribute("id")||e.src)||"paperscope-"+PaperScope._id++,e&&e.setAttribute("id",this._id),PaperScope._scopes[this._id]=this},version:.22,evaluate:function(e){var t=PaperScript.evaluate(e,this);return View.updateFocus(),t},install:function(e){var t=this;Base.each(["project","view","tool"],function(i){Base.define(e,i,{configurable:!0,writable:!0,get:function(){return t[i]}})});for(var i in this)/^(version|_id|load)/.test(i)||i in e||(e[i]=this[i])},setup:function(e){paper=this,this.project=new Project,e&&(this.view=new View(e))},clear:function(){for(var e=this.projects.length-1;e>=0;e--)this.projects[e].remove();for(var e=this.views.length-1;e>=0;e--)this.views[e].remove();for(var e=this.tools.length-1;e>=0;e--)this.tools[e].remove()},remove:function(){this.clear(),delete PaperScope._scopes[this._id]},_needsRedraw:function(){if(!this._redrawNotified){for(var e=this.views.length-1;e>=0;e--)this.views[e]._redrawNeeded=!0;this._redrawNotified=!0}},statics:{_scopes:{},_id:0,get:function(e){return"object"==typeof e&&(e=e.getAttribute("id")),this._scopes[e]||null},each:function(e){Base.each(this._scopes,e)}}}),PaperScopeItem=Base.extend({initialize:function(e){this._scope=paper,this._index=this._scope[this._list].push(this)-1,(e||!this._scope[this._reference])&&this.activate()},activate:function(){return this._scope?(this._scope[this._reference]=this,!0):!1},remove:function(){return null==this._index?!1:(Base.splice(this._scope[this._list],null,this._index,1),this._scope[this._reference]==this&&(this._scope[this._reference]=null),this._scope=null,!0)}}),Point=this.Point=Base.extend({initialize:function(e,t){void 0!==t?(this.x=e,this.y=t):void 0!==e?null==e?this.x=this.y=0:void 0!==e.x?(this.x=e.x,this.y=e.y):void 0!==e.width?(this.x=e.width,this.y=e.height):Array.isArray(e)?(this.x=e[0],this.y=e.length>1?e[1]:e[0]):void 0!==e.angle?(this.x=e.length,this.y=0,this.setAngle(e.angle)):this.x=this.y="number"==typeof e?e:0:this.x=this.y=0},set:function(e,t){return this.x=e,this.y=t,this},clone:function(){return Point.create(this.x,this.y)},toString:function(){var e=Base.formatNumber;return"{ x: "+e(this.x)+", y: "+e(this.y)+" }"},add:function(e){return e=Point.read(arguments),Point.create(this.x+e.x,this.y+e.y)},subtract:function(e){return e=Point.read(arguments),Point.create(this.x-e.x,this.y-e.y)},multiply:function(e){return e=Point.read(arguments),Point.create(this.x*e.x,this.y*e.y)},divide:function(e){return e=Point.read(arguments),Point.create(this.x/e.x,this.y/e.y)},modulo:function(e){return e=Point.read(arguments),Point.create(this.x%e.x,this.y%e.y)},negate:function(){return Point.create(-this.x,-this.y)},transform:function(e){return e?e._transformPoint(this):this},getDistance:function(e,t){e=Point.read(arguments);var i=e.x-this.x,n=e.y-this.y,r=i*i+n*n;return t?r:Math.sqrt(r)},getLength:function(){var e=this.x*this.x+this.y*this.y;return arguments[0]?e:Math.sqrt(e)},setLength:function(e){if(this.isZero()){var t=this._angle||0;this.set(Math.cos(t)*e,Math.sin(t)*e)}else{var i=e/this.getLength();0==i&&this.getAngle(),this.set(this.x*i,this.y*i)}return this},normalize:function(e){void 0===e&&(e=1);var t=this.getLength(),i=0!=t?e/t:0,n=Point.create(this.x*i,this.y*i);return n._angle=this._angle,n},getAngle:function(){return 180*this.getAngleInRadians(arguments[0])/Math.PI},setAngle:function(e){if(e=this._angle=e*Math.PI/180,!this.isZero()){var t=this.getLength();this.set(Math.cos(e)*t,Math.sin(e)*t)}return this},getAngleInRadians:function(){if(void 0===arguments[0])return null==this._angle&&(this._angle=Math.atan2(this.y,this.x)),this._angle;var e=Point.read(arguments),t=this.getLength()*e.getLength();return 0==t?0/0:Math.acos(this.dot(e)/t)},getAngleInDegrees:function(){return this.getAngle(arguments[0])},getQuadrant:function(){return this.x>=0?this.y>=0?1:4:this.y>=0?2:3},getDirectedAngle:function(e){return e=Point.read(arguments),180*Math.atan2(this.cross(e),this.dot(e))/Math.PI},rotate:function(e,t){e=e*Math.PI/180;var i=t?this.subtract(t):this,n=Math.sin(e),r=Math.cos(e);return i=Point.create(i.x*r-i.y*n,i.y*r+i.x*n),t?i.add(t):i},equals:function(e){return e=Point.read(arguments),this.x==e.x&&this.y==e.y},isInside:function(e){return e.contains(this)},isClose:function(e,t){return t>this.getDistance(e)},isColinear:function(e){return this.cross(e)1?e[1]:e[0]):this.width=this.height="number"==typeof e?e:0:this.width=this.height=0},toString:function(){var e=Base.formatNumber;return"{ width: "+e(this.width)+", height: "+e(this.height)+" }"},set:function(e,t){return this.width=e,this.height=t,this},clone:function(){return Size.create(this.width,this.height)},add:function(e){return e=Size.read(arguments),Size.create(this.width+e.width,this.height+e.height)},subtract:function(e){return e=Size.read(arguments),Size.create(this.width-e.width,this.height-e.height)},multiply:function(e){return e=Size.read(arguments),Size.create(this.width*e.width,this.height*e.height)},divide:function(e){return e=Size.read(arguments),Size.create(this.width/e.width,this.height/e.height)},modulo:function(e){return e=Size.read(arguments),Size.create(this.width%e.width,this.height%e.height)},negate:function(){return Size.create(-this.width,-this.height)},equals:function(e){return e=Size.read(arguments),this.width==e.width&&this.height==e.height},isZero:function(){return 0==this.width&&0==this.height},isNaN:function(){return isNaN(this.width)||isNaN(this.height)},statics:{create:function(e,t){return new Size(Size.dont).set(e,t)},min:function(e,t){return Size.create(Math.min(e.width,t.width),Math.min(e.height,t.height))},max:function(e,t){return Size.create(Math.max(e.width,t.width),Math.max(e.height,t.height))},random:function(){return Size.create(Math.random(),Math.random())}}},new function(){return Base.each(["round","ceil","floor","abs"],function(e){var t=Math[e];this[e]=function(){return Size.create(t(this.width),t(this.height))}},{})}),LinkedSize=Size.extend({set:function(e,t,i){return this._width=e,this._height=t,i||this._owner[this._setter](this),this},getWidth:function(){return this._width},setWidth:function(e){this._width=e,this._owner[this._setter](this)},getHeight:function(){return this._height},setHeight:function(e){this._height=e,this._owner[this._setter](this)},statics:{create:function(e,t,i,n,r){if(r)return Size.create(i,n);var s=new LinkedSize(LinkedSize.dont);return s._width=i,s._height=n,s._owner=e,s._setter=t,s}}}),Rectangle=this.Rectangle=Base.extend({initialize:function(e,t,i,n){if(4==arguments.length)this.x=e,this.y=t,this.width=i,this.height=n;else if(2==arguments.length)if(t&&void 0!==t.x){var r=Point.read(arguments,0,1),s=Point.read(arguments,1,1);this.x=r.x,this.y=r.y,this.width=s.x-r.x,this.height=s.y-r.y,0>this.width&&(this.x=s.x,this.width=-this.width),0>this.height&&(this.y=s.y,this.height=-this.height)}else{var o=Point.read(arguments,0,1),a=Size.read(arguments,1,1);this.x=o.x,this.y=o.y,this.width=a.width,this.height=a.height}else e?(this.x=e.x||0,this.y=e.y||0,this.width=e.width||0,this.height=e.height||0):this.x=this.y=this.width=this.height=0},set:function(e,t,i,n){return this.x=e,this.y=t,this.width=i,this.height=n,this},getPoint:function(){return LinkedPoint.create(this,"setPoint",this.x,this.y,arguments[0])},setPoint:function(e){return e=Point.read(arguments),this.x=e.x,this.y=e.y,this},getSize:function(){return LinkedSize.create(this,"setSize",this.width,this.height,arguments[0])},setSize:function(e){return e=Size.read(arguments),this.width=e.width,this.height=e.height,this},getLeft:function(){return this.x},setLeft:function(e){return this.width-=e-this.x,this.x=e,this},getTop:function(){return this.y},setTop:function(e){return this.height-=e-this.y,this.y=e,this},getRight:function(){return this.x+this.width},setRight:function(e){return this.width=e-this.x,this},getBottom:function(){return this.y+this.height},setBottom:function(e){return this.height=e-this.y,this},getCenterX:function(){return this.x+.5*this.width},setCenterX:function(e){return this.x=e-.5*this.width,this},getCenterY:function(){return this.y+.5*this.height},setCenterY:function(e){return this.y=e-.5*this.height,this},getCenter:function(){return LinkedPoint.create(this,"setCenter",this.getCenterX(),this.getCenterY(),arguments[0])},setCenter:function(e){return e=Point.read(arguments),this.setCenterX(e.x).setCenterY(e.y)},equals:function(e){return e=Rectangle.read(arguments),this.x==e.x&&this.y==e.y&&this.width==e.width&&this.height==e.height},isEmpty:function(){return 0==this.width||0==this.height},toString:function(){var e=Base.formatNumber;return"{ x: "+e(this.x)+", y: "+e(this.y)+", width: "+e(this.width)+", height: "+e(this.height)+" }"},contains:function(e){return e&&void 0!==e.width||4==(Array.isArray(e)?e:arguments).length?this._containsRectangle(Rectangle.read(arguments)):this._containsPoint(Point.read(arguments))},_containsPoint:function(e){var t=e.x,i=e.y;return t>=this.x&&i>=this.y&&this.x+this.width>=t&&this.y+this.height>=i},_containsRectangle:function(e){var t=e.x,i=e.y;return t>=this.x&&i>=this.y&&t+e.width<=this.x+this.width&&i+e.height<=this.y+this.height},intersects:function(e){return e=Rectangle.read(arguments),e.x+e.width>this.x&&e.y+e.height>this.y&&e.x=4&&(e[1]+=n?"Y":"X");var r=e[n?0:1],s=e[n?1:0],o="get"+r,a="get"+s,l="set"+r,h="set"+s,c="get"+i,u="set"+i;this[c]=function(){return LinkedPoint.create(this,u,this[o](),this[a](),arguments[0])},this[u]=function(e){return e=Point.read(arguments),this[l](e.x)[h](e.y)}},{})}),LinkedRectangle=Rectangle.extend({set:function(e,t,i,n,r){return this._x=e,this._y=t,this._width=i,this._height=n,r||this._owner[this._setter](this),this},statics:{create:function(e,t,i,n,r,s){var o=new LinkedRectangle(LinkedRectangle.dont).set(i,n,r,s,!0);return o._owner=e,o._setter=t,o}}},new function(){var e=Rectangle.prototype;return Base.each(["x","y","width","height"],function(e){var t=Base.capitalize(e),i="_"+e;this["get"+t]=function(){return this[i]},this["set"+t]=function(e){this[i]=e,this._dontNotify||this._owner[this._setter](this)}},Base.each(["Point","Size","Center","Left","Top","Right","Bottom","CenterX","CenterY","TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],function(t){var i="set"+t;this[i]=function(){return this._dontNotify=!0,e[i].apply(this,arguments),delete this._dontNotify,this._owner[this._setter](this),this}},{}))}),Matrix=this.Matrix=Base.extend({initialize:function(e){var t=arguments.length,i=!0;if(6==t?this.set.apply(this,arguments):1==t?e instanceof Matrix?this.set(e._a,e._c,e._b,e._d,e._tx,e._ty):Array.isArray(e)?this.set.apply(this,e):i=!1:0==t?(this._a=this._d=1,this._c=this._b=this._tx=this._ty=0):i=!1,!i)throw Error("Unsupported matrix parameters")},clone:function(){return Matrix.create(this._a,this._c,this._b,this._d,this._tx,this._ty)},set:function(e,t,i,n,r,s){return this._a=e,this._c=t,this._b=i,this._d=n,this._tx=r,this._ty=s,this},scale:function(e,t,i){return 2>arguments.length||"object"==typeof t?(i=Point.read(arguments,1),t=e):i=Point.read(arguments,2),i&&this.translate(i),this._a*=e,this._c*=e,this._b*=t,this._d*=t,i&&this.translate(i.negate()),this},translate:function(e){e=Point.read(arguments);var t=e.x,i=e.y;return this._tx+=t*this._a+i*this._b,this._ty+=t*this._c+i*this._d,this},rotate:function(){return this.concatenate(Matrix.getRotateInstance.apply(Matrix,arguments))},shear:function(e,t,i){2>arguments.length||"object"==typeof t?(i=Point.read(arguments,1),t=e):i=Point.read(arguments,2),i&&this.translate(i);var n=this._a,r=this._c;return this._a+=t*this._b,this._c+=t*this._d,this._b+=e*n,this._d+=e*r,i&&this.translate(i.negate()),this},toString:function(){var e=Base.formatNumber;return"[["+[e(this._a),e(this._b),e(this._tx)].join(", ")+"], ["+[e(this._c),e(this._d),e(this._ty)].join(", ")+"]]"},getValues:function(){return[this._a,this._c,this._b,this._d,this._tx,this._ty]},concatenate:function(e){var t=this._a,i=this._b,n=this._c,r=this._d;return this._a=e._a*t+e._c*i,this._b=e._b*t+e._d*i,this._tx+=e._tx*t+e._ty*i,this._c=e._a*n+e._c*r,this._d=e._b*n+e._d*r,this._ty+=e._tx*n+e._ty*r,this},preConcatenate:function(e){var t=this._a,i=this._b,n=this._c,r=this._d,s=this._tx,o=this._ty;return this._a=e._a*t+e._b*n,this._c=e._c*t+e._d*n,this._b=e._a*i+e._b*r,this._d=e._c*i+e._d*r,this._tx=e._a*s+e._b*o+e._tx,this._ty=e._c*s+e._d*o+e._ty,this},transform:function(e,t,i,n,r){return 5>arguments.length?this._transformPoint(Point.read(arguments)):this._transformCoordinates(e,t,i,n,r)},_transformPoint:function(e,t,i){var n=e.x,r=e.y;return t||(t=new Point(Point.dont)),t.set(n*this._a+r*this._b+this._tx,n*this._c+r*this._d+this._ty,i)},_transformCoordinates:function(e,t,i,n,r){for(var s=t,o=n,a=t+2*r;a>s;){var l=e[s++],h=e[s++];i[o++]=l*this._a+h*this._b+this._tx,i[o++]=l*this._c+h*this._d+this._ty}return i},_transformCorners:function(e){var t=e.x,i=e.y,n=t+e.width,r=i+e.height,s=[t,i,n,i,n,r,t,r];return this._transformCoordinates(s,0,s,0,4)},_transformBounds:function(e){for(var t=this._transformCorners(e),i=t.slice(0,2),n=t.slice(0),r=2;8>r;r++){var s=t[r],o=1&r;i[o]>s?i[o]=s:s>n[o]&&(n[o]=s)}return Rectangle.create(i[0],i[1],n[0]-i[0],n[1]-i[1])},inverseTransform:function(){return this._inverseTransform(Point.read(arguments))},_getDeterminant:function(){var e=this._a*this._d-this._b*this._c;return isFinite(e)&&Math.abs(e)>Numerical.EPSILON&&isFinite(this._tx)&&isFinite(this._ty)?e:null},_inverseTransform:function(e,t,i){var n=this._getDeterminant();if(!n)return null;var r=e.x-this._tx,s=e.y-this._ty;return t||(t=new Point(Point.dont)),t.set((r*this._d-s*this._b)/n,(s*this._a-r*this._c)/n,i)},getTranslation:function(){return new Point(this._tx,this._ty)},getScaling:function(){var e=Math.sqrt(this._a*this._a+this._c*this._c),t=Math.sqrt(this._b*this._b+this._d*this._d);return new Point(0>this._a?-e:e,0>this._b?-t:t)},getRotation:function(){var e=-Math.atan2(this._b,this._d),t=Math.atan2(this._c,this._a);return Math.abs(e-t)=0&&1>=n)&&(e.infinite||r>=0&&1>=r)?this.point.add(this.vector.multiply(n)):null},getSide:function(e){var t=this.vector,i=e.subtract(this.point),n=i.cross(t);return 0==n&&(n=i.dot(t),n>0&&(n=i.subtract(t).dot(t),0>n&&(n=0))),0>n?-1:n>0?1:0},getDistance:function(e){var t=this.vector.y/this.vector.x,i=this.point.y-t*this.point.x,n=Math.abs(e.y-t*e.x-i)/Math.sqrt(t*t+1);return this.infinite?n:Math.min(n,e.getDistance(this.point),e.getDistance(this.point.add(this.vector)))}}),Project=this.Project=PaperScopeItem.extend({_list:"projects",_reference:"project",initialize:function(){this.base(!0),this._currentStyle=new PathStyle,this._selectedItems={},this._selectedItemCount=0,this.layers=[],this.symbols=[],this.activeLayer=new Layer},_needsRedraw:function(){this._scope&&this._scope._needsRedraw()},getCurrentStyle:function(){return this._currentStyle},setCurrentStyle:function(e){this._currentStyle.initialize(e)},getIndex:function(){return this._index},getSelectedItems:function(){var e=[];return Base.each(this._selectedItems,function(t){e.push(t)}),e},_updateSelection:function(e){e._selected?(this._selectedItemCount++,this._selectedItems[e.getId()]=e):(this._selectedItemCount--,delete this._selectedItems[e.getId()])},selectAll:function(){for(var e=0,t=this.layers.length;t>e;e++)this.layers[e].setSelected(!0)},deselectAll:function(){for(var e in this._selectedItems)this._selectedItems[e].setSelected(!1)},hitTest:function(e,t){t=HitResult.getOptions(e,t),e=t.point;for(var i=this.layers.length-1;i>=0;i--){var n=this.layers[i].hitTest(e,t);if(n)return n}return null},draw:function(e){e.save();for(var t={offset:new Point(0,0)},i=0,n=this.layers.length;n>i;i++)Item.draw(this.layers[i],e,t);e.restore(),this._selectedItemCount>0&&(e.save(),e.strokeWidth=1,e.strokeStyle=e.fillStyle="#009dec",t={selection:!0},Base.each(this._selectedItems,function(i){i.draw(e,t)}),e.restore())}}),Symbol=this.Symbol=Base.extend({initialize:function(e){this.project=paper.project,this.project.symbols.push(this),this.setDefinition(e),this._instances={}},_changed:function(e){Base.each(this._instances,function(t){t._changed(e)})},getDefinition:function(){return this._definition},setDefinition:function(e){e._parentSymbol&&(e=e.clone()),this._definition&&delete this._definition._parentSymbol,this._definition=e,e.remove(),e.setPosition(new Point),e._parentSymbol=this,this._changed(Change.GEOMETRY)},place:function(e){return new PlacedSymbol(this,e)},clone:function(){return new Symbol(this._definition.clone())}}),ChangeFlag={APPEARANCE:1,HIERARCHY:2,GEOMETRY:4,STROKE:8,STYLE:16,ATTRIBUTE:32,CONTENT:64,PIXELS:128,CLIPPING:256},Change={HIERARCHY:ChangeFlag.HIERARCHY|ChangeFlag.APPEARANCE,GEOMETRY:ChangeFlag.GEOMETRY|ChangeFlag.APPEARANCE,STROKE:ChangeFlag.STROKE|ChangeFlag.STYLE|ChangeFlag.APPEARANCE,STYLE:ChangeFlag.STYLE|ChangeFlag.APPEARANCE,ATTRIBUTE:ChangeFlag.ATTRIBUTE|ChangeFlag.APPEARANCE,CONTENT:ChangeFlag.CONTENT|ChangeFlag.APPEARANCE,PIXELS:ChangeFlag.PIXELS|ChangeFlag.APPEARANCE},Item=this.Item=Base.extend({initialize:function(){this._id=++Item._id,this._project||paper.project.activeLayer.addChild(this),this._style=PathStyle.create(this),this.setStyle(this._project.getCurrentStyle())},_changed:function(e){if(e&ChangeFlag.GEOMETRY&&(delete this._bounds,delete this._position),e&ChangeFlag.APPEARANCE&&this._project._needsRedraw(),this._parentSymbol&&this._parentSymbol._changed(e),this._project._changes){var t=this._project._changesById[this._id];t?t.flags|=e:(t={item:this,flags:e},this._project._changesById[this._id]=t,this._project._changes.push(t))}},getId:function(){return this._id},getName:function(){return this._name},setName:function(e){if(this._name&&this._removeFromNamed(),this._name=e||void 0,e){var t=this._parent._children,i=this._parent._namedChildren;(i[e]=i[e]||[]).push(this),t[e]=this}this._changed(ChangeFlag.ATTRIBUTE)},getPosition:function(){var e=this._position||(this._position=this.getBounds().getCenter());return LinkedPoint.create(this,"setPosition",e._x,e._y)},setPosition:function(){this.translate(Point.read(arguments).subtract(this.getPosition()))},getStyle:function(){return this._style},setStyle:function(e){this._style.initialize(e)},statics:{_id:0}},new function(){return Base.each(["locked","visible","blendMode","opacity","guide"],function(e){var t=Base.capitalize(e),e="_"+e;this["get"+t]=function(){return this[e]},this["set"+t]=function(t){t!=this[e]&&(this[e]=t,this._changed("_locked"===e?ChangeFlag.ATTRIBUTE:Change.ATTRIBUTE))}},{})},{_locked:!1,_visible:!0,_blendMode:"normal",_opacity:1,_guide:!1,isSelected:function(){if(this._children)for(var e=0,t=this._children.length;t>e;e++)if(this._children[e].isSelected())return!0;return this._selected},setSelected:function(e){if(this._children)for(var t=0,i=this._children.length;i>t;t++)this._children[t].setSelected(e);else(e=!!e)!=this._selected&&(this._selected=e,this._project._updateSelection(this),this._changed(Change.ATTRIBUTE))},_selected:!1,isFullySelected:function(){if(this._children&&this._selected){for(var e=0,t=this._children.length;t>e;e++)if(!this._children[e].isFullySelected())return!1;return!0}return this._selected},setFullySelected:function(e){if(this._children)for(var t=0,i=this._children.length;i>t;t++)this._children[t].setFullySelected(e);this.setSelected(e)},isClipMask:function(){return this._clipMask},setClipMask:function(e){this._clipMask!=(e=!!e)&&(this._clipMask=e,e&&(this.setFillColor(null),this.setStrokeColor(null)),this._changed(Change.ATTRIBUTE),this._parent&&this._parent._changed(ChangeFlag.CLIPPING))},_clipMask:!1,getProject:function(){return this._project},_setProject:function(e){if(this._project!=e&&(this._project=e,this._children))for(var t=0,i=this._children.length;i>t;t++)this._children[t]._setProject(e)},getLayer:function(){for(var e=this;e=e._parent;)if(e instanceof Layer)return e;return null},getParent:function(){return this._parent},getChildren:function(){return this._children},setChildren:function(e){this.removeChildren(),this.addChildren(e)},getFirstChild:function(){return this._children&&this._children[0]||null},getLastChild:function(){return this._children&&this._children[this._children.length-1]||null},getNextSibling:function(){return this._parent&&this._parent._children[this._index+1]||null},getPreviousSibling:function(){return this._parent&&this._parent._children[this._index-1]||null},getIndex:function(){return this._index},clone:function(){return this._clone(new this.constructor)},_clone:function(e){if(e.setStyle(this._style),this._children)for(var t=0,i=this._children.length;i>t;t++)e.addChild(this._children[t].clone());for(var n=["_locked","_visible","_blendMode","_opacity","_clipMask","_guide"],t=0,i=n.length;i>t;t++){var r=n[t];this.hasOwnProperty(r)&&(e[r]=this[r])}return e.setSelected(this._selected),this._name&&e.setName(this._name),e},copyTo:function(e){var t=this.clone();return e.layers?e.activeLayer.addChild(t):e.addChild(t),t},rasterize:function(e){var t=this.getStrokeBounds(),i=(e||72)/72,n=CanvasProvider.getCanvas(t.getSize().multiply(i)),r=n.getContext("2d"),s=(new Matrix).scale(i).translate(-t.x,-t.y);s.applyToContext(r),this.draw(r,{});var o=new Raster(n);return o.setBounds(t),o},hitTest:function(e,t,i){function n(n,r){var a=s["get"+r]().transform(i);return e.getDistance(a)l;l++)if(r=n("bounds",a[l]))return r}return this._children||!(t.guides&&!this._guide||t.selected&&!this._selected)?this._hitTest(e,t,i):null},_hitTest:function(e,t,i){if(this._children)for(var n=this._children.length-1;n>=0;n--){var r=this._children[n].hitTest(e,t,i);if(r)return r}},addChild:function(e){return this.insertChild(void 0,e)},insertChild:function(e,t){return this._children?(t._remove(!1,!0),Base.splice(this._children,[t],e,0),t._parent=this,t._setProject(this._project),t._name&&t.setName(t._name),this._changed(Change.HIERARCHY),!0):!1},addChildren:function(e){for(var t=0,i=e&&e.length;i>t;t++)this.insertChild(void 0,e[t])},insertChildren:function(e,t){for(var i=0,n=t&&t.length;n>i;i++)this.insertChild(e,t[i])&&e++},insertAbove:function(e){return e._parent&&e._parent.insertChild(e._index+1,this)},insertBelow:function(e){return e._parent&&e._parent.insertChild(e._index-1,this)},appendTop:function(e){return this.addChild(e)},appendBottom:function(e){return this.insertChild(0,e)},moveAbove:function(e){return this.insertAbove(e)},moveBelow:function(e){return this.insertBelow(e)},_removeFromNamed:function(){var e=this._parent._children,t=this._parent._namedChildren,i=this._name,n=t[i],r=n?n.indexOf(this):-1;-1!=r&&(e[i]==this&&delete e[i],n.splice(r,1),n.length?e[i]=n[n.length-1]:delete t[i])},_remove:function(e,t){return this._parent?(e&&this.setSelected(!1),this._name&&this._removeFromNamed(),Base.splice(this._parent._children,null,this._index,1),t&&this._parent._changed(Change.HIERARCHY),this._parent=null,!0):!1},remove:function(){return this._remove(!0,!0)},removeChildren:function(e,t){if(!this._children)return null;e=e||0,t=Base.pick(t,this._children.length);for(var i=this._children.splice(e,t-e),n=i.length-1;n>=0;n--)i[n]._remove(!0,!1);return i.length>0&&this._changed(Change.HIERARCHY),i},reverseChildren:function(){if(this._children){this._children.reverse();for(var e=0,t=this._children.length;t>e;e++)this._children[e]._index=e;this._changed(Change.HIERARCHY)}},isEditable:function(){for(var e=this;e;){if(!e._visible||e._locked)return!1;e=e._parent}return!0},_getOrder:function(e){function t(e){var t=[];do t.unshift(e);while(e=e._parent);return t}for(var i=t(this),n=t(e),r=0,s=Math.min(i.length,n.length);s>r;r++)if(i[r]!=n[r])return i[r]._index0},isAbove:function(e){return-1==this._getOrder(e)},isBelow:function(e){return 1==this._getOrder(e)},isParent:function(e){return this._parent==e},isChild:function(e){return e&&e._parent==this},isDescendant:function(e){for(var t=this;t=t._parent;)if(t==e)return!0;return!1},isAncestor:function(e){return e?e.isDescendant(this):!1},isGroupedWith:function(e){for(var t=this._parent;t;){if(t._parent&&(t instanceof Group||t instanceof CompoundPath)&&e.isDescendant(t))return!0;t=t._parent}return!1},_getBounds:function(e,t,i){var n=this._children;if(!n||0==n.length)return new Rectangle;for(var r=1/0,s=-r,o=r,a=s,l=0,h=n.length;h>l;l++){var c=n[l];if(c._visible){var u=c[e](i[0]);r=Math.min(u.x,r),o=Math.min(u.y,o),s=Math.max(u.x+u.width,s),a=Math.max(u.y+u.height,a)}}var d=Rectangle.create(r,o,s-r,a-o);return"getBounds"==e?this._createBounds(d):d},_createBounds:function(e){return LinkedRectangle.create(this,"setBounds",e.x,e.y,e.width,e.height)},getBounds:function(){return this._getBounds("getBounds","_bounds",arguments)},setBounds:function(e){e=Rectangle.read(arguments);var t=this.getBounds(),i=new Matrix,n=e.getCenter();i.translate(n),(e.width!=t.width||e.height!=t.height)&&i.scale(0!=t.width?e.width/t.width:1,0!=t.height?e.height/t.height:1),n=t.getCenter(),i.translate(-n.x,-n.y),this.transform(i)},getStrokeBounds:function(){return this._getBounds("getStrokeBounds","_strokeBounds",arguments)},getHandleBounds:function(){return this._getBounds("getHandleBounds","_handleBounds",arguments)},getRoughBounds:function(){return this._getBounds("getRoughBounds","_roughBounds",arguments)},scale:function(e,t,i){return(2>arguments.length||"object"==typeof t)&&(i=t,t=e),this.transform((new Matrix).scale(e,t,i||this.getPosition()))},translate:function(){var e=new Matrix;return this.transform(e.translate.apply(e,arguments))},rotate:function(e,t){return this.transform((new Matrix).rotate(e,t||this.getPosition()))},shear:function(e,t,i){return(2>arguments.length||"object"==typeof t)&&(i=t,t=e),this.transform((new Matrix).shear(e,t,i||this.getPosition()))},transform:function(e,t){var i=this._bounds,n=this._position,r=this._children;this._transform&&(this._transform(e,t),this._changed(Change.GEOMETRY)),i&&0===e.getRotation()%90?(this._bounds=this._createBounds(e._transformBounds(i)),this._position=this._bounds.getCenter()):n&&(this._position=e._transformPoint(n,n,!0));for(var s=0,o=r&&r.length;o>s;s++)r[s].transform(e,t);return this},fitBounds:function(e,t){e=Rectangle.read(arguments);var i=this.getBounds(),n=i.height/i.width,r=e.height/e.width,s=(t?n>r:r>n)?e.width/i.width:e.height/i.height,o=(e.getCenter().subtract(i.getCenter()),new Rectangle(new Point,new Size(i.width*s,i.height*s)));o.setCenter(e.getCenter()),this.setBounds(o)},toString:function(){return(this.constructor._name||"Item")+(this._name?" '"+this._name+"'":" @"+this._id)},statics:{drawSelectedBounds:function(e,t,i){var n=i._transformCorners(e);t.beginPath();for(var r=0;8>r;r++)t[0==r?"moveTo":"lineTo"](n[r],n[++r]);t.closePath(),t.stroke();for(var r=0;8>r;r++)t.beginPath(),t.rect(n[r]-2,n[++r]-2,4,4),t.fill()},draw:function(e,t,i){if(e._visible&&0!=e._opacity){var n,r;if("normal"!==e._blendMode||1>e._opacity&&(!e._segments||e.getFillColor()&&e.getStrokeColor())){var s=e.getStrokeBounds()||e.getBounds();if(!s.width||!s.height)return;var o=s.getTopLeft().floor(),a=s.getSize().ceil().add(new Size(1,1));n=CanvasProvider.getCanvas(a),r=t,t=n.getContext("2d"),t.save(),t.translate(-o.x,-o.y)}var l;if(o&&(l=i.offset,i.offset=o),e.draw(t,i),o&&(i.offset=l),n){if(t.restore(),"normal"!==e._blendMode){var h=o.subtract(i.offset);BlendMode.process(e._blendMode,t,r,e._opacity,h)}else r.save(),r.globalAlpha=e._opacity,r.drawImage(n,o.x,o.y),r.restore();CanvasProvider.returnCanvas(n)}}}}},new function(){function e(e){for(var t in e){var n=e[t];n.remove();for(var r in i){var s=i[r];s!=e&&s[n.getId()]&&delete s[n.getId()]}}}function t(t){var n="onMouse"+Base.capitalize(t),r=paper.tool[n];if(!r||!r._installed){var s={};s[n]=function(n){"up"===t&&(i.drag={}),e(i[t]),i[t]={},this.base&&this.base(n)},paper.tool.inject(s),paper.tool[n]._installed=!0}}var i={down:{},drag:{},up:{},move:{}};return Base.each(["down","drag","up","move"],function(e){this["removeOn"+Base.capitalize(e)]=function(){var t={};return t[e]=!0,this.removeOn(t)}},{removeOn:function(e){for(var n in e)e[n]&&(i[n][this.getId()]=this,"drag"===n&&t("up"),t(n));return this}})}),Group=this.Group=Item.extend({initialize:function(e){this.base(),this._children=[],this._namedChildren={},this.addChildren(e&&Array.isArray(e)&&"object"==typeof e[0]?e:arguments)},_changed:function(e){Item.prototype._changed.call(this,e),e&(ChangeFlag.HIERARCHY|ChangeFlag.CLIPPING)&&delete this._clipItem},_getClipItem:function(){if(void 0!==this._clipItem)return this._clipItem;for(var e=0,t=this._children.length;t>e;e++){var i=this._children[e];if(i._clipMask)return this._clipItem=i}return this._clipItem=null},isClipped:function(){return!!this._getClipItem()},setClipped:function(e){var t=this.getFirstChild();return t&&t.setClipMask(e),this},draw:function(e,t){var i=this._getClipItem();i&&Item.draw(i,e,t);for(var n=0,r=this._children.length;r>n;n++){var s=this._children[n];s!=i&&Item.draw(s,e,t)}}}),Layer=this.Layer=Group.extend({initialize:function(){this._project=paper.project,this._index=this._project.layers.push(this)-1,this.base.apply(this,arguments),this.activate()},_remove:function(e,t){return this._parent?this.base(e,t):null!=this._index?(e&&this.setSelected(!1),Base.splice(this._project.layers,null,this._index,1),this._project._needsRedraw(),!0):!1},getNextSibling:function(){return this._parent?this.base():this._project.layers[this._index+1]||null},getPreviousSibling:function(){return this._parent?this.base():this._project.layers[this._index-1]||null},activate:function(){this._project.activeLayer=this}},new function(){function e(e){return function(t){return t instanceof Layer&&!t._parent&&this._remove(!1,!0)?(Base.splice(t._project.layers,[this],t._index+(e?1:-1),0),this._setProject(t._project),!0):this.base(t)}}return{insertAbove:e(!0),insertBelow:e(!1)}}),PlacedItem=this.PlacedItem=Item.extend({_transform:function(e){this._matrix.preConcatenate(e)},_changed:function(e){Item.prototype._changed.call(this,e),e&ChangeFlag.GEOMETRY&&(delete this._strokeBounds,delete this._handleBounds,delete this._roughBounds)},getMatrix:function(){return this._matrix},setMatrix:function(e){this._matrix=e.clone(),this._changed(Change.GEOMETRY)},getBounds:function(){var e=void 0===arguments[0];if(e&&this._bounds)return this._bounds;var t=this.getStrokeBounds(arguments[0]);return e&&(t=this._bounds=this._createBounds(t)),t},_getBounds:function(e,t,i){var n=i[0],r=void 0===n;if(r&&this[t])return this[t];n=n?n.clone().concatenate(this._matrix):this._matrix;var s=this._calculateBounds(e,n);return r&&(this[t]=s),s}}),Raster=this.Raster=PlacedItem.extend({initialize:function(e){this.base(),e.getContext?this.setCanvas(e):("string"==typeof e&&(e=document.getElementById(e)),this.setImage(e)),this._matrix=new Matrix},clone:function(){var e=this._image;e||(e=CanvasProvider.getCanvas(this._size),e.getContext("2d").drawImage(this._canvas,0,0));var t=new Raster(e);return t._matrix=this._matrix.clone(),this._clone(t)},getSize:function(){return this._size},setSize:function(){var e=Size.read(arguments),t=this.getImage();this.setCanvas(CanvasProvider.getCanvas(e)),this.getContext(!0).drawImage(t,0,0,e.width,e.height)},getWidth:function(){return this._size.width},getHeight:function(){return this._size.height},getPpi:function(){var e=this._matrix,t=new Point(0,0).transform(e),i=new Point(1,0).transform(e).subtract(t),n=new Point(0,1).transform(e).subtract(t);return new Size(72/i.getLength(),72/n.getLength())},getContext:function(){return this._context||(this._context=this.getCanvas().getContext("2d")),arguments[0]&&this._changed(Change.PIXELS),this._context},setContext:function(e){this._context=e},getCanvas:function(){return this._canvas||(this._canvas=CanvasProvider.getCanvas(this._size),this._image&&this.getContext(!0).drawImage(this._image,0,0)),this._canvas},setCanvas:function(e){this._canvas&&CanvasProvider.returnCanvas(this._canvas),this._canvas=e,this._size=new Size(e.width,e.height),this._image=null,this._context=null,this._changed(Change.GEOMETRY)},getImage:function(){return this._image||this.getCanvas()},setImage:function(e){this._canvas&&CanvasProvider.returnCanvas(this._canvas),this._image=e,this._size=new Size(e.naturalWidth,e.naturalHeight),this._canvas=null,this._context=null,this._changed(Change.GEOMETRY)},getSubImage:function(e){e=Rectangle.read(arguments);var t=CanvasProvider.getCanvas(e.getSize());return t.getContext("2d").drawImage(this.getCanvas(),e.x,e.y,t.width,t.height,0,0,t.width,t.height),t},drawImage:function(e,t){t=Point.read(arguments,1),this.getContext(!0).drawImage(e,t.x,t.y)},getAverageColor:function(e){e||(e=this.getBounds());var t,i;e instanceof PathItem?(i=e,t=e.getBounds()):e.width?t=new Rectangle(e):e.x&&(t=Rectangle.create(e.x-.5,e.y-.5,1,1));var n=32,r=Math.min(t.width,n),s=Math.min(t.height,n),o=Raster._sampleContext;o?o.clearRect(0,0,n,n):o=Raster._sampleContext=CanvasProvider.getCanvas(new Size(n)).getContext("2d"),o.save(),o.scale(r/t.width,s/t.height),o.translate(-t.x,-t.y),i&&i.draw(o,{clip:!0}),this._matrix.applyToContext(o),o.drawImage(this._canvas||this._image,-this._size.width/2,-this._size.height/2),o.restore();for(var a=o.getImageData(.5,.5,Math.ceil(r),Math.ceil(s)).data,l=[0,0,0],h=0,c=0,u=a.length;u>c;c+=4){var d=a[c+3];h+=d,d/=255,l[0]+=a[c]*d,l[1]+=a[c+1]*d,l[2]+=a[c+2]*d}for(var c=0;3>c;c++)l[c]/=h;return h?Color.read(l):null},getPixel:function(e){e=Point.read(arguments);for(var t=this.getContext().getImageData(e.x,e.y,1,1).data,i=Array(4),n=0;4>n;n++)i[n]=t[n]/255;return RgbColor.read(i)},setPixel:function(e,t){var i=2==arguments.length;e=Point.read(arguments,0,i?1:2),t=Color.read(arguments,i?1:2);var n=this.getContext(!0),r=n.createImageData(1,1),s=t.getAlpha();r.data[0]=255*t.getRed(),r.data[1]=255*t.getGreen(),r.data[2]=255*t.getBlue(),r.data[3]=null!=s?255*s:255,n.putImageData(r,e.x,e.y)},createData:function(e){return e=Size.read(arguments),this.getContext().createImageData(e.width,e.height)},getData:function(e){return e=Rectangle.read(arguments),e.isEmpty()&&(e=new Rectangle(this.getSize())),this.getContext().getImageData(e.x,e.y,e.width,e.height)},setData:function(e,t){t=Point.read(arguments,1),this.getContext(!0).putImageData(e,t.x,t.y)},_calculateBounds:function(e,t){return t._transformBounds(new Rectangle(this._size).setCenter(0,0))},getHandleBounds:function(){return this.getStrokeBounds(arguments[0])},getRoughBounds:function(){return this.getStrokeBounds(arguments[0])},draw:function(e,t){if(t.selection){var i=new Rectangle(this._size).setCenter(0,0);Item.drawSelectedBounds(i,e,this._matrix)}else e.save(),this._matrix.applyToContext(e),e.drawImage(this._canvas||this._image,-this._size.width/2,-this._size.height/2),e.restore()}}),PlacedSymbol=this.PlacedSymbol=PlacedItem.extend({initialize:function(e,t){this.base(),this.setSymbol(e instanceof Symbol?e:new Symbol(e)),this._matrix=void 0!==t?t instanceof Matrix?t:(new Matrix).translate(Point.read(arguments,1)):new Matrix},getSymbol:function(){return this._symbol},setSymbol:function(e){this._symbol&&delete this._symbol._instances[this._id],this._symbol=e,e._instances[this._id]=this},clone:function(){return this._clone(new PlacedSymbol(this.symbol,this._matrix.clone()))},_calculateBounds:function(e,t){return this.symbol._definition[e](t)},draw:function(e,t){t.selection?Item.drawSelectedBounds(this.symbol._definition.getStrokeBounds(),e,this._matrix):(e.save(),this._matrix.applyToContext(e),Item.draw(this.symbol.getDefinition(),e,t),e.restore())}});HitResult=Base.extend({initialize:function(e,t,i){this.type=e,this.item=t,i&&Base.each(i,function(e,t){this[t]=e},this)},statics:{getOptions:function(e,t){return t&&t._merged?t:Base.merge({point:Point.read(arguments,0,1),type:null,tolerance:2,fill:!t,stroke:!t,segments:!t,handles:!1,ends:!1,center:!1,bounds:!1,guides:!1,selected:!1,_merged:!0},t)}}});var Segment=this.Segment=Base.extend({initialize:function(e,t,i,n,r,s){var o,a,l,h=arguments.length,c=SegmentPoint.create;0==h||(1==h?e.point?(o=e.point,a=e.handleIn,l=e.handleOut):o=e:6>h?2==h&&void 0===t.x?o=[e,t]:(o=e,a=t,l=i):6==h&&(o=[e,t],a=[i,n],l=[r,s])),c(this,"_point",o),c(this,"_handleIn",a),c(this,"_handleOut",l)},_changed:function(e){if(this._path){var t,i=this._path._curves&&this.getCurve();i&&(i._changed(),(t=i[e==this._point||e==this._handleIn&&i._segment1==this?"getPrevious":"getNext"]())&&t._changed()),this._path._changed(Change.GEOMETRY)}},getPoint:function(){return this._point},setPoint:function(e){e=Point.read(arguments),this._point.set(e.x,e.y)},getHandleIn:function(){return this._handleIn},setHandleIn:function(e){e=Point.read(arguments),this._handleIn.set(e.x,e.y)},getHandleOut:function(){return this._handleOut},setHandleOut:function(e){e=Point.read(arguments),this._handleOut.set(e.x,e.y)},_isSelected:function(e){var t=this._selectionState;return e==this._point?!!(t&SelectionState.POINT):e==this._handleIn?!!(t&SelectionState.HANDLE_IN):e==this._handleOut?!!(t&SelectionState.HANDLE_OUT):!1},_setSelected:function(e,t){var i=this._path,t=!!t,n=this._selectionState||0,r=[!!(n&SelectionState.POINT),!!(n&SelectionState.HANDLE_IN),!!(n&SelectionState.HANDLE_OUT)];if(e==this._point){if(t)r[1]=r[2]=!1;else{var s=this.getPrevious(),o=this.getNext();r[1]=s&&(s._point.isSelected()||s._handleOut.isSelected()),r[2]=o&&(o._point.isSelected()||o._handleIn.isSelected())}r[0]=t}else{var a=e==this._handleIn?1:2;r[a]!=t&&(t&&(r[0]=!1),r[a]=t,i._changed(Change.ATTRIBUTE))}this._selectionState=(r[0]?SelectionState.POINT:0)|(r[1]?SelectionState.HANDLE_IN:0)|(r[2]?SelectionState.HANDLE_OUT:0),i&&n!=this._selectionState&&i._updateSelection(this,n,this._selectionState)},isSelected:function(){return this._isSelected(this._point)},setSelected:function(e){this._setSelected(this._point,e)},getIndex:function(){return void 0!==this._index?this._index:null},getPath:function(){return this._path||null},getCurve:function(){if(this._path){var e=this._index;return this._path._closed||e!=this._path._segments.length-1||e--,this._path.getCurves()[e]||null}return null},getNext:function(){var e=this._path&&this._path._segments;return e&&(e[this._index+1]||this._path._closed&&e[0])||null},getPrevious:function(){var e=this._path&&this._path._segments;return e&&(e[this._index-1]||this._path._closed&&e[e.length-1])||null},reverse:function(){return new Segment(this._point,this._handleOut,this._handleIn)},remove:function(){return this._path?!!this._path.removeSegment(this._index):!1},toString:function(){var e=["point: "+this._point];return this._handleIn.isZero()||e.push("handleIn: "+this._handleIn),this._handleOut.isZero()||e.push("handleOut: "+this._handleOut),"{ "+e.join(", ")+" }"},_transformCoordinates:function(e,t,i){var n=this._point,r=i&&this._handleIn.isZero()?null:this._handleIn,s=i&&this._handleOut.isZero()?null:this._handleOut,o=n._x,a=n._y,l=2;t[0]=o,t[1]=a,r&&(t[l++]=r._x+o,t[l++]=r._y+a),s&&(t[l++]=s._x+o,t[l++]=s._y+a),e&&(e._transformCoordinates(t,0,t,0,l/2),o=t[0],a=t[1],i?(n._x=o,n._y=a,l=2,r&&(r._x=t[l++]-o,r._y=t[l++]-a),s&&(s._x=t[l++]-o,s._y=t[l++]-a)):(r||(t[l++]=o,t[l++]=a),s||(t[l++]=o,t[l++]=a)))}}),SegmentPoint=Point.extend({set:function(e,t){return this._x=e,this._y=t,this._owner._changed(this),this},getX:function(){return this._x},setX:function(e){this._x=e,this._owner._changed(this)},getY:function(){return this._y},setY:function(e){this._y=e,this._owner._changed(this)},isZero:function(){return 0==this._x&&0==this._y},setSelected:function(e){this._owner._setSelected(this,e)},isSelected:function(){return this._owner._isSelected(this)},statics:{create:function(e,t,i){var n,r,s,o=new SegmentPoint(SegmentPoint.dont);return i?void 0!==(n=i[0])?r=i[1]:(void 0===(n=i.x)&&(i=Point.read(arguments,2,1),n=i.x),r=i.y,s=i.selected):n=r=0,o._x=n,o._y=r,o._owner=e,e[t]=o,s&&o.setSelected(!0),o}}}),SelectionState={HANDLE_IN:1,HANDLE_OUT:2,POINT:4},Curve=this.Curve=Base.extend({initialize:function(e,t,i,n,r,s,o,a){var l=arguments.length;if(0==l)this._segment1=new Segment,this._segment2=new Segment;else if(1==l)this._segment1=new Segment(e.segment1),this._segment2=new Segment(e.segment2);else if(2==l)this._segment1=new Segment(e),this._segment2=new Segment(t);else if(4==l)this._segment1=new Segment(e,null,t),this._segment2=new Segment(n,i,null);else if(8==l){var h=Point.create(e,t),c=Point.create(o,a);this._segment1=new Segment(h,null,Point.create(i,n).subtract(h)),this._segment2=new Segment(c,Point.create(r,s).subtract(c),null)}},_changed:function(){delete this._length},getPoint1:function(){return this._segment1._point},setPoint1:function(e){e=Point.read(arguments),this._segment1._point.set(e.x,e.y)},getPoint2:function(){return this._segment2._point},setPoint2:function(e){e=Point.read(arguments),this._segment2._point.set(e.x,e.y)},getHandle1:function(){return this._segment1._handleOut},setHandle1:function(e){e=Point.read(arguments),this._segment1._handleOut.set(e.x,e.y)},getHandle2:function(){return this._segment2._handleIn},setHandle2:function(e){e=Point.read(arguments),this._segment2._handleIn.set(e.x,e.y)},getSegment1:function(){return this._segment1},getSegment2:function(){return this._segment2},getPath:function(){return this._path},getIndex:function(){return this._segment1._index},getNext:function(){var e=this._path&&this._path._curves;return e&&(e[this._segment1._index+1]||this._path._closed&&e[0])||null},getPrevious:function(){var e=this._path&&this._path._curves;return e&&(e[this._segment1._index-1]||this._path._closed&&e[e.length-1])||null},isSelected:function(){return this.getHandle1().isSelected()&&this.getHandle2().isSelected()},setSelected:function(e){this.getHandle1().setSelected(e),this.getHandle2().setSelected(e)},getValues:function(e){return Curve.getValues(this._segment1,this._segment2,e)},getPoints:function(e){for(var t=this.getValues(e),i=[],n=0;8>n;n+=2)i.push(Point.create(t[n],t[n+1]));return i},getLength:function(){var e=arguments[0],t=arguments[1];if(fullLength=0==arguments.length||0==e&&1==t,fullLength&&null!=this._length)return this._length;var i=Curve.getLength(this.getValues(),e,t);return fullLength&&(this._length=i),i},getPart:function(e,t){return new Curve(Curve.getPart(this.getValues(),e,t))},isLinear:function(){return this._segment1._handleOut.isZero()&&this._segment2._handleIn.isZero()},getParameterAt:function(e,t){return Curve.getParameterAt(this.getValues(),e,void 0!==t?t:0>e?1:0)},getPoint:function(e){return Curve.evaluate(this.getValues(),e,0)},getTangent:function(e){return Curve.evaluate(this.getValues(),e,1)},getNormal:function(e){return Curve.evaluate(this.getValues(),e,2)},getParameter:function(e){return e=Point.read(e),Curve.getParameter(this.getValues(),e.x,e.y)},getCrossings:function(e,t,i){for(var n=this.getValues(t),r=Curve.solveCubic(n,1,e.y,i),s=0,o=0;r>o;o++){var a=i[o];if(a>=0&&1>a&&Curve.evaluate(n,a,0).x>e.x){if(Numerical.TOLERANCE>a&&Curve.evaluate(this.getPrevious().getValues(t),1,1).y*Curve.evaluate(n,a,1).y>=0)continue;s++}}return s},reverse:function(){return new Curve(this._segment2.reverse(),this._segment1.reverse())},clone:function(){return new Curve(this._segment1,this._segment2)},toString:function(){var e=["point1: "+this._segment1._point];return this._segment1._handleOut.isZero()||e.push("handle1: "+this._segment1._handleOut),this._segment2._handleIn.isZero()||e.push("handle2: "+this._segment2._handleIn),e.push("point2: "+this._segment2._point),"{ "+e.join(", ")+" }"},statics:{create:function(e,t,i){var n=new Curve(Curve.dont);return n._path=e,n._segment1=t,n._segment2=i,n},getValues:function(e,t,i){var n=e._point,r=e._handleOut,s=t._handleIn,o=t._point,a=[n._x,n._y,n._x+r._x,n._y+r._y,o._x+s._x,o._y+s._y,o._x,o._y];return i?i._transformCoordinates(a,0,a,0,4):a},evaluate:function(e,t,i){var n,r,s=e[0],o=e[1],a=e[2],l=e[3],h=e[4],c=e[5],u=e[6],d=e[7];if(0!=i||0!=t&&1!=t){var p=Numerical.TOLERANCE;p>t&&a==s&&l==o?t=p:t>1-p&&h==u&&c==d&&(t=1-p);var f=3*(a-s),m=3*(h-a)-f,g=u-s-f-m,y=3*(l-o),v=3*(c-l)-y,b=d-o-y-v;switch(i){case 0:n=((g*t+m)*t+f)*t+s,r=((b*t+v)*t+y)*t+o;break;case 1:case 2:n=(3*g*t+2*m)*t+f,r=(3*b*t+2*v)*t+y}}else n=0==t?s:u,r=0==t?o:d;return 2==i?new Point(r,-n):new Point(n,r)},subdivide:function(e,t){var i=e[0],n=e[1],r=e[2],s=e[3],o=e[4],a=e[5],l=e[6],h=e[7];void 0===t&&(t=.5);var c=1-t,u=c*i+t*r,d=c*n+t*s,p=c*r+t*o,f=c*s+t*a,m=c*o+t*l,g=c*a+t*h,y=c*u+t*p,v=c*d+t*f,b=c*p+t*m,L=c*f+t*g,x=c*y+t*b,C=c*v+t*L;return[[i,n,u,d,y,v,x,C],[x,C,b,L,m,g,l,h]]},solveCubic:function(e,t,i,n){var r=e[t],s=e[t+2],o=e[t+4],a=e[t+6],l=3*(s-r),h=3*(o-s)-l,c=a-r-l-h;return Numerical.solveCubic(c,h,l,r-i,n,Numerical.TOLERANCE)},getParameter:function(e,t,i){for(var n,r,s=[],o=[],a=Curve.solveCubic(e,0,t,s),l=Curve.solveCubic(e,1,i,o),h=0;-1==a||a>h;)if(-1==a||(n=s[h++])>=0&&1>=n){for(var c=0;-1==l||l>c;)if((-1==l||(r=o[c++])>=0&&1>=r)&&(-1==a?n=r:-1==l&&(r=n),Math.abs(n-r)0&&(e=Curve.subdivide(e,t)[1]),1>i&&(e=Curve.subdivide(e,(i-t)/(1-t))[0]),e},isFlatEnough:function(e){var t=e[0],i=e[1],n=e[2],r=e[3],s=e[4],o=e[5],a=e[6],l=e[7],h=i-l,c=a-t,u=t*l-a*i,d=h*n+c*r+u,p=h*s+c*o+u;return.005>Math.abs((d*d+p*p)/(h*(h*h+c*c)))}}},new function(){function e(e){var t=e[0],i=e[1],n=e[2],r=e[3],s=e[4],o=e[5],a=e[6],l=e[7],h=9*(n-s)+3*(a-t),c=6*(t+s)-12*n,u=3*(n-t),d=9*(r-o)+3*(l-i),p=6*(i+o)-12*r,f=3*(r-i);return function(e){var t=(h*e+c)*e+u,i=(d*e+p)*e+f;return Math.sqrt(t*t+i*i)}}function t(e,t){return Math.max(2,Math.min(16,Math.ceil(32*Math.abs(t-e))))}return{statics:!0,getLength:function(i,n,r){if(void 0===n&&(n=0),void 0===r&&(r=1),i[0]==i[2]&&i[1]==i[3]&&i[6]==i[4]&&i[7]==i[5]){var s=i[6]-i[0],o=i[7]-i[1];return(r-n)*Math.sqrt(s*s+o*o)}var a=e(i);return Numerical.integrate(a,n,r,t(n,r))},getParameterAt:function(i,n,r){function s(e){var i=t(r,e);return d+=e>r?Numerical.integrate(h,r,e,i):-Numerical.integrate(h,e,r,i),r=e,d-n}if(0==n)return r;var o=n>0,a=o?r:0,l=o?1:r,n=Math.abs(n),h=e(i),c=Numerical.integrate(h,a,l,t(a,l));if(n>=c)return o?l:a;var u=n/c,d=0;return Numerical.findRoot(s,h,o?a+u:l-u,a,l,16,Numerical.TOLERANCE)}}},new function(){function e(e,t){for(var i=3,n=5,r=[],s=[],a=[],l=[],h=0;i>=h;h++)r[h]=e[h].subtract(t),i>h&&(s[h]=e[h+1].subtract(e[h]).multiply(i));for(var c=0;i>c;c++){a[c]=[];for(var u=0;i>=u;u++)a[c][u]=s[c].dot(r[u])}for(var h=0;n>=h;h++)l[h]=new Point(h/n,0);for(k=0;n>=k;k++)for(var d=Math.max(0,k-i+1),p=Math.min(k,i),h=d;p>=h;h++){var f=k-h;l[k].y+=a[f][h]*o[f][h]}return l}function t(e,s){switch(i(e)){case 0:return[];case 1:if(s>=r)return[.5*(e[0].x+e[5].x)];if(n(e)){var o=new Line(e[0],e[5],!0);return[o.vector.getLength(!0)<=Numerical.EPSILON?o.point.x:a.intersect(o).x]}}for(var l=[[]],h=[],c=[],u=0;5>=u;u++)l[0][u]=new Point(e[u]);for(var d=1;5>=d;d++){l[d]=[];for(var u=0;5-d>=u;u++)l[d][u]=l[d-1][u].add(l[d-1][u+1]).multiply(.5)}for(var u=0;5>=u;u++)h[u]=l[u][0],c[u]=l[5-u][u];return t(h,s+1).concat(t(c,s+1))}function i(e){for(var t=0,i=null,n=0,r=e.length;r>n;n++){var s=0>e[n].y?-1:1;null!=i&&s!=i&&t++,i=s}return t}function n(e){for(var t=e.length-1,i=e[0].y-e[t].y,n=e[t].x-e[0].x,r=e[0].x*e[t].y-e[t].x*e[0].y,o=0,a=0,l=1;t>l;l++){var h=i*e[l].x+n*e[l].y+r,c=h*h;0>h&&c>a?a=c:c>o&&(o=c)}return s>Math.abs((o+a)/(2*i*(i*i+n*n)))}var r=32,s=Math.pow(2,-r-1),o=[[1,.6,.3,.1],[.4,.6,.6,.4],[.1,.3,.6,1]],a=new Line(new Point(0,0),new Point(1,0));return{getNearestLocation:function(i,n){for(var r,s,o=e(this.getPoints(n),i),a=t(o,0).concat([0,1]),l=1/0,h=0;a.length>h;h++){var c=this.getPoint(a[h]),u=i.getDistance(c,!0);l>u&&(l=u,r=a[h],s=c)}return new CurveLocation(this,r,s,Math.sqrt(l))},getNearestPoint:function(e,t){return this.getNearestLocation(e,t).getPoint()}}});CurveLocation=Base.extend({initialize:function(e,t,i,n){this._curve=e,this._parameter=t,this._point=i,this._distance=n},getSegment:function(){if(!this._segment){var e=this._curve,t=this.getParameter();if(0==t)this._segment=e._segment1;else if(1==t)this._segment=e._segment2;else{if(null==t)return null;this._segment=e.getLength(0,t)0&&t--,this._curves=Array(t);for(var i=0;t>i;i++)this._curves[i]=Curve.create(this,e[i],e[i+1]||e[0])}return this._curves},getFirstCurve:function(){return this.getCurves()[0]},getLastCurve:function(){var e=this.getCurves();return e[e.length-1]},getClosed:function(){return this._closed},setClosed:function(e){if(this._closed!=(e=!!e)){if(this._closed=e,this._curves){var t,i=this._segments.length;!e&&i>0&&i--,this._curves.length=i,e&&(this._curves[t=i-1]=Curve.create(this,this._segments[t],this._segments[0]))}this._changed(Change.GEOMETRY)}},_transform:function(e){if(!e.isIdentity()){for(var t=Array(6),i=0,n=this._segments.length;n>i;i++)this._segments[i]._transformCoordinates(e,t,!0);var r=this.getFillColor(),s=this.getStrokeColor();r&&r.transform&&r.transform(e),s&&s.transform&&s.transform(e)}},_add:function(e,t){for(var i=this._segments,n=this._curves,r=e.length,s=null==t,t=s?i.length:t,o=this.isFullySelected(),a=0;r>a;a++){var l=e[a];l._path&&(l=e[a]=new Segment(l)),l._path=this,l._index=t+a,o&&(l._selectionState=SelectionState.POINT),l._selectionState&&this._updateSelection(l,0,l._selectionState)}if(s)i.push.apply(i,e);else{i.splice.apply(i,[t,0].concat(e));for(var a=t+r,h=i.length;h>a;a++)i[a]._index=a}if(n&&--t>=0){n.splice(t,0,Curve.create(this,i[t],i[t+1]));var c=n[t+r];c&&(c._segment1=i[t+r])}return this._changed(Change.GEOMETRY),e},add:function(e){return arguments.length>1&&"number"!=typeof e?this._add(Segment.readAll(arguments)):this._add([Segment.read(arguments)])[0]},insert:function(e,t){return arguments.length>2&&"number"!=typeof t?this._add(Segment.readAll(arguments,1),e):this._add([Segment.read(arguments,1)],e)[0]},addSegment:function(){return this._add([Segment.read(arguments)])[0]},insertSegment:function(e){return this._add([Segment.read(arguments,1)],e)[0]},addSegments:function(e){return this._add(Segment.readAll(e))},insertSegments:function(e,t){return this._add(Segment.readAll(t),e)},removeSegment:function(e){var t=this.removeSegments(e,e+1);return t[0]||null},removeSegments:function(e,t){e=e||0,t=Base.pick(t,this._segments.length);var i=this._segments,n=this._curves,r=t>=i.length,s=i.splice(e,t-e),o=s.length;if(!o)return s;for(var a=0;o>a;a++){var l=s[a];l._selectionState&&this._updateSelection(l,l._selectionState,0),s._index=s._path=void 0}for(var a=e,h=i.length;h>a;a++)i[a]._index=a;if(n){n.splice(e,o);var c;(c=n[e-1])&&(c._segment2=i[e]),(c=n[e])&&(c._segment1=i[e]),r&&this._closed&&(c=n[n.length-1])&&(c._segment2=i[0])}return this._changed(Change.GEOMETRY),s},isFullySelected:function(){return this._selected&&this._selectedSegmentState==this._segments.length*SelectionState.POINT},setFullySelected:function(e){var t=this._segments.length;this._selectedSegmentState=e?t*SelectionState.POINT:0;for(var i=0;t>i;i++)this._segments[i]._selectionState=e?SelectionState.POINT:0;this.setSelected(e) +},_updateSelection:function(e,t,i){e._selectionState=i;var n=this._selectedSegmentState+=i-t;n>0&&this.setSelected(!0)},flatten:function(e){for(var t=new PathFlattener(this),i=0,n=t.length/Math.ceil(t.length/e),r=t.length+(this._closed?-n:n)/2,s=[];r>=i;)s.push(new Segment(t.evaluate(i,0))),i+=n;this.setSegments(s)},simplify:function(e){if(this._segments.length>2){var t=new PathFitter(this,e||2.5);this.setSegments(t.fit())}},isClockwise:function(){function e(e,r){void 0!==t&&(n+=(t-e)*(r+i)),t=e,i=r}if(void 0!==this._clockwise)return this._clockwise;for(var t,i,n=0,r=0,s=this._segments.length;s>r;r++){var o=this._segments[r],a=this._segments[s>r+1?r+1:0],l=o._point,h=o._handleOut,c=a._handleIn,u=a._point;e(l._x,l._y),e(l._x+h._x,l._y+h._y),e(u._x+c._x,u._y+c._y),e(u._x,u._y)}return n>0},setClockwise:function(e){this.isClockwise()!=(e=!!e)&&(this.reverse(),this._clockwise=e)},reverse:function(){this._segments.reverse();for(var e=0,t=this._segments.length;t>e;e++){var i=this._segments[e],n=i._handleIn;i._handleIn=i._handleOut,i._handleOut=n}void 0!==this._clockwise&&(this._clockwise=!this._clockwise)},join:function(e){if(e){var t=e._segments,i=this.getLastSegment(),n=e.getLastSegment();i._point.equals(n._point)&&e.reverse();var r=e.getFirstSegment();if(i._point.equals(r._point))i.setHandleOut(r._handleOut),this._add(t.slice(1));else{var s=this.getFirstSegment();s._point.equals(r._point)&&e.reverse(),n=e.getLastSegment(),s._point.equals(n._point)?(s.setHandleIn(n._handleIn),this._add(t.slice(0,t.length-1),0)):this._add(t.slice(0))}e.remove();var s=this.getFirstSegment();return i=this.getLastSegment(),i._point.equals(s._point)&&(s.setHandleIn(i._handleIn),i.remove(),this.setClosed(!0)),this._changed(Change.GEOMETRY),!0}return!1},getLength:function(){if(null==this._length){var e=this.getCurves();this._length=0;for(var t=0,i=e.length;i>t;t++)this._length+=e[t].getLength()}return this._length},_getOffset:function(e){var t=e&&e.getIndex();if(null!=t){for(var i=this.getCurves(),n=0,r=0;t>r;r++)n+=i[r].getLength();var s=i[t];return n+s.getLength(0,e.getParameter())}return null},getLocation:function(e){for(var t=this.getCurves(),i=0,n=t.length;n>i;i++){var r=t[i],s=r.getParameter(e);if(null!=s)return new CurveLocation(r,s)}return null},getLocationAt:function(e,t){var i=this.getCurves(),n=0;if(t){var r=~~e;return new CurveLocation(i[r],e-r)}for(var s=0,o=i.length;o>s;s++){var a=n,l=i[s];if(n+=l.getLength(),n>=e)return new CurveLocation(l,l.getParameterAt(e-a))}return this.getLength()>=e?new CurveLocation(i[i.length-1],1):null},getPointAt:function(e,t){var i=this.getLocationAt(e,t);return i&&i.getPoint()},getTangentAt:function(e,t){var i=this.getLocationAt(e,t);return i&&i.getTangent()},getNormalAt:function(e,t){var i=this.getLocationAt(e,t);return i&&i.getNormal()},getNearestLocation:function(e,t){for(var i=this.getCurves(),n=1/0,r=null,s=0,o=i.length;o>s;s++){var a=i[s].getNearestLocation(e,t);n>a._distance&&(n=a._distance,r=a)}return r},getNearestPoint:function(e,t){return this.getNearestLocation(e,t).getPoint()},contains:function(e,t){if(e=Point.read(arguments),!this._closed||!this.getRoughBounds(t)._containsPoint(e))return!1;for(var i=this.getCurves(),n=0,r=[],s=0,o=i.length;o>s;s++)n+=i[s].getCrossings(e,t,r);return 1==(1&n)},_hitTest:function(e,t,i){function n(n,r){n._transformCoordinates(i,l);for(var s=r||t.segments?0:2,a=!r&&t.handles?6:2;a>s;s+=2)if(o>e.getDistance(l[s],l[s+1]))return new HitResult(0==s?"segment":"handle-"+(2==s?"in":"out"),h,{segment:n})}var r,s,o=t.tolerance||0,a=(t.stroke?this.getStrokeWidth()/2:0)+o,l=[],h=this;if(!t.ends||t.segments||this._closed){if(t.segments||t.handles)for(var c=0,u=this._segments.length;u>c;c++)if(s=n(this._segments[c]))return s}else if(s=n(this.getFirstSegment(),!0)||n(this.getLastSegment(),!0))return s;return t.stroke&&a>0&&(r=this.getNearestLocation(e,i)),!(r&&a>=r._distance)&&t.fill&&this.getFillColor()&&this.contains(e,i)?new HitResult("fill",this):(!r&&t.stroke&&a>0&&(r=this.getNearestLocation(e,i)),r&&a>=r._distance?t.stroke?new HitResult("stroke",this,{location:r}):new HitResult("fill",this):void 0)}},new function(){function e(e,i){for(var n=0,r=i.length;r>n;n++){var s=i[n],o=s._point,a=s._selectionState,l=a&SelectionState.POINT;(l||a&SelectionState.HANDLE_IN)&&t(e,o,s._handleIn),(l||a&SelectionState.HANDLE_OUT)&&t(e,o,s._handleOut),e.save(),e.beginPath(),e.rect(o._x-2,o._y-2,4,4),e.fill(),l||(e.beginPath(),e.rect(o._x-1,o._y-1,2,2),e.fillStyle="#ffffff",e.fill()),e.restore()}}function t(e,t,i){if(!i.isZero()){var n=t._x+i._x,r=t._y+i._y;e.beginPath(),e.moveTo(t._x,t._y),e.lineTo(n,r),e.stroke(),e.beginPath(),e.arc(n,r,1.75,0,2*Math.PI,!0),e.fill()}}function i(e,t){function i(t){var i=o[t],a=i._point,l=a._x,h=a._y,c=i._handleIn;n?c.isZero()&&n.isZero()?e.lineTo(l,h):e.bezierCurveTo(r,s,c._x+l,c._y+h,l,h):e.moveTo(l,h),n=i._handleOut,r=n._x+l,s=n._y+h}for(var n,r,s,o=t._segments,a=o.length,l=0;a>l;l++)i(l);t._closed&&a>1&&i(0)}function n(e,t,i,n){for(var r,s=new PathFlattener(t),o=n,a=0;s.length>o;)r=o+i[a++%i.length],s.drawPart(e,o,r),o=r+i[a++%i.length]}return{draw:function(t,r){r.compound||t.beginPath();var s=this.getFillColor(),o=this.getStrokeColor(),a=this.getDashArray()||[],l=!!a.length;(r.compound||r.selection||this._clipMask||s||o&&!l)&&i(t,this),r.selection?(t.stroke(),e(t,this._segments)):this._clipMask?t.clip():r.compound||!s&&!o||(t.save(),this._setStyles(t),s&&o||(t.globalAlpha=this._opacity),s&&(t.fillStyle=s.getCanvasStyle(t),t.fill()),o&&(t.strokeStyle=o.getCanvasStyle(t),l&&(t.beginPath(),n(t,this,a,this.getDashOffset())),t.stroke()),t.restore())}}},new function(){function e(e){var t=e.length,i=[],n=[],r=2;i[0]=e[0]/r;for(var s=1;t>s;s++)n[s]=1/r,r=(t-1>s?4:2)-n[s],i[s]=(e[s]-i[s-1])/r;for(var s=1;t>s;s++)i[t-s-1]-=n[t-s]*i[t-s];return i}var t={getStrokeWidth:"lineWidth",getStrokeJoin:"lineJoin",getStrokeCap:"lineCap",getMiterLimit:"miterLimit"};return{_setStyles:function(e){for(var i in t){var n=this._style[i]();n&&(e[t[i]]=n)}},smooth:function(){var t,i=this._segments,n=i.length,r=n;if(!(2>=n)){this._closed?(t=Math.min(n,4),r+=2*Math.min(n,t)):t=0;for(var s=[],o=0;n>o;o++)s[o+t]=i[o]._point;if(this._closed)for(var o=0;t>o;o++)s[o]=i[o+n-t]._point,s[o+n+t]=i[o]._point;else r--;for(var a=[],o=1;r-1>o;o++)a[o]=4*s[o]._x+2*s[o+1]._x;a[0]=s[0]._x+2*s[1]._x,a[r-1]=3*s[r-1]._x;for(var l=e(a),o=1;r-1>o;o++)a[o]=4*s[o]._y+2*s[o+1]._y;a[0]=s[0]._y+2*s[1]._y,a[r-1]=3*s[r-1]._y;var h=e(a);if(this._closed){for(var o=0,c=n;t>o;o++,c++){var u=o/t,d=1-u;l[c]=l[o]*u+l[c]*d,h[c]=h[o]*u+h[c]*d;var p=o+t,f=c+t;l[f]=l[p]*d+l[f]*u,h[f]=h[p]*d+h[f]*u}r--}for(var m=null,o=t;r-t>=o;o++){var g=i[o-t];m&&g.setHandleIn(m.subtract(g._point)),r>o&&(g.setHandleOut(new Point(l[o],h[o]).subtract(g._point)),m=r-1>o?new Point(2*s[o+1]._x-l[o+1],2*s[o+1]._y-h[o+1]):new Point((s[r]._x+l[r-1])/2,(s[r]._y+h[r-1])/2))}if(this._closed&&m){var g=this._segments[0];g.setHandleIn(m.subtract(g._point))}}}}},new function(){function e(e){var t=e._segments;if(0==t.length)throw Error("Use a moveTo() command first");return t[t.length-1]}return{moveTo:function(){this._segments.length||this._add([new Segment(Point.read(arguments))])},moveBy:function(){throw Error("moveBy() is unsupported on Path items.")},lineTo:function(){this._add([new Segment(Point.read(arguments))])},cubicCurveTo:function(t,i,n){t=Point.read(arguments,0,1),i=Point.read(arguments,1,1),n=Point.read(arguments,2,1);var r=e(this);r.setHandleOut(t.subtract(r._point)),this._add([new Segment(n,i.subtract(n))])},quadraticCurveTo:function(t,i){t=Point.read(arguments,0,1),i=Point.read(arguments,1,1);var n=e(this)._point;this.cubicCurveTo(t.add(n.subtract(t).multiply(1/3)),t.add(i.subtract(t).multiply(1/3)),i)},curveTo:function(t,i,n){t=Point.read(arguments,0,1),i=Point.read(arguments,1,1);var r=Base.pick(n,.5),s=1-r,o=e(this)._point,a=t.subtract(o.multiply(s*s)).subtract(i.multiply(r*r)).divide(2*r*s);if(a.isNaN())throw Error("Cannot put a curve through points with parameter = "+r);this.quadraticCurveTo(a,i)},arcTo:function(t,i){var n,r=e(this),s=r._point;if(void 0===i&&(i=!0),"boolean"==typeof i){t=Point.read(arguments,0,1);var o=s.add(t).divide(2),n=o.add(o.subtract(s).rotate(i?-90:90))}else n=Point.read(arguments,0,1),t=Point.read(arguments,1,1);var a=new Line(s.add(n).divide(2),n.subtract(s).rotate(90)),l=new Line(n.add(t).divide(2),t.subtract(n).rotate(90)),h=a.intersect(l),c=new Line(s,t,!0),u=c.getSide(n);if(!h){if(!u)return this.lineTo(t);throw Error("Cannot put an arc through the given points: "+[s,n,t])}var d=s.subtract(h),p=(d.getLength(),d.getDirectedAngle(t.subtract(h))),f=c.getSide(h);0==f?p=u*Math.abs(p):u==f&&(p-=360*(0>p?-1:1));for(var m=Math.abs(p),g=m>=360?4:Math.ceil(m/90),y=p/g,v=y*Math.PI/360,b=4/3*Math.sin(v)/(1+Math.cos(v)),L=[],x=0;g>=x;x++){var C=g>x?h.add(d):t,w=g>x?d.rotate(90).multiply(b):null;0==x?r.setHandleOut(w):L.push(new Segment(C,d.rotate(-90).multiply(b),w)),d=d.rotate(y)}this._add(L)},lineBy:function(t){t=Point.read(arguments);var i=e(this);this.lineTo(i._point.add(t))},curveBy:function(t,i,n){t=Point.read(t),i=Point.read(i);var r=e(this)._point;this.curveTo(r.add(t),r.add(i),n)},arcBy:function(t,i){t=Point.read(t),i=Point.read(i);var n=e(this)._point;this.arcBy(n.add(t),n.add(i))},closePath:function(){this.setClosed(!0)}}},new function(){function e(e,t,i){function n(e){function n(e,t){var n=0;if(null==e){var o=1-t;e=o*o*o*s+3*o*o*t*d+3*o*t*t*p+t*t*t*f,n=i?i[r]:0}var a=e-n,c=e+n;l[r]>a&&(l[r]=a),c>h[r]&&(h[r]=c)}e._transformCoordinates(t,o,!1);for(var r=0;2>r;r++){var s=a[r],d=a[r+4],p=o[r+2],f=o[r];n(f,null);var m=3*(d-p)-s+f,g=2*(s+p)-4*d,y=d-s;if(0!=m){var v=g*g-4*m*y;if(!(0>v)){var b=Math.sqrt(v),L=-.5/m,x=(g-b)*L,C=(g+b)*L;x>c&&u>x&&n(null,x),C>c&&u>C&&n(null,C)}}else{if(0==g)continue;var w=-y/g;w>c&&u>w&&n(null,w)}}var S=a;a=o,o=S}var r=e._segments,s=r[0];if(!s)return null;var o=Array(6),a=Array(6);t&&t.isIdentity()&&(t=null),s._transformCoordinates(t,a,!1);for(var l=a.slice(0,2),h=l.slice(0),c=Numerical.TOLERANCE,u=1-c,d=1,p=r.length;p>d;d++)n(r[d]);return e._closed&&n(s),Rectangle.create(l[0],l[1],h[0]-l[0],h[1]-l[1])}function t(e,t){if(!t)return[e,e];var i=t.createShiftless(),n=i.transform(new Point(e,0)),r=i.transform(new Point(0,e)),s=n.getAngleInRadians(),o=n.getLength(),a=r.getLength(),l=-Math.atan(a*Math.tan(s)),h=+Math.atan(a/Math.tan(s)),c=o*Math.cos(l)*Math.cos(s)-a*Math.sin(l)*Math.sin(s),u=a*Math.sin(h)*Math.cos(s)+o*Math.cos(h)*Math.sin(s);return[Math.abs(c),Math.abs(u)]}return{getBounds:function(){var t=void 0===arguments[0];if(t&&this._bounds)return this._bounds;var i=this._createBounds(e(this,arguments[0]));return t&&(this._bounds=i),i},getStrokeBounds:function(){function i(e){g=g.include(a?a.transform(e):e)}function n(e,t){var n=e.getPoint(t),r=e.getNormal(t).normalize(h);i(n.add(r)),i(n.subtract(r))}function r(e,t){if("round"===t||!e._handleIn.isZero()&&!e._handleOut.isZero())g=g.unite(y.setCenter(a?a.transform(e._point):e._point));else if("bevel"==t){var s=e.getCurve();n(s,0),n(s.getPrevious(),1)}else if("miter"==t){var o=e.getCurve(),l=o.getPrevious(),c=o.getPoint(0),u=l.getNormal(1).normalize(h),d=o.getNormal(0).normalize(h),f=new Line(c.subtract(u),new Point(-u.y,u.x)),m=new Line(c.subtract(d),new Point(-d.y,d.x)),v=f.intersect(m);!v||c.getDistance(v)>p?r(e,"bevel"):i(v)}}function s(e,t,n){switch(t){case"round":return r(e,t);case"butt":case"square":var s=e.getCurve(),o=s.getPoint(n),a=s.getNormal(n).normalize(h);"square"===t&&(o=o.add(a.y,-a.x)),i(o.add(a)),i(o.subtract(a))}}if(!this._style._strokeColor||!this._style._strokeWidth)return this.getBounds.apply(this,arguments);var o=void 0===arguments[0];if(o&&this._strokeBounds)return this._strokeBounds;for(var a=arguments[0],l=this.getStrokeWidth(),h=l/2,c=t(h,a),u=this.getStrokeJoin(),d=this.getStrokeCap(),p=this.getMiterLimit()*l/2,f=this._segments,m=f.length,g=e(this,a,t(h)),y=new Rectangle(new Size(c).multiply(2)),v=1,b=m-(this._closed?0:1);b>v;v++)r(f[v],u);return this._closed?r(f[0],u):(s(f[0],d,0),s(f[m-1],d,1)),o&&(this._strokeBounds=g),g},getHandleBounds:function(){var e=arguments[0],t=void 0===e;if(t&&this._handleBounds)return this._handleBounds;for(var i=Array(6),n=arguments[1]/2||0,r=arguments[2]/2||0,s=(!this._closed,1/0),o=-s,a=s,l=o,h=0,c=this._segments.length;c>h;h++){var u=this._segments[h];u._transformCoordinates(e,i,!1);for(var d=0;6>d;d+=2){var p=0==d?r:n,f=i[d],m=i[d+1],g=f-p,y=f+p,v=m-p,b=m+p;s>g&&(s=g),y>o&&(o=y),a>v&&(a=v),b>l&&(l=b)}}var L=Rectangle.create(s,a,o-s,l-a);return t&&(this._handleBounds=L),L},getRoughBounds:function(){var e=void 0===arguments[0];if(e&&this._roughBounds)return this._roughBounds;var t=this.getHandleBounds(arguments[0],this.strokeWidth,"miter"==this.getStrokeJoin()?this.strokeWidth*this.getMiterLimit():this.strokeWidth);return e&&(this._roughBounds=t),t}}});Path.inject({statics:new function(){var e=2/3*(Math.sqrt(2)-1),t=[new Segment([0,.5],[0,e],[0,-e]),new Segment([.5,0],[-e,0],[e,0]),new Segment([1,.5],[0,-e],[0,e]),new Segment([.5,1],[e,0],[-e,0])];return{Line:function(){var e=Math.floor(arguments.length/2);return new Path(Segment.read(arguments,0,e),Segment.read(arguments,e,e))},Rectangle:function(e){e=Rectangle.read(arguments);var t=e.x,i=e.y;return right=t+e.width,bottom=i+e.height,path=new Path,path._add([new Segment(Point.create(t,bottom)),new Segment(Point.create(t,i)),new Segment(Point.create(right,i)),new Segment(Point.create(right,bottom))]),path._closed=!0,path},RoundRectangle:function(t,i){2==arguments.length?(t=Rectangle.read(arguments,0,1),i=Size.read(arguments,1,1)):6==arguments.length&&(t=Rectangle.read(arguments,0,4),i=Size.read(arguments,4,2)),i=Size.min(i,t.getSize(!0).divide(2));var n=new Path,r=i.multiply(2*e),s=t.getBottomLeft(!0),o=t.getTopLeft(!0),a=t.getTopRight(!0),l=t.getBottomRight(!0);return n._add([new Segment(s.add(i.width,0),null,[-r.width,0]),new Segment(s.subtract(0,i.height),[0,r.height],null),new Segment(o.add(0,i.height),null,[0,-r.height]),new Segment(o.add(i.width,0),[-r.width,0],null),new Segment(a.subtract(i.width,0),null,[r.width,0]),new Segment(a.add(0,i.height),[0,-r.height],null),new Segment(l.subtract(0,i.height),null,[0,r.height]),new Segment(l.subtract(i.width,0),[r.width,0],null)]),n._closed=!0,n},Oval:function(e){e=Rectangle.read(arguments);for(var i=new Path,n=e.getPoint(!0),r=e.getSize(!0),s=Array(4),o=0;4>o;o++){var a=t[o];s[o]=new Segment(a._point.multiply(r).add(n),a._handleIn.multiply(r),a._handleOut.multiply(r))}return i._add(s),i._closed=!0,i},Circle:function(e,t){return 3==arguments.length?(e=Point.read(arguments,0,2),t=arguments[2]):e=Point.read(arguments,0,1),Path.Oval(new Rectangle(e.subtract(t),Size.create(2*t,2*t)))},Arc:function(e,t,i){var n=new Path;return n.moveTo(e),n.arcTo(t,i),n},RegularPolygon:function(e,t,i){e=Point.read(arguments,0,1);for(var n=new Path,r=360/t,s=!(t%3),o=new Point(0,s?-i:i),a=s?-1:.5,l=Array(t),h=0;t>h;h++)l[h]=new Segment(e.add(o.rotate((h+a)*r)));return n._add(l),n._closed=!0,n},Star:function(e,t,i,n){e=Point.read(arguments,0,1),t*=2;for(var r=new Path,s=360/t,o=new Point(0,-1),a=Array(t),l=0;t>l;l++)a[l]=new Segment(e.add(o.rotate(s*l).multiply(l%2?n:i)));return r._add(a),r._closed=!0,r}}}});var CompoundPath=this.CompoundPath=PathItem.extend({initialize:function(e){this.base(),this._children=[],this._namedChildren={};var t=e&&Array.isArray(e)&&"object"==typeof e[0]?e:arguments;this.addChildren(t)},insertChild:function(e,t){this.base(e,t),void 0===t._clockwise&&t.setClockwise(0==t._index)},simplify:function(){if(1==this._children.length){var e=this._children[0];return e.insertAbove(this),this.remove(),e}return this},smooth:function(){for(var e=0,t=this._children.length;t>e;e++)this._children[e].smooth()},draw:function(e,t){var i=this._children.length;if(0!=i){var n=this._children[0];e.beginPath(),t.compound=!0;for(var r=0;i>r;r++)Item.draw(this._children[r],e,t);n._setStyles(e);var s=n.getFillColor(),o=n.getStrokeColor();s&&(e.fillStyle=s.getCanvasStyle(e),e.fill()),o&&(e.strokeStyle=o.getCanvasStyle(e),e.stroke()),t.compound=!1}}},new function(){function e(e){if(!e._children.length)throw Error("Use a moveTo() command first");return e._children[e._children.length-1]}var t={moveTo:function(){var e=new Path;this.addChild(e),e.moveTo.apply(e,arguments)},moveBy:function(){this.moveTo(e(this).getLastSegment()._point.add(Point.read(arguments)))},closePath:function(){e(this).setClosed(!0)}};return Base.each(["lineTo","cubicCurveTo","quadraticCurveTo","curveTo","arcTo","lineBy","curveBy","arcBy"],function(i){t[i]=function(){var t=e(this);t[i].apply(t,arguments)}}),t}),PathFlattener=Base.extend({initialize:function(e){function t(e,t){var i=Curve.getValues(e,t);s.curves.push(i),s._computeParts(i,e._index,0,1)}this.curves=[],this.parts=[],this.length=0,this.index=0;for(var i,n=e._segments,r=n[0],s=this,o=1,a=n.length;a>o;o++)i=n[o],t(r,i),r=i;e._closed&&t(i,n[0])},_computeParts:function(e,t,i,n){if(n-i>1/32&&!Curve.isFlatEnough(e)){var r=Curve.subdivide(e),s=(i+n)/2;this._computeParts(r[0],t,i,s),this._computeParts(r[1],t,s,n)}else{var o=e[6]-e[0],a=e[7]-e[1],l=Math.sqrt(o*o+a*a);l>Numerical.TOLERANCE&&(this.length+=l,this.parts.push({offset:this.length,value:n,index:t}))}},getParameterAt:function(e){for(var t,i=this.index;t=i,!(0==i||e>this.parts[--i].offset););for(var n=this.parts.length;n>t;t++){var r=this.parts[t];if(r.offset>=e){this.index=t;var s=this.parts[t-1],o=s&&s.index==r.index?s.value:0,a=s?s.offset:0;return{value:o+(r.value-o)*(e-a)/(r.offset-a),index:r.index}}}var r=this.parts[this.parts.length-1];return{value:1,index:r.index}},evaluate:function(e,t){var i=this.getParameterAt(e);return Curve.evaluate(this.curves[i.index],i.value,t)},drawPart:function(e,t,i){t=this.getParameterAt(t),i=this.getParameterAt(i);for(var n=t.index;i.index>=n;n++){var r=Curve.getPart(this.curves[n],n==t.index?t.value:0,n==i.index?i.value:1);n==t.index&&e.moveTo(r[0],r[1]),e.bezierCurveTo.apply(e,r.slice(2))}}}),PathFitter=Base.extend({initialize:function(e,t){this.points=[];for(var i,n=e._segments,r=0,s=n.length;s>r;r++){var o=n[r].point.clone();i&&i.equals(o)||(this.points.push(o),i=o)}this.error=t},fit:function(){return this.segments=[new Segment(this.points[0])],this.fitCubic(0,this.points.length-1,this.points[1].subtract(this.points[0]).normalize(),this.points[this.points.length-2].subtract(this.points[this.points.length-1]).normalize()),this.segments},fitCubic:function(e,t,i,n){if(1==t-e){var r=this.points[e],s=this.points[t],o=r.getDistance(s)/3;return this.addCurve([r,r.add(i.normalize(o)),s.add(n.normalize(o)),s]),void 0}for(var a,l=this.chordLengthParameterize(e,t),h=Math.max(this.error,this.error*this.error),c=0;4>=c;c++){var u=this.generateBezier(e,t,l,i,n),d=this.findMaxError(e,t,u,l);if(d.error=h)break;this.reparameterize(e,t,l,u),h=d.error}var p=this.points[a-1].subtract(this.points[a]),f=this.points[a].subtract(this.points[a+1]),m=p.add(f).divide(2).normalize();this.fitCubic(e,a,i,m),this.fitCubic(a,t,m.negate(),n)},addCurve:function(e){var t=this.segments[this.segments.length-1];t.setHandleOut(e[1].subtract(e[0])),this.segments.push(new Segment(e[3],e[2].subtract(e[3])))},generateBezier:function(e,t,i,n,r){for(var s=Numerical.EPSILON,o=this.points[e],a=this.points[t],l=[[0,0],[0,0]],h=[0,0],c=0,u=t-e+1;u>c;c++){var d=i[c],p=1-d,f=3*d*p,m=p*p*p,g=f*p,y=f*d,v=d*d*d,b=n.normalize(g),L=r.normalize(y),x=this.points[e+c].subtract(o.multiply(m+g)).subtract(a.multiply(y+v));l[0][0]+=b.dot(b),l[0][1]+=b.dot(L),l[1][0]=l[0][1],l[1][1]+=L.dot(L),h[0]+=b.dot(x),h[1]+=L.dot(x)}var C,w,S=l[0][0]*l[1][1]-l[1][0]*l[0][1];if(Math.abs(S)>s){var O=l[0][0]*h[1]-l[1][0]*h[0],_=h[0]*l[1][1]-h[1]*l[0][1];C=_/S,w=O/S}else{var E=l[0][0]+l[0][1],T=l[1][0]+l[1][1];C=w=Math.abs(E)>s?h[0]/E:Math.abs(E)>s?h[1]/T:0}var k=a.getDistance(o);return s*=k,(s>C||s>w)&&(C=w=k/3),[o,o.add(n.normalize(C)),a.add(r.normalize(w)),a]},reparameterize:function(e,t,i,n){for(var r=e;t>=r;r++)i[r-e]=this.findRoot(n,this.points[r],i[r-e])},findRoot:function(e,t,i){for(var n=[],r=[],s=0;2>=s;s++)n[s]=e[s+1].subtract(e[s]).multiply(3);for(var s=0;1>=s;s++)r[s]=n[s+1].subtract(n[s]).multiply(2);var o=this.evaluate(3,e,i),a=this.evaluate(2,n,i),l=this.evaluate(1,r,i),h=o.subtract(t),c=a.dot(a)+h.dot(l);return Math.abs(c)=r;r++)for(var s=0;e-r>=s;s++)n[s]=n[s].multiply(1-i).add(n[s+1].multiply(i));return n[0]},chordLengthParameterize:function(e,t){for(var i=[0],n=e+1;t>=n;n++)i[n-e]=i[n-e-1]+this.points[n].getDistance(this.points[n-1]);for(var n=1,r=t-e;r>=n;n++)i[n]/=i[r];return i},findMaxError:function(e,t,i,n){for(var r=Math.floor((t-e+1)/2),s=0,o=e+1;t>o;o++){var a=this.evaluate(3,i,n[o-e]),l=a.subtract(this.points[o]),h=l.x*l.x+l.y*l.y;h>=s&&(s=h,r=o)}return{error:s,index:r}}}),TextItem=this.TextItem=Item.extend({initialize:function(){this.base(),this._content="",this._characterStyle=CharacterStyle.create(this),this.setCharacterStyle(this._project.getCurrentStyle()),this._paragraphStyle=ParagraphStyle.create(this),this.setParagraphStyle()},_clone:function(e){return e._content=this._content,e.setCharacterStyle(this._characterStyle),e.setParagraphStyle(this._paragraphStyle),this.base(e)},getContent:function(){return this._content},setContent:function(e){this._changed(Change.CONTENT),this._content=""+e},getCharacterStyle:function(){return this._characterStyle},setCharacterStyle:function(e){this._characterStyle.initialize(e)},getParagraphStyle:function(){return this._paragraphStyle},setParagraphStyle:function(e){this._paragraphStyle.initialize(e)}}),PointText=this.PointText=TextItem.extend({initialize:function(){this.base(),this._point=Point.read(arguments).clone(),this._matrix=(new Matrix).translate(this._point)},clone:function(){var e=this._clone(new PointText(this._point));return e._matrix.initialize(this._matrix),e},getPoint:function(){return LinkedPoint.create(this,"setPoint",this._point.x,this._point.y)},setPoint:function(){this.translate(Point.read(arguments).subtract(this._point))},getPosition:function(){return this.getPoint()},setPosition:function(){this.setPoint.apply(this,arguments)},_transform:function(e){this._matrix.preConcatenate(e),e._transformPoint(this._point,this._point)},draw:function(e){if(this._content){e.save(),e.font=this.getFontSize()+"pt "+this.getFont(),e.textAlign=this.getJustification(),this._matrix.applyToContext(e);var t=this.getFillColor(),i=this.getStrokeColor();t&&i||(e.globalAlpha=this._opacity),t&&(e.fillStyle=t.getCanvasStyle(e),e.fillText(this._content,0,0)),i&&(e.strokeStyle=i.getCanvasStyle(e),e.strokeText(this._content,0,0)),e.restore()}}}),Style=Item.extend({initialize:function(e){var t=e instanceof Style;return Base.each(this._defaults,function(i,n){i=e&&e[n]||i,this[n]=i&&t&&i.clone?i.clone():i},this)},statics:{create:function(e){var t=new this(this.dont);return t._item=e,t},extend:function(e){var t=e._style,i=e._flags||{};return e._owner.inject(Base.each(e._defaults,function(n,r){var s=!!r.match(/Color$/),o=Base.capitalize(r),a="set"+o,l="get"+o;e[a]=function(e){var n=this._item&&this._item._children;if(e=s?Color.read(arguments):e,n)for(var o=0,l=n.length;l>o;o++)n[o][t][a](e);else{var h=this["_"+r];h==e||h&&h.equals&&h.equals(e)||(this["_"+r]=e,s&&(h&&h._removeOwner(this._item),e&&e._addOwner(this._item)),this._item&&this._item._changed(i[r]||Change.STYLE))}return this},e[l]=function(){var e,i=this._item&&this._item._children;if(!i)return this["_"+r];for(var n=0,s=i.length;s>n;n++){var o=i[n][t][l]();if(e){if(e!=o&&!(e&&e.equals&&e.equals(o)))return void 0}else e=o}return e},this[a]=function(e){return this[t][a](e),this},this[l]=function(){return this[t][l]()}},{})),this.base(e)}}}),PathStyle=this.PathStyle=Style.extend({_defaults:{fillColor:void 0,strokeColor:void 0,strokeWidth:1,strokeCap:"butt",strokeJoin:"miter",miterLimit:10,dashOffset:0,dashArray:[]},_flags:{strokeWidth:Change.STROKE,strokeCap:Change.STROKE,strokeJoin:Change.STROKE,miterLimit:Change.STROKE},_owner:Item,_style:"_style"}),ParagraphStyle=this.ParagraphStyle=Style.extend({_defaults:{justification:"left"},_owner:TextItem,_style:"_paragraphStyle"}),CharacterStyle=this.CharacterStyle=PathStyle.extend({_defaults:Base.merge(PathStyle.prototype._defaults,{fillColor:"black",fontSize:10,font:"sans-serif"}),_owner:TextItem,_style:"_characterStyle"}),Color=this.Color=Base.extend(new function(){function e(e){var t=r[e];if(t)return t.clone();if(!i){var n=CanvasProvider.getCanvas(Size.create(1,1));i=n.getContext("2d"),i.globalCompositeOperation="copy"}i.fillStyle="rgba(0,0,0,0)",i.fillStyle=e,i.fillRect(0,0,1,1);var s=i.getImageData(0,0,1,1).data,o=[s[0]/255,s[1]/255,s[2]/255];return(r[e]=RgbColor.read(o)).clone()}function t(e){var t=e.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);if(t.length>=4){for(var i=Array(3),n=0;3>n;n++){var r=t[n+1];i[n]=parseInt(1==r.length?r+r:r,16)/255}return RgbColor.read(i)}}var i,n={gray:["gray"],rgb:["red","green","blue"],hsb:["hue","saturation","brightness"],hsl:["hue","saturation","lightness"]},r={},s=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]],o={"rgb-hsb":function(e){var t=e._red,i=e._green,n=e._blue,r=Math.max(t,i,n),s=Math.min(t,i,n),o=r-s,a=0==o?0:60*(r==t?(i-n)/o+(n>i?6:0):r==i?(n-t)/o+2:(t-i)/o+4),l=0==r?0:o/r,h=r;return new HsbColor(a,l,h,e._alpha)},"hsb-rgb":function(e){var t=e._hue/60%6,i=e._saturation,n=e._brightness,r=Math.floor(t),o=t-r,r=s[r],a=[n,n*(1-i),n*(1-i*o),n*(1-i*(1-o))];return new RgbColor(a[r[0]],a[r[1]],a[r[2]],e._alpha)},"rgb-hsl":function(e){var t=e._red,i=e._green,n=e._blue,r=Math.max(t,i,n),s=Math.min(t,i,n),o=r-s,a=0==o,l=a?0:60*(r==t?(i-n)/o+(n>i?6:0):r==i?(n-t)/o+2:(t-i)/o+4),h=(r+s)/2,c=a?0:.5>h?o/(r+s):o/(2-r-s);return new HslColor(l,c,h,e._alpha)},"hsl-rgb":function(e){var t,i,n,r=e._saturation,s=e._hue/360,o=e._lightness;if(0==r)return new RgbColor(o,o,o,e._alpha);for(var a=[s+1/3,s,s-1/3],i=.5>o?o*(1+r):o+r-o*r,t=2*o-i,n=[],l=0;3>l;l++){var h=a[l];0>h&&(h+=1),h>1&&(h-=1),n[l]=1>6*h?t+6*(i-t)*h:1>2*h?i:2>3*h?t+6*(i-t)*(2/3-h):t}return new RgbColor(n[0],n[1],n[2],e._alpha)},"rgb-gray":function(e){return new GrayColor(1-(.2989*e._red+.587*e._green+.114*e._blue),e._alpha)},"gray-rgb":function(e){var t=1-e._gray;return new RgbColor(t,t,t,e._alpha)},"gray-hsb":function(e){return new HsbColor(0,0,1-e._gray,e._alpha)},"gray-hsl":function(e){return new HslColor(0,0,1-e._gray,e._alpha)}},a={_readNull:!0,initialize:function(i){var n=Array.isArray(i),r=this._colorType;if("object"==typeof i&&!n)return r?Color.read(arguments).convert(r):void 0!==i.red?new RgbColor(i.red,i.green,i.blue,i.alpha):void 0!==i.gray?new GrayColor(i.gray,i.alpha):void 0!==i.lightness?new HslColor(i.hue,i.saturation,i.lightness,i.alpha):void 0!==i.hue?new HsbColor(i.hue,i.saturation,i.brightness,i.alpha):new RgbColor;if("string"==typeof i){var s=i.match(/^#[0-9a-f]{3,6}$/i)?t(i):e(i);return r?s.convert(r):s}var o=n?i:Array.prototype.slice.call(arguments);return r?(Base.each(this._components,function(e,t){var i=o[t];this["_"+e]=void 0!==i?i:null},this),void 0):o.length>=3?new RgbColor(o):new GrayColor(o)},clone:function(){for(var e=this.constructor,t=new e(e.dont),i=this._components,n=0,r=i.length;r>n;n++){var s="_"+i[n];t[s]=this[s]}return t},convert:function(e){var t;return this._colorType==e?this.clone():(t=o[this._colorType+"-"+e])?t(this):o["rgb-"+e](o[this._colorType+"-rgb"](this))},statics:{extend:function(e){if(e.beans=!0,e._colorType){var t=n[e._colorType];e._components=t.concat(["alpha"]),Base.each(t,function(e){var t="hue"===e,i=Base.capitalize(e),e="_"+e;this["get"+i]=function(){return this[e]},this["set"+i]=function(i){return this[e]=t?(i%360+360)%360:Math.min(Math.max(i,0),1),this._changed(),this}},e)}return this.base(e)}}};return Base.each(n,function(e,t){Base.each(e,function(e){var i=Base.capitalize(e);a["get"+i]=function(){return this.convert(t)[e]},a["set"+i]=function(i){var n=this.convert(t);n[e]=i,n=n.convert(this._colorType);for(var r=0,s=this._components.length;s>r;r++){var o=this._components[r];this[o]=n[o]}}})}),a},{_changed:function(){this._cssString=null;for(var e=0,t=this._owners&&this._owners.length;t>e;e++)this._owners[e]._changed(Change.STYLE)},_addOwner:function(e){this._owners||(this._owners=[]),this._owners.push(e)},_removeOwner:function(e){var t=this._owners?this._owners.indexOf(e):-1;-1!=t&&(this._owners.splice(t,1),0==this._owners.length&&delete this._owners)},getType:function(){return this._colorType},getComponents:function(){for(var e=this._components.length,t=Array(e),i=0;e>i;i++)t[i]=this["_"+this._components[i]];return t},getAlpha:function(){return null!=this._alpha?this._alpha:1},setAlpha:function(e){return this._alpha=null==e?null:Math.min(Math.max(e,0),1),this._changed(),this},hasAlpha:function(){return null!=this._alpha},equals:function(e){if(e&&e._colorType===this._colorType){for(var t=0,i=this._components.length;i>t;t++){var n="_"+this._components[t];if(this[n]!==e[n])return!1}return!0}return!1},toString:function(){for(var e=[],t=Base.formatNumber,i=0,n=this._components.length;n>i;i++){var r=this._components[i],s=this["_"+r];"alpha"===r&&null==s&&(s=1),e.push(r+": "+t(s))}return"{ "+e.join(", ")+" }"},toCssString:function(){if(!this._cssString){var e=this.convert("rgb"),t=e.getAlpha(),i=[Math.round(255*e._red),Math.round(255*e._green),Math.round(255*e._blue),null!=t?t:1];this._cssString="rgba("+i.join(", ")+")"}return this._cssString},getCanvasStyle:function(){return this.toCssString()}}),GrayColor=this.GrayColor=Color.extend({_colorType:"gray"}),RgbColor=this.RgbColor=this.RGBColor=Color.extend({_colorType:"rgb"}),HsbColor=this.HsbColor=this.HSBColor=Color.extend({_colorType:"hsb"}),HslColor=this.HslColor=this.HSLColor=Color.extend({_colorType:"hsl"}),GradientColor=this.GradientColor=Color.extend({initialize:function(e,t,i,n){this.gradient=e||new Gradient,this.setOrigin(t),this.setDestination(i),n&&this.setHilite(n)},clone:function(){return new GradientColor(this.gradient,this._origin,this._destination,this._hilite)},getOrigin:function(){return this._origin},setOrigin:function(e){return e=Point.read(arguments).clone(),this._origin=e,this._destination&&(this._radius=this._destination.getDistance(this._origin)),this._changed(),this},getDestination:function(){return this._destination},setDestination:function(e){return e=Point.read(arguments).clone(),this._destination=e,this._radius=this._destination.getDistance(this._origin),this._changed(),this},getHilite:function(){return this._hilite},setHilite:function(e){e=Point.read(arguments).clone();var t=e.subtract(this._origin);return this._hilite=t.getLength()>this._radius?this._origin.add(t.normalize(this._radius-.1)):e,this._changed(),this},getCanvasStyle:function(e){var t;if("linear"===this.gradient.type)t=e.createLinearGradient(this._origin.x,this._origin.y,this._destination.x,this._destination.y);else{var i=this._hilite||this._origin;t=e.createRadialGradient(i.x,i.y,0,this._origin.x,this._origin.y,this._radius)}for(var n=0,r=this.gradient._stops.length;r>n;n++){var s=this.gradient._stops[n];t.addColorStop(s._rampPoint,s._color.toCssString())}return t},equals:function(e){return e==this||e&&e._colorType===this._colorType&&this.gradient.equals(e.gradient)&&this._origin.equals(e._origin)&&this._destination.equals(e._destination)},transform:function(e){e._transformPoint(this._origin,this._origin,!0),e._transformPoint(this._destination,this._destination,!0),this._hilite&&e._transformPoint(this._hilite,this._hilite,!0),this._radius=this._destination.getDistance(this._origin)}}),Gradient=this.Gradient=Base.extend({initialize:function(e,t){this.setStops(e||["white","black"]),this.type=t||"linear"},clone:function(){for(var e=[],t=0,i=this._stops.length;i>t;t++)e[t]=this._stops[t].clone();return new Gradient(e,this.type)},getStops:function(){return this._stops},setStops:function(e){if(2>e.length)throw Error("Gradient stop list needs to contain at least two stops."); +this._stops=GradientStop.readAll(e);for(var t=0,i=this._stops.length;i>t;t++){var n=this._stops[t];n._defaultRamp&&n.setRampPoint(t/(i-1))}},equals:function(e){if(e.type!=this.type)return!1;if(this._stops.length==e._stops.length){for(var t=0,i=this._stops.length;i>t;t++)if(!this._stops[t].equals(e._stops[t]))return!1;return!0}return!1}}),GradientStop=this.GradientStop=Base.extend({initialize:function(e,t){void 0===t&&Array.isArray(e)?(this.setColor(e[0]),this.setRampPoint(e[1])):e.color?(this.setColor(e.color),this.setRampPoint(e.rampPoint)):(this.setColor(e),this.setRampPoint(t))},clone:function(){return new GradientStop(this._color.clone(),this._rampPoint)},getRampPoint:function(){return this._rampPoint},setRampPoint:function(e){this._defaultRamp=null==e,this._rampPoint=e||0},getColor:function(){return this._color},setColor:function(){this._color=Color.read(arguments)},equals:function(e){return e==this||e instanceof GradientStop&&this._color.equals(e._color)&&this._rampPoint==e._rampPoint}}),DomElement={getBounds:function(e,t){var i=e.getBoundingClientRect(),n=e.ownerDocument,r=n.body,s=n.documentElement,o=i.left-(s.clientLeft||r.clientLeft||0),a=i.top-(s.clientTop||r.clientTop||0);if(!t){var l=DomElement.getViewport(n);o+=l.pageXOffset||s.scrollLeft||r.scrollLeft,a+=l.pageYOffset||s.scrollTop||r.scrollTop}return new Rectangle(o,a,i.width,i.height)},getOffset:function(e,t){return this.getBounds(e,t).getPoint()},getSize:function(e){return this.getBounds(e,!0).getSize()},isInvisible:function(e){return this.getSize(e).equals([0,0])},isVisible:function(e){return!this.isInvisible(e)&&this.getViewportBounds(e).intersects(this.getBounds(e,!0))},getViewport:function(e){return e.defaultView||e.parentWindow},getViewportBounds:function(e){var t=e.ownerDocument,i=this.getViewport(t),n=t.getElementsByTagName("CSS1Compat"===t.compatMode?"html":"body")[0];return Rectangle.create(0,0,i.innerWidth||n.clientWidth,i.innerHeight||n.clientHeight)},getComputedStyle:function(e,t){if(e.currentStyle)return e.currentStyle[Base.camelize(t)];var i=this.getViewport(e.ownerDocument).getComputedStyle(e,null);return i?i.getPropertyValue(Base.hyphenate(t)):null}},DomEvent={add:function(e,t){for(var i in t){var n=t[i];e.addEventListener?e.addEventListener(i,n,!1):e.attachEvent&&e.attachEvent("on"+i,n.bound=function(){n.call(e,window.event)})}},remove:function(e,t){for(var i in t){var n=t[i];e.removeEventListener?e.removeEventListener(i,n,!1):e.detachEvent&&e.detachEvent("on"+i,n.bound)}},getPoint:function(e){var t=e.targetTouches?e.targetTouches.length?e.targetTouches[0]:e.changedTouches[0]:e;return Point.create(t.pageX||t.clientX+document.documentElement.scrollLeft,t.pageY||t.clientY+document.documentElement.scrollTop)},getTarget:function(e){return e.target||e.srcElement},getOffset:function(e,t){return DomEvent.getPoint(e).subtract(DomElement.getOffset(t||DomEvent.getTarget(e)))},preventDefault:function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},stop:function(e){DomEvent.stopPropagation(e),DomEvent.preventDefault(e)}};DomEvent.requestAnimationFrame=new function(){var e="equestAnimationFrame",t=window["r"+e]||window["webkitR"+e]||window["mozR"+e]||window["oR"+e]||window["msR"+e];t&&t(function(e){void 0==e&&(t=null)});var i,n=[],r=!0;return DomEvent.add(window,{focus:function(){r=!0},blur:function(){r=!1}}),function(e,s){return t?t(e,s):(n.push([e,s]),i||(i=window.setInterval(function(){for(var e=n.length-1;e>=0;e--){var t=n[e],i=t[0],s=t[1];(!s||("true"==PaperScript.getAttribute(s,"keepalive")||r)&&DomElement.isVisible(s))&&(n.splice(e,1),i(Date.now()))}},1e3/60)),void 0)}};var View=this.View=PaperScopeItem.extend({_list:"views",_reference:"view",initialize:function(e){this.base();var t;if("string"==typeof e&&(e=document.getElementById(e)),e instanceof HTMLCanvasElement){if(this._canvas=e,PaperScript.hasAttribute(e,"resize")){var i=DomElement.getOffset(e,!0),n=this;t=DomElement.getViewportBounds(e).getSize().subtract(i),e.width=t.width,e.height=t.height,DomEvent.add(window,{resize:function(){DomElement.isInvisible(e)||(i=DomElement.getOffset(e,!0)),n.setViewSize(DomElement.getViewportBounds(e).getSize().subtract(i))}})}else t=DomElement.isInvisible(e)?Size.create(parseInt(e.getAttribute("width")),parseInt(e.getAttribute("height"))):DomElement.getSize(e);if(PaperScript.hasAttribute(e,"stats")){this._stats=new Stats;var r=this._stats.domElement,s=r.style,i=DomElement.getOffset(e);s.position="absolute",s.left=i.x+"px",s.top=i.y+"px",document.body.appendChild(r)}}else t=Size.read(arguments,1),t.isZero()&&(t=new Size(1024,768)),this._canvas=CanvasProvider.getCanvas(t);this._id=this._canvas.getAttribute("id"),null==this._id&&this._canvas.setAttribute("id",this._id="canvas-"+View._id++),View._views[this._id]=this,this._viewSize=LinkedSize.create(this,"setViewSize",t.width,t.height),this._context=this._canvas.getContext("2d"),this._matrix=new Matrix,this._zoom=1,this._events=this._createEvents(),DomEvent.add(this._canvas,this._events),View._focused||(View._focused=this),this._scope._redrawNotified=!1},remove:function(){return this.base()?(View._focused==this&&(View._focused=null),delete View._views[this._id],DomEvent.remove(this._canvas,this._events),this._canvas=this._events=this._onFrame=null,!0):!1},_redraw:function(){this._redrawNeeded=!0,this._onFrameCallback?this._onFrameCallback(0,!0):this.draw()},_transform:function(e){this._matrix.preConcatenate(e),this._bounds=null,this._inverse=null,this._redraw()},getCanvas:function(){return this._canvas},getViewSize:function(){return this._viewSize},setViewSize:function(e){e=Size.read(arguments);var t=e.subtract(this._viewSize);t.isZero()||(this._canvas.width=e.width,this._canvas.height=e.height,this._viewSize.set(e.width,e.height,!0),this._bounds=null,this._redrawNeeded=!0,this.onResize&&this.onResize({size:e,delta:t}),this._redraw())},getBounds:function(){return this._bounds||(this._bounds=this._getInverse()._transformBounds(new Rectangle(new Point,this._viewSize))),this._bounds},getSize:function(){return this.getBounds().getSize()},getCenter:function(){return this.getBounds().getCenter()},setCenter:function(){this.scrollBy(Point.read(arguments).subtract(this.getCenter()))},getZoom:function(){return this._zoom},setZoom:function(e){this._transform((new Matrix).scale(e/this._zoom,this.getCenter())),this._zoom=e},isVisible:function(){return DomElement.isVisible(this._canvas)},scrollBy:function(){this._transform((new Matrix).translate(Point.read(arguments).negate()))},draw:function(e){if(e&&!this._redrawNeeded)return!1;this._stats&&this._stats.update();var t=this._context,i=this._viewSize;return t.clearRect(0,0,i._width+1,i._height+1),t.save(),this._matrix.applyToContext(t),this._scope.project.draw(t),t.restore(),this._redrawNeeded&&(this._redrawNeeded=!1,this._scope._redrawNotified=!1),!0},projectToView:function(){return this._matrix._transformPoint(Point.read(arguments))},viewToProject:function(){return this._getInverse()._transformPoint(Point.read(arguments))},_getInverse:function(){return this._inverse||(this._inverse=this._matrix.createInverse()),this._inverse},getOnFrame:function(){return this._onFrame},setOnFrame:function(e){if(this._onFrame=e,!e)return delete this._onFrameCallback,void 0;var t,i=this,n=!1,r=0,s=0;this._onFrameCallback=function(e,o){if(n=!1,i._onFrame){paper=i._scope,n=!0,o||DomEvent.requestAnimationFrame(i._onFrameCallback,i._canvas);var a=Date.now()/1e3,l=t?a-t:0;i._onFrame(Base.merge({delta:l,time:r+=l,count:s++})),t=a,i.draw(!0)}},n||this._onFrameCallback()},onResize:null},{statics:{_views:{},_id:0}},new function(){function e(e,t){return e.viewToProject(DomEvent.getOffset(t,e._canvas))}function t(){View._focused&&View._focused.isVisible()||PaperScope.each(function(e){for(var t=0,i=e.views.length;i>t;t++){var n=e.views[t];if(n.isVisible())throw View._focused=l=n,Base.stop}})}function i(i){var n;if(h||(n=View._views[DomEvent.getTarget(i).getAttribute("id")],n?View._focused=l=n:l&&l==View._focused&&(View._focused=null,t())),(n=n||View._focused)&&(s=n._scope.tool)){var r=i&&e(n,i),o=!(s.onMouseDrag||!s.onMouseMove);h&&!o?(a=r||a,a&&s.onHandleEvent("mousedrag",a,i)&&(n.draw(!0),DomEvent.stop(i))):h&&!o||!s.onHandleEvent("mousemove",r,i)||(n.draw(!0),DomEvent.stop(i))}}function n(t){var i=View._focused;i&&h&&(h=!1,a=null,s&&(null!=o&&(o=clearInterval(o)),s.onHandleEvent("mouseup",e(i,t),t)&&(i.draw(!0),DomEvent.stop(t))))}function r(e){h&&DomEvent.stop(e)}var s,o,a,l,h=!1;return DomEvent.add(document,{mousemove:i,mouseup:n,touchmove:i,touchend:n,selectstart:r,scroll:t}),DomEvent.add(window,{load:t}),{_createEvents:function(){function t(t){View._focused=n,(s=n._scope.tool)&&(a=e(n,t),s.onHandleEvent("mousedown",a,t)&&n.draw(!0),null!=s.eventInterval&&(o=setInterval(i,s.eventInterval)),h=!0)}var n=this;return{mousedown:t,touchstart:t,selectstart:r}},statics:{updateFocus:t}}}),Event=this.Event=Base.extend({initialize:function(e){this.event=e},preventDefault:function(){DomEvent.preventDefault(this.event)},stopPropagation:function(){DomEvent.stopPropagation(this.event)},stop:function(){DomEvent.stop(this.event)},getModifiers:function(){return Key.modifiers}}),KeyEvent=this.KeyEvent=Event.extend(new function(){return{initialize:function(e,t,i,n){this.base(n),this.type=e?"keydown":"keyup",this.key=t,this.character=i},toString:function(){return"{ type: "+this.type+", key: "+this.key+", character: "+this.character+", modifiers: "+this.getModifiers()+" }"}}}),Key=this.Key=new function(){function e(e,t,n,r){var o=String.fromCharCode(n),a=i[t]||o.toLowerCase(),l=e?"onKeyDown":"onKeyUp",h=View._focused,c=h&&h.isVisible()&&h._scope,u=c&&c.tool;if(s[a]=e,u&&u[l]){var d=new KeyEvent(e,a,o,r);u[l](d)===!1&&d.preventDefault(),h&&h.draw(!0)}}var t,i={8:"backspace",13:"enter",16:"shift",17:"control",18:"option",19:"pause",20:"caps-lock",27:"escape",32:"space",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",46:"delete",91:"command",93:"command",224:"command"},n=Base.merge({shift:!1,control:!1,option:!1,command:!1,capsLock:!1}),r={},s={};return DomEvent.add(document,{keydown:function(s){var o,a=s.which||s.keyCode,l=i[a];l?((o=Base.camelize(l))in n&&(n[o]=!0),r[a]=0,e(!0,a,null,s)):t=a},keypress:function(i){if(null!=t){var n=i.which||i.keyCode;r[t]=n,e(!0,t,n,i),t=null}},keyup:function(t){var s,o=t.which||t.keyCode,a=i[o];a&&(s=Base.camelize(a))in n&&(n[s]=!1),null!=r[o]&&(e(!1,o,r[o],t),delete r[o])}}),{modifiers:n,isDown:function(e){return!!s[e]}}},ToolEvent=this.ToolEvent=Event.extend({initialize:function(e,t,i){this.tool=e,this.type=t,this.event=i},_choosePoint:function(e,t){return e?e:t?t.clone():null},getPoint:function(){return this._choosePoint(this._point,this.tool._point)},setPoint:function(e){this._point=e},getLastPoint:function(){return this._choosePoint(this._lastPoint,this.tool._lastPoint)},setLastPoint:function(e){this._lastPoint=e},getDownPoint:function(){return this._choosePoint(this._downPoint,this.tool._downPoint)},setDownPoint:function(e){this._downPoint=e},getMiddlePoint:function(){return!this._middlePoint&&this.tool._lastPoint?this.tool._point.add(this.tool._lastPoint).divide(2):this.middlePoint},setMiddlePoint:function(e){this._middlePoint=e},getDelta:function(){return!this._delta&&this.tool._lastPoint?this.tool._point.subtract(this.tool._lastPoint):this._delta},setDelta:function(e){this._delta=e},getCount:function(){return/^mouse(down|up)$/.test(this.type)?this.tool._downCount:this.tool._count},setCount:function(e){this.tool[/^mouse(down|up)$/.test(this.type)?"downCount":"count"]=e},getItem:function(){if(!this._item){var e=this.tool._scope.project.hitTest(this.getPoint());if(e){for(var t=e.item,i=t._parent;i instanceof Group&&!(i instanceof Layer)||i instanceof CompoundPath;)t=i,i=i._parent;this._item=t}}return this._item},setItem:function(e){this._item=e},toString:function(){return"{ type: "+this.type+", point: "+this.getPoint()+", count: "+this.getCount()+", modifiers: "+this.getModifiers()+" }"}}),Tool=this.Tool=PaperScopeItem.extend({_list:"tools",_reference:"tool",initialize:function(){this.base(),this._firstMove=!0,this._count=0,this._downCount=0},eventInterval:null,getMinDistance:function(){return this._minDistance},setMinDistance:function(e){this._minDistance=e,null!=this._minDistance&&null!=this._maxDistance&&this._minDistance>this._maxDistance&&(this._maxDistance=this._minDistance)},getMaxDistance:function(){return this._maxDistance},setMaxDistance:function(e){this._maxDistance=e,null!=this._minDistance&&null!=this._maxDistance&&this._maxDistanceh)return!1;var c=null!=n?n:0;if(0!=c)if(h>c)t=this._point.add(l.normalize(c));else if(o)return!1}if(s&&t.equals(this._point))return!1}switch(this._lastPoint=r&&"mousemove"==e?t:this._point,this._point=t,e){case"mousedown":this._lastPoint=this._downPoint,this._downPoint=this._point,this._downCount++;break;case"mouseup":this._lastPoint=this._downPoint}return this._count=r?0:this._count+1,!0},onHandleEvent:function(e,t,i){paper=this._scope;var n=!1;switch(e){case"mousedown":this.updateEvent(e,t,null,null,!0,!1,!1),this.onMouseDown&&(this.onMouseDown(new ToolEvent(this,e,i)),n=!0);break;case"mousedrag":for(var r=!1,s=!1;this.updateEvent(e,t,this.minDistance,this.maxDistance,!1,r,s);)this.onMouseDrag&&(this.onMouseDrag(new ToolEvent(this,e,i)),n=!0),r=!0,s=!0;break;case"mouseup":this._point.x==t.x&&this._point.y==t.y||!this.updateEvent("mousedrag",t,this.minDistance,this.maxDistance,!1,!1,!1)||this.onMouseDrag&&(this.onMouseDrag(new ToolEvent(this,e,i)),n=!0),this.updateEvent(e,t,null,this.maxDistance,!1,!1,!1),this.onMouseUp&&(this.onMouseUp(new ToolEvent(this,e,i)),n=!0),this.updateEvent(e,t,null,null,!0,!1,!1),this._firstMove=!0;break;case"mousemove":for(;this.updateEvent(e,t,this.minDistance,this.maxDistance,this._firstMove,!0,!1);)this.onMouseMove&&(this.onMouseMove(new ToolEvent(this,e,i)),n=!0),this._firstMove=!1}return n}}),CanvasProvider={canvases:[],getCanvas:function(e){if(this.canvases.length){var t=this.canvases.pop();return t.width!=e.width||t.height!=e.height?(t.width=e.width,t.height=e.height):t.getContext("2d").clearRect(0,0,e.width+1,e.height+1),t}var t=document.createElement("canvas");return t.width=e.width,t.height=e.height,t},returnCanvas:function(e){this.canvases.push(e)}},Numerical=new function(){var e=[[.5773502691896257],[0,.7745966692414834],[.33998104358485626,.8611363115940526],[0,.5384693101056831,.906179845938664],[.2386191860831969,.6612093864662645,.932469514203152],[0,.4058451513773972,.7415311855993945,.9491079123427585],[.1834346424956498,.525532409916329,.7966664774136267,.9602898564975363],[0,.3242534234038089,.6133714327005904,.8360311073266358,.9681602395076261],[.14887433898163122,.4333953941292472,.6794095682990244,.8650633666889845,.9739065285171717],[0,.26954315595234496,.5190961292068118,.7301520055740494,.8870625997680953,.978228658146057],[.1252334085114689,.3678314989981802,.5873179542866175,.7699026741943047,.9041172563704749,.9815606342467192],[0,.2304583159551348,.44849275103644687,.6423493394403402,.8015780907333099,.9175983992229779,.9841830547185881],[.10805494870734367,.31911236892788974,.5152486363581541,.6872929048116855,.827201315069765,.9284348836635735,.9862838086968123],[0,.20119409399743451,.3941513470775634,.5709721726085388,.7244177313601701,.8482065834104272,.937273392400706,.9879925180204854],[.09501250983763744,.2816035507792589,.45801677765722737,.6178762444026438,.755404408355003,.8656312023878318,.9445750230732326,.9894009349916499]],t=[[1],[.8888888888888888,.5555555555555556],[.6521451548625461,.34785484513745385],[.5688888888888889,.47862867049936647,.23692688505618908],[.46791393457269104,.3607615730481386,.17132449237917036],[.4179591836734694,.3818300505051189,.27970539148927664,.1294849661688697],[.362683783378362,.31370664587788727,.22238103445337448,.10122853629037626],[.3302393550012598,.31234707704000286,.26061069640293544,.1806481606948574,.08127438836157441],[.29552422471475287,.26926671930999635,.21908636251598204,.1494513491505806,.06667134430868814],[.2729250867779006,.26280454451024665,.23319376459199048,.18629021092773426,.1255803694649046,.05566856711617366],[.24914704581340277,.2334925365383548,.20316742672306592,.16007832854334622,.10693932599531843,.04717533638651183],[.2325515532308739,.22628318026289723,.2078160475368885,.17814598076194574,.13887351021978725,.09212149983772845,.04048400476531588],[.2152638534631578,.2051984637212956,.18553839747793782,.15720316715819355,.12151857068790319,.08015808715976021,.03511946033175186],[.2025782419255613,.19843148532711158,.1861610000155622,.16626920581699392,.13957067792615432,.10715922046717194,.07036604748810812,.03075324199611727],[.1894506104550685,.18260341504492358,.16915651939500254,.14959598881657674,.12462897125553388,.09515851168249279,.062253523938647894,.027152459411754096]],i=Math.abs,n=Math.sqrt,r=Math.cos,s=Math.PI;return{TOLERANCE:1e-5,EPSILON:1e-11,integrate:function(i,n,r,s){for(var o=e[s-2],a=t[s-2],l=.5*(r-n),h=l+n,c=0,u=s+1>>1,d=1&s?a[c++]*i(h):0;u>c;){var p=l*o[c];d+=a[c++]*(i(h+p)+i(h-p))}return l*d},findRoot:function(e,t,n,r,s,o,a){for(var l=0;o>l;l++){var h=e(n),c=h/t(n);if(a>i(c))return n;var u=n-c;h>0?(s=n,n=r>=u?.5*(r+s):u):(r=n,n=u>=s?.5*(r+s):u)}},solveQuadratic:function(e,t,r,s,o){if(o>i(e))return i(t)>=o?(s[0]=-r/t,1):o>i(r)?-1:0;var a=t*t-4*e*r;if(0>a)return 0;a=n(a),0>t&&(a=-a),a=(t+a)*-.5;var l=0;return i(a)>=o&&(s[l++]=r/a),i(e)>=o&&(s[l++]=a/e),l},solveCubic:function(e,t,o,a,l,h){if(h>i(e))return Numerical.solveQuadratic(t,o,a,l,h);t/=e,o/=e,a/=e;var c=(t*t-3*o)/9,u=(2*t*t*t-9*t*o+27*a)/54,d=c*c*c,p=u*u;if(t/=3,d>p){var f=Math.acos(u/n(d)),m=-2*n(c);return l[0]=m*r(f/3)-t,l[1]=m*r((f+2*s)/3)-t,l[2]=m*r((f-2*s)/3)-t,3}var g=-Math.pow(i(u)+n(p-d),1/3);0>u&&(g=-g);var y=h>i(g)?0:c/g;return l[0]=g+y-t,1}}},BlendMode={process:function(e,t,i,n,r){function s(e,t,i){return.2989*e+.587*t+.114*i}function o(e,t,i,n){var r=n-s(e,t,i);y=e+r,v=t+r,b=i+r;var n=s(y,v,b),o=S(y,v,b),a=O(y,v,b);if(0>o){var l=n-o;y=n+(y-n)*n/l,v=n+(v-n)*n/l,b=n+(b-n)*n/l}if(a>255){var h=255-n,c=a-n;y=n+(y-n)*h/c,v=n+(v-n)*h/c,b=n+(b-n)*h/c}}function a(e,t,i){return O(e,t,i)-S(e,t,i)}function l(e,t,i,n){var r,s=[e,t,i],o=O(e,t,i),a=S(e,t,i);a=a==e?0:a==t?1:2,o=o==e?0:o==t?1:2,r=0==S(a,o)?1==O(a,o)?2:1:0,s[o]>s[a]?(s[r]=(s[r]-s[a])*n/(s[o]-s[a]),s[o]=n):s[r]=s[o]=0,s[a]=0,y=s[0],v=s[1],b=s[2]}var h,c,u,d,p,f,m,g,y,v,b,L=t.canvas,x=i.getImageData(r.x,r.y,L.width,L.height),C=x.data,w=t.getImageData(0,0,L.width,L.height).data,S=Math.min,O=Math.max,_=Math.abs,E={multiply:function(){y=p*h/255,v=f*c/255,b=m*u/255},screen:function(){y=255-(255-p)*(255-h)/255,v=255-(255-f)*(255-c)/255,b=255-(255-m)*(255-u)/255},overlay:function(){y=128>p?2*p*h/255:255-2*(255-p)*(255-h)/255,v=128>f?2*f*c/255:255-2*(255-f)*(255-c)/255,b=128>m?2*m*u/255:255-2*(255-m)*(255-u)/255},"soft-light":function(){var e=h*p/255;y=e+p*(255-(255-p)*(255-h)/255-e)/255,e=c*f/255,v=e+f*(255-(255-f)*(255-c)/255-e)/255,e=u*m/255,b=e+m*(255-(255-m)*(255-u)/255-e)/255},"hard-light":function(){y=128>h?2*h*p/255:255-2*(255-h)*(255-p)/255,v=128>c?2*c*f/255:255-2*(255-c)*(255-f)/255,b=128>u?2*u*m/255:255-2*(255-u)*(255-m)/255},"color-dodge":function(){y=255==h?h:S(255,255*p/(255-h)),v=255==c?c:S(255,255*f/(255-c)),b=255==u?u:S(255,255*m/(255-u))},"color-burn":function(){y=0==h?0:O(255-255*(255-p)/h,0),v=0==c?0:O(255-255*(255-f)/c,0),b=0==u?0:O(255-255*(255-m)/u,0)},darken:function(){y=h>p?p:h,v=c>f?f:c,b=u>m?m:u},lighten:function(){y=p>h?p:h,v=f>c?f:c,b=m>u?m:u},difference:function(){y=p-h,0>y&&(y=-y),v=f-c,0>v&&(v=-v),b=m-u,0>b&&(b=-b)},exclusion:function(){y=p+h*(255-p-p)/255,v=f+c*(255-f-f)/255,b=m+u*(255-m-m)/255},hue:function(){l(h,c,u,a(p,f,m)),o(y,v,b,s(p,f,m))},saturation:function(){l(p,f,m,a(h,c,u)),o(y,v,b,s(p,f,m))},luminosity:function(){o(p,f,m,s(h,c,u))},color:function(){o(h,c,u,s(p,f,m))},add:function(){y=S(p+h,255),v=S(f+c,255),b=S(m+u,255)},subtract:function(){y=O(p-h,0),v=O(f-c,0),b=O(m-u,0)},average:function(){y=(p+h)/2,v=(f+c)/2,b=(m+u)/2},negation:function(){y=255-_(255-h-p),v=255-_(255-c-f),b=255-_(255-u-m)}},T=E[e];if(T){for(var k=0,P=C.length;P>k;k+=4){h=w[k],p=C[k],c=w[k+1],f=C[k+1],u=w[k+2],m=C[k+2],d=w[k+3],g=C[k+3],T();var A=d*n/255,M=1-A;C[k]=A*y+M*p,C[k+1]=A*v+M*f,C[k+2]=A*b+M*m,C[k+3]=d*n+M*g}i.putImageData(x,r.x,r.y)}}},PaperScript=this.PaperScript=new function(){function $eval(e,t,i){var n=operators[t];if(e&&e[n]){var r=e[n](i);return"!="==t?!r:r}switch(t){case"+":return e+i;case"-":return e-i;case"*":return e*i;case"/":return e/i;case"%":return e%i;case"==":return e==i;case"!=":return e!=i;default:throw Error("Implement Operator: "+t)}}function $sign(e,t){var i=signOperators[e];if(t&&t[i])return t[i]();switch(e){case"+":return+t;case"-":return-t;default:throw Error("Implement Sign Operator: "+e)}}function isDynamic(e){var t=e[0];return"num"!=t&&"string"!=t}function handleOperator(e,t,i){return operators[e]&&isDynamic(t)?["call",["name","$eval"],[t,["string",e],i]]:void 0}function compile(e){var t=parse_js.parse(e),i=parse_js.ast_walker(),n=i.walk;return t=i.with_walkers({binary:function(e,t,i){return handleOperator(e,t=n(t),i=n(i))||[this[0],e,t,i]},assign:function(e,t,i){var r=handleOperator(e,t=n(t),i=n(i));return r?[this[0],!0,t,r]:[this[0],e,t,i]},"unary-prefix":function(e,t){return signOperators[e]&&isDynamic(t)?["call",["name","$sign"],[["string",e],n(t)]]:void 0}},function(){return n(t)}),parse_js.gen_code(t,{beautify:!0})}function evaluate(code,scope){paper=scope;var view=scope.view,tool=/on(?:Key|Mouse)(?:Up|Down|Move|Drag)/.test(code)&&new Tool,res;with(scope)(function(){var onEditOptions,onSelect,onDeselect,onReselect,onMouseDown,onMouseUp,onMouseDrag,onMouseMove,onKeyDown,onKeyUp,onFrame,onResize,handlers=["onEditOptions","onSelect","onDeselect","onReselect","onMouseDown","onMouseUp","onMouseDrag","onMouseMove","onKeyDown","onKeyUp"];res=eval(compile(code)),tool&&Base.each(handlers,function(key){tool[key]=eval(key)}),view&&(view.onResize=onResize,view.setOnFrame(onFrame),view.draw())}).call(scope);return res}function request(e,t){var i=new(window.ActiveXObject||XMLHttpRequest)("Microsoft.XMLHTTP");return i.open("GET",e,!0),i.overrideMimeType&&i.overrideMimeType("text/plain"),i.onreadystatechange=function(){return 4===i.readyState?evaluate(i.responseText,t):void 0},i.send(null)}function load(){for(var e=document.getElementsByTagName("script"),t=0,i=e.length;i>t;t++){var n=e[t];if(/^text\/(?:x-|)paperscript$/.test(n.type)&&!n.getAttribute("data-paper-loaded")){var r=new PaperScope(n);r.setup(PaperScript.getAttribute(n,"canvas")),n.src?request(n.src,r):evaluate(n.innerHTML,r),n.setAttribute("data-paper-loaded",!0)}}}function handleAttribute(e){return e+="Attribute",function(t,i){return t[e](i)||t[e]("data-paper-"+i)}}var parse_js=new function(){function e(e,t,i){for(var n=[],r=0;e.length>r;++r)n.push(t.call(i,e[r],r));return n}function t(e){return/^[a-z_$][a-z0-9_$]*$/i.test(e)&&"this"!=e&&!l(P,e)&&!l(T,e)&&!l(E,e)}function i(e,t){var i={};e===!0&&(e={});for(var n in t)l(t,n)&&(i[n]=e&&l(e,n)?e[n]:t[n]);return i}function n(e,t){return 1>t?"":Array(t+1).join(e)}function r(r,c){function d(e){var t=e[0],i=N[t];if(!i)throw Error("Can't find generator for \""+t+'"');R.push(e);var n=i.apply(t,e.slice(1));return R.pop(),n}function p(e){var t=e[0],i=e[1];return null!=i&&(t=O([T(t),"=",C(i,"seq")])),t}function f(e){return e?0==e.length?"{}":"{"+A+_(function(){return g(e).join(A)})+A+E("}"):";"}function m(t){var i=t.length;return 0==i?"{}":"{"+A+e(t,function(e,t){var n=e[1].length>0,r=_(function(){return E(e[0]?O(["case",d(e[0])+":"]):"default:")},.5)+(n?A+_(function(){return g(e[1]).join(A)}):"");return!k&&n&&i-1>t&&(r+=";"),r}).join(A)+A+E("}")}function g(t,i){for(var n=[],r=t.length-1,s=0;r>=s;++s){var a=t[s],l=d(a);";"!=l&&(!k&&s==r&&(l="while"==a[0]&&o(a[2])||h(a[0],["for","for-in"])&&o(a[4])||"if"==a[0]&&o(a[2])&&!a[3]||"if"==a[0]&&a[3]&&o(a[3])?l.replace(/;*\s*$/,";"):l.replace(/;+\s*$/,"")),n.push(l))}return i?n:e(n,E)}function y(t,i,n,r){var s=r||"function";return t&&(s+=" "+T(t)),s+="("+w(e(i,T))+")",O([s,f(n)])}function v(e){if("do"==e[0])return d(["block",[e]]);for(var t=e;;){var i=t[0];if("if"==i){if(!t[3])return d(["block",[e]]);t=t[3]}else if("while"==i||"do"==i)t=t[2];else{if("for"!=i&&"for-in"!=i)break;t=t[4]}}return d(e)}function b(e){var t,i=e.toString(10),n=[i.replace(/^0\./,".")];return Math.floor(e)===e?(n.push("0x"+e.toString(16).toLowerCase(),"0"+e.toString(8)),(t=/^(.*?)(0+)$/.exec(e))&&n.push(t[1]+"e"+t[2].length)):(t=/^0?\.(0+)(.*)$/.exec(e))&&n.push(t[2]+"e-"+(t[1].length+t[2].length),i.substr(i.indexOf("."))),x(n)}function L(e){if("function"==e[0]||"object"==e[0])for(var t=u(R),i=t.pop(),n=t.pop();n;){if("stat"==n[0])return!0;if(("seq"!=n[0]&&"call"!=n[0]&&"dot"!=n[0]&&"sub"!=n[0]&&"conditional"!=n[0]||n[1]!==i)&&("binary"!=n[0]&&"assign"!=n[0]&&"unary-postfix"!=n[0]||n[2]!==i))return!1;i=n,n=t.pop()}return!l(V,e[0])}function x(e){if(1==e.length)return e[0];if(2==e.length){var t=e[1];return e=e[0],e.length<=t.length?e:t}return x([e[0],x(e.slice(1))])}function C(e){for(var t=d(e),i=1;arguments.length>i;++i){var n=arguments[i];if(n instanceof Function&&n(e)||e[0]==n)return"("+t+")"}return t}function w(e){return e.join(","+M)}function O(e){if(k)return e.join(" ");for(var t=[],i=0;e.length>i;++i){var n=e[i+1];t.push(e[i]),n&&(/[a-z0-9_\x24]$/i.test(""+e[i])&&/^[a-z0-9_\x24]/i.test(""+n)||/[\+\-]$/.test(""+e[i])&&/^[\+\-]/.test(""+n))&&t.push(" ")}return t.join("")}function _(e,t){null==t&&(t=1),P+=t;try{return e.apply(null,u(arguments,1))}finally{P-=t}}function E(e){return null==e&&(e=""),k&&(e=n(" ",c.indent_start+P*c.indent_level)+e),e}function T(e){return""+e}c=i(c,{indent_start:0,indent_level:4,quote_keys:!1,space_colon:!1,beautify:!1});var k=!!c.beautify,P=0,A=k?"\n":"",M=k?" ":"",N={string:s,num:b,name:T,toplevel:function(e){return g(e).join(A)},splice:function(t){var i=R[R.length-2][0];return l(Y,i)?f.apply(this,arguments):e(g(t,!0),function(e,t){return t>0?E(e):e}).join(A)},block:f,"var":function(t){return"var "+w(e(t,p))+";"},"const":function(t){return"const "+w(e(t,p))+";"},"try":function(e,t,i){var n=["try",f(e)];return t&&n.push("catch","("+t[0]+")",f(t[1])),i&&n.push("finally",f(i)),O(n)},"throw":function(e){return O(["throw",d(e)])+";"},"new":function(t,i){return i=i.length>0?"("+w(e(i,d))+")":"",O(["new",C(t,"seq","binary","conditional","assign",function(e){var t=a(),i={};try{t.with_walkers({call:function(){throw i},"function":function(){return this}},function(){t.walk(e)})}catch(n){if(n===i)return!0;throw n}})+i])},"switch":function(e,t){return O(["switch","("+d(e)+")",m(t)])},"break":function(e){var t="break";return null!=e&&(t+=" "+T(e)),t+";"},"continue":function(e){var t="continue";return null!=e&&(t+=" "+T(e)),t+";"},conditional:function(e,t,i){return O([C(e,"assign","seq","conditional"),"?",C(t,"seq"),":",C(i,"seq")])},assign:function(e,t,i){return e&&e!==!0?e+="=":e="=",O([d(t),e,C(i,"seq")])},dot:function(e){var t=d(e),i=1;for("num"==e[0]?/\./.test(e[1])||(t+="."):L(e)&&(t="("+t+")");arguments.length>i;)t+="."+T(arguments[i++]);return t},call:function(t,i){var n=d(t);return L(t)&&(n="("+n+")"),n+"("+w(e(i,function(e){return C(e,"seq")}))+")"},"function":y,defun:y,"if":function(e,t,i){var n=["if","("+d(e)+")",i?v(t):d(t)];return i&&n.push("else",d(i)),O(n)},"for":function(e,t,i,n){var r=["for"];e=(null!=e?d(e):"").replace(/;*\s*$/,";"+M),t=(null!=t?d(t):"").replace(/;*\s*$/,";"+M),i=(null!=i?d(i):"").replace(/;*\s*$/,"");var s=e+t+i;return"; ; "==s&&(s=";;"),r.push("("+s+")",d(n)),O(r)},"for-in":function(e,t,i,n){return O(["for","("+(e?d(e).replace(/;+$/,""):d(t)),"in",d(i)+")",d(n)])},"while":function(e,t){return O(["while","("+d(e)+")",d(t)])},"do":function(e,t){return O(["do",d(t),"while","("+d(e)+")"])+";"},"return":function(e){var t=["return"];return null!=e&&t.push(d(e)),O(t)+";"},binary:function(e,t,i){var n=d(t),r=d(i);return(h(t[0],["assign","conditional","seq"])||"binary"==t[0]&&U[e]>U[t[1]])&&(n="("+n+")"),(h(i[0],["assign","conditional","seq"])||"binary"==i[0]&&U[e]>=U[i[1]]&&(i[1]!=e||!h(e,["&&","||","*"])))&&(r="("+r+")"),O([n,e,r])},"unary-prefix":function(e,t){var i=d(t);return"num"==t[0]||"unary-prefix"==t[0]&&!l(D,e+t[1])||!L(t)||(i="("+i+")"),e+(S(e.charAt(0))?" ":"")+i},"unary-postfix":function(e,t){var i=d(t);return"num"==t[0]||"unary-postfix"==t[0]&&!l(D,e+t[1])||!L(t)||(i="("+i+")"),i+e},sub:function(e,t){var i=d(e);return L(e)&&(i="("+i+")"),i+"["+d(t)+"]"},object:function(i){return 0==i.length?"{}":"{"+A+_(function(){return e(i,function(e){if(3==e.length)return E(y(e[0],e[1][2],e[1][3],e[2]));var i=e[0],n=d(e[1]);return c.quote_keys?i=s(i):("number"==typeof i||!k&&+i+""==i)&&parseFloat(i)>=0?i=b(+i):t(i)||(i=s(i)),E(O(k&&c.space_colon?[i,":",n]:[i+":",n]))}).join(","+A)})+A+E("}")},regexp:function(e,t){return"/"+e+"/"+t},array:function(t){return 0==t.length?"[]":O(["[",w(e(t,function(e){return k||"atom"!=e[0]||"undefined"!=e[1]?C(e,"seq"):""})),"]"])},stat:function(e){return d(e).replace(/;*\s*$/,";")},seq:function(){return w(e(u(arguments),d))},label:function(e,t){return O([T(e),":",d(t)])},"with":function(e,t){return O(["with","("+d(e)+")",d(t)])},atom:function(e){return T(e)}},R=[];return d(r)}function s(e){var t=0,i=0;return e=e.replace(/[\\\b\f\n\r\t\x22\x27]/g,function(e){switch(e){case"\\":return"\\\\";case"\b":return"\\b";case"\f":return"\\f";case"\n":return"\\n";case"\r":return"\\r";case" ":return"\\t";case'"':return++t,'"';case"'":return++i,"'"}return e}),t>i?"'"+e.replace(/\x27/g,"\\'")+"'":'"'+e.replace(/\x22/g,'\\"')+'"'}function o(e){return!e||"block"==e[0]&&(!e[1]||0==e[1].length)}function a(){function t(e,t){var i,n={};for(i in e)l(e,i)&&(n[i]=o[i],o[i]=e[i]);var r=t();for(i in n)l(n,i)&&(n[i]?o[i]=n[i]:delete o[i]);return r}function i(e){if(null==e)return null;try{a.push(e);var t=e[0],i=o[t];if(i){var n=i.apply(e,e.slice(1));if(null!=n)return n}return i=s[t],i.apply(e,e.slice(1))}finally{a.pop()}}function n(t){var n=[this[0]];return null!=t&&n.push(e(t,i)),n}function r(t){return[this[0],e(t,function(e){var t=[e[0]];return e.length>1&&(t[1]=i(e[1])),t})]}var s={string:function(e){return[this[0],e]},num:function(e){return[this[0],e]},name:function(e){return[this[0],e]},toplevel:function(t){return[this[0],e(t,i)]},block:n,splice:n,"var":r,"const":r,"try":function(t,n,r){return[this[0],e(t,i),null!=n?[n[0],e(n[1],i)]:null,null!=r?e(r,i):null]},"throw":function(e){return[this[0],i(e)]},"new":function(t,n){return[this[0],i(t),e(n,i)]},"switch":function(t,n){return[this[0],i(t),e(n,function(t){return[t[0]?i(t[0]):null,e(t[1],i)]})]},"break":function(e){return[this[0],e]},"continue":function(e){return[this[0],e]},conditional:function(e,t,n){return[this[0],i(e),i(t),i(n)]},assign:function(e,t,n){return[this[0],e,i(t),i(n)]},dot:function(e){return[this[0],i(e)].concat(u(arguments,1))},call:function(t,n){return[this[0],i(t),e(n,i)]},"function":function(t,n,r){return[this[0],t,n.slice(),e(r,i)]},defun:function(t,n,r){return[this[0],t,n.slice(),e(r,i)]},"if":function(e,t,n){return[this[0],i(e),i(t),i(n)]},"for":function(e,t,n,r){return[this[0],i(e),i(t),i(n),i(r)]},"for-in":function(e,t,n,r){return[this[0],i(e),i(t),i(n),i(r)]},"while":function(e,t){return[this[0],i(e),i(t)]},"do":function(e,t){return[this[0],i(e),i(t)]},"return":function(e){return[this[0],i(e)]},binary:function(e,t,n){return[this[0],e,i(t),i(n)]},"unary-prefix":function(e,t){return[this[0],e,i(t)]},"unary-postfix":function(e,t){return[this[0],e,i(t)]},sub:function(e,t){return[this[0],i(e),i(t)]},object:function(t){return[this[0],e(t,function(e){return 2==e.length?[e[0],i(e[1])]:[e[0],i(e[1]),e[2]] +})]},regexp:function(e,t){return[this[0],e,t]},array:function(t){return[this[0],e(t,i)]},stat:function(e){return[this[0],i(e)]},seq:function(){return[this[0]].concat(e(u(arguments),i))},label:function(e,t){return[this[0],e,i(t)]},"with":function(e,t){return[this[0],i(e),i(t)]},atom:function(e){return[this[0],e]}},o={},a=[];return{walk:i,with_walkers:t,parent:function(){return a[a.length-2]},stack:function(){return a}}}function l(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function h(e,t){for(var i=t.length;--i>=0;)if(t[i]===e)return!0;return!1}function c(e){return e.split("")}function u(e,t){return Array.prototype.slice.call(e,t||0)}function d(e){for(var t={},i=0;e.length>i;++i)t[e[i]]=!0;return t}function p(e){e instanceof Function&&(e=e());for(var t=1,i=arguments.length;--i>0;++t)arguments[t]();return e}function f(e){var t=u(arguments,1);return function(){return e.apply(this,t.concat(u(arguments)))}}function m(e,t,i){function n(e){try{return++st.in_loop,e()}finally{--st.in_loop}}function r(e){var t=o(e),i=st.token.value;if(rt("operator")&&l(J,i)){if(s(t))return it(),V("assign",J[i],t,r(e));et("Invalid assignment")}return t}function s(e){if(!t)return!0;switch(e[0]){case"dot":case"sub":case"new":case"call":return!0;case"name":return"this"!=e[1]}}function o(e){var t=a(e);if(rt("operator","?")){it();var i=ct(!1);return q(":"),V("conditional",t,i,ct(!1,e))}return t}function a(e){return c(ht(!0),0,e)}function c(e,t,i){var n=rt("operator")?st.token.value:null;n&&"in"==n&&i&&(n=null);var r=null!=n?U[n]:null;if(null!=r&&r>t){it();var s=c(ht(!0),r,i);return c(V("binary",n,e,s),t,i)}return e}function d(e,t,i){return("++"==t||"--"==t)&&!s(i)&&et("Invalid use of "+t+" operator"),V(e,t,i)}function m(e,t){return rt("punc",".")?(it(),m(V("dot",e,L()),t)):rt("punc","[")?(it(),m(V("sub",e,p(ct,f(q,"]"))),t)):t&&rt("punc","(")?(it(),m(V("call",e,S(")")),!0)):t&&rt("operator")&&l(j,st.token.value)?p(f(d,"unary-postfix",st.token.value,e),it):e}function L(){switch(st.token.type){case"name":case"operator":case"keyword":case"atom":return p(st.token.value,it);default:Z()}}function x(){switch(st.token.type){case"num":case"string":return p(st.token.value,it)}return L()}function C(){for(var e=!0,i=[];!rt("punc","}")&&(e?e=!1:q(","),t||!rt("punc","}"));){var n=st.token.type,r=x();"name"!=n||"get"!=r&&"set"!=r||rt("punc",":")?(q(":"),i.push([r,ct(!1)])):i.push([L(),at(!1),r])}return it(),V("object",i)}function w(){return V("array",S("]",!t,!0))}function S(e,t,i){for(var n=!0,r=[];!rt("punc",e)&&(n?n=!1:q(","),!t||!rt("punc",e));)rt("punc",",")&&i?r.push(["atom","undefined"]):r.push(ct(!1));return it(),r}function O(){var e,t=ht(!1);return rt("punc","(")?(it(),e=S(")")):e=[],m(V("new",t,e),!0)}function _(){return V("const",T())}function E(e){return V("var",T(e))}function T(e){for(var t=[];;){rt("name")||Z();var i=st.token.value;if(it(),rt("operator","=")?(it(),t.push([i,ct(!1,e)])):t.push([i]),!rt("punc",","))break;it()}return t}function k(){var e,t,i=P();if(rt("keyword","catch")){it(),q("("),rt("name")||et("Name expected");var n=st.token.value;it(),q(")"),e=[n,P()]}return rt("keyword","finally")&&(it(),t=P()),!e&&!t&&et("Missing catch/finally blocks"),V("try",i,e,t)}function P(){q("{");for(var e=[];!rt("punc","}");)rt("eof")&&Z(),e.push(ot());return it(),e}function A(){var e,t=X(),i=ot();return rt("keyword","else")&&(it(),e=ot()),V("if",t,i,e)}function M(e){var t="var"==e[0]?V("name",e[1][0]):e;it();var i=ct();return q(")"),V("for-in",e,t,i,n(ot))}function N(e){q(";");var t=rt("punc",";")?null:ct();q(";");var i=rt("punc",")")?null:ct();return q(")"),V("for",e,t,i,n(ot))}function R(){q("(");var e=null;return!rt("punc",";")&&(e=rt("keyword","var")?(it(),E(!0)):ct(!0,!0),rt("operator","in"))?M(e):N(e)}function D(e){var t;return $()||(t=rt("name")?st.token.value:null),null!=t?(it(),h(t,st.labels)||et("Label "+t+" without matching loop or statement")):0==st.in_loop&&et(e+" not inside a loop or switch"),Y(),V(e,t)}function I(){return V("stat",p(ct,Y))}function F(e){st.labels.push(e);var i=st.token,n=ot();return t&&!l(H,n[0])&&Z(i),st.labels.pop(),V("label",e,n)}function G(e){return i?function(){var t=st.token,i=e.apply(this,arguments);return i[0]=B(i[0],t,tt()),i}:e}function B(e,t,i){return e instanceof g?e:new g(e,t,i)}function X(){q("(");var e=ct();return q(")"),e}function V(){return u(arguments)}function Y(){rt("punc",";")?it():$()||Z()}function $(){return!t&&(st.token.nlb||rt("eof")||rt("punc","}"))}function q(e){return K("punc",e)}function K(e,t){return rt(e,t)?it():(Q(st.token,"Unexpected token "+st.token.type+", expected "+e),void 0)}function Z(e){null==e&&(e=st.token),Q(e,"Unexpected token: "+e.type+" ("+e.value+")")}function Q(e,t){et(t,e.line,e.col)}function et(e,t,i,n){var r=st.input.context();b(e,null!=t?t:r.tokline,null!=i?i:r.tokcol,null!=n?n:r.tokpos)}function tt(){return st.prev}function it(){return st.prev=st.token,st.peeked?(st.token=st.peeked,st.peeked=null):st.token=st.input(),st.token}function nt(){return st.peeked||(st.peeked=st.input())}function rt(e,t){return v(st.token,e,t)}var st={input:"string"==typeof e?y(e,!0):e,token:null,prev:null,peeked:null,in_function:0,in_loop:0,labels:[]};st.token=it();var ot=G(function(){switch(rt("operator","/")&&(st.peeked=null,st.token=st.input(!0)),st.token.type){case"num":case"string":case"regexp":case"operator":case"atom":return I();case"name":return v(nt(),"punc",":")?F(p(st.token.value,it,it)):I();case"punc":switch(st.token.value){case"{":return V("block",P());case"[":case"(":return I();case";":return it(),V("block");default:Z()}case"keyword":switch(p(st.token.value,it)){case"break":return D("break");case"continue":return D("continue");case"debugger":return Y(),V("debugger");case"do":return function(e){return K("keyword","while"),V("do",p(X,Y),e)}(n(ot));case"for":return R();case"function":return at(!0);case"if":return A();case"return":return 0==st.in_function&&et("'return' outside of function"),V("return",rt("punc",";")?(it(),null):$()?null:p(ct,Y));case"switch":return V("switch",X(),lt());case"throw":return V("throw",p(ct,Y));case"try":return k();case"var":return p(E,Y);case"const":return p(_,Y);case"while":return V("while",X(),n(ot));case"with":return V("with",X(),ot());default:Z()}}}),at=G(function(e){var t=rt("name")?p(st.token.value,it):null;return e&&!t&&Z(),q("("),V(e?"defun":"function",t,function(e,t){for(;!rt("punc",")");)e?e=!1:q(","),rt("name")||Z(),t.push(st.token.value),it();return it(),t}(!0,[]),function(){++st.in_function;var e=st.in_loop;st.in_loop=0;var t=P();return--st.in_function,st.in_loop=e,t}())}),lt=f(n,function(){q("{");for(var e=[],t=null;!rt("punc","}");)rt("eof")&&Z(),rt("keyword","case")?(it(),t=[],e.push([ct(),t]),q(":")):rt("keyword","default")?(it(),q(":"),t=[],e.push([null,t])):(t||Z(),t.push(ot()));return it(),e}),ht=G(function(e){if(rt("operator","new"))return it(),O();if(rt("operator")&&l(z,st.token.value))return d("unary-prefix",p(st.token.value,it),ht(e));if(rt("punc")){switch(st.token.value){case"(":return it(),m(p(ct,f(q,")")),e);case"[":return it(),m(w(),e);case"{":return it(),m(C(),e)}Z()}if(rt("keyword","function"))return it(),m(at(!1),e);if(l(W,st.token.type)){var t="regexp"==st.token.type?V("regexp",st.token.value[0],st.token.value[1]):V(st.token.type,st.token.value);return m(p(t,it),e)}Z()}),ct=G(function(e,t){0==arguments.length&&(e=!0);var i=r(t);return e&&rt("punc",",")?(it(),V("seq",i,ct(!0,t))):i});return V("toplevel",function(e){for(;!rt("eof");)e.push(ot());return e}([]))}function g(e,t,i){this.name=e,this.start=t,this.end=i}function y(e){function t(e){if(e)return a();y(),L();var t=M();return t?O(t)?f():'"'==t||"'"==t?u():l(G,t)?v("punc",T()):"."==t?r():"/"==t?s():l(A,t)?o():"\\"==t||w(t)?n():(m("Unexpected character '"+t+"'"),void 0):v("eof")}function i(e,t){try{return t()}catch(i){if(i!==X)throw i;m(e)}}function n(){var e=g(C);return l(E,e)?l(D,e)?v("operator",e):l(P,e)?v("atom",e):v("keyword",e):v("name",e)}function r(){return T(),O(M())?f("."):v("punc",".")}function s(){T();var e=N.regex_allowed;switch(M()){case"/":return N.comments_before.push(c()),N.regex_allowed=e,t();case"*":return N.comments_before.push(h()),N.regex_allowed=e,t()}return N.regex_allowed?a():o("/")}function o(e){function t(e){if(!M())return e;var i=e+M();return l(D,i)?(T(),t(i)):e}return v("operator",t(e||T()))}function a(){return i("Unterminated regular expression",function(){for(var e,t=!1,i="",n=!1;e=T(!0);)if(t)i+="\\"+e,t=!1;else if("["==e)n=!0,i+=e;else if("]"==e&&n)n=!1,i+=e;else{if("/"==e&&!n)break;"\\"==e?t=!0:i+=e}var r=g(function(e){return l(B,e)});return v("regexp",[i,r])})}function h(){return T(),i("Unterminated multiline comment",function(){var e=_("*/",!0),t=N.text.substring(N.pos,e),i=v("comment2",t,!0);return N.pos=e+2,N.line+=t.split("\n").length-1,N.newline_before=t.indexOf("\n")>=0,i})}function c(){T();var e,t=_("\n");return-1==t?(e=N.text.substr(N.pos),N.pos=N.text.length):(e=N.text.substring(N.pos,t),N.pos=t),v("comment1",e,!0)}function u(){return i("Unterminated string constant",function(){for(var e=T(),t="";;){var i=T(!0);if("\\"==i)i=p();else if(i==e)break;t+=i}return v("string",t)})}function d(e){for(var t=0;e>0;--e){var i=parseInt(T(!0),16);isNaN(i)&&m("Invalid hex-character pattern in string"),t=t<<4|i}return t}function p(){var e=T(!0);switch(e){case"n":return"\n";case"r":return"\r";case"t":return" ";case"b":return"\b";case"v":return" ";case"f":return"\f";case"0":return"\0";case"x":return String.fromCharCode(d(2));case"u":return String.fromCharCode(d(4));case"\n":return"";default:return e}}function f(e){var t=!1,i=!1,n=!1,r="."==e,s=g(function(s,o){return"x"==s||"X"==s?n?!1:n=!0:n||"E"!=s&&"e"!=s?"-"==s?i||0==o&&!e?!0:!1:"+"==s?i:(i=!1,"."==s?r||n?!1:r=!0:S(s)):t?!1:t=i=!0});e&&(s=e+s);var o=x(s);return isNaN(o)?(m("Invalid syntax: "+s),void 0):v("num",o)}function m(e){b(e,N.tokline,N.tokcol,N.tokpos)}function g(e){for(var t="",i=M(),n=0;i&&e(i,n++);)t+=T(),i=M();return t}function y(){for(;l(I,M());)T()}function v(e,t,i){N.regex_allowed="operator"==e&&!l(j,t)||"keyword"==e&&l(k,t)||"punc"==e&&l(F,t);var n={type:e,value:t,line:N.tokline,col:N.tokcol,pos:N.tokpos,nlb:N.newline_before};return i||(n.comments_before=N.comments_before,N.comments_before=[]),N.newline_before=!1,n}function L(){N.tokline=N.line,N.tokcol=N.col,N.tokpos=N.pos}function _(e,t){var i=N.text.indexOf(e,N.pos);if(t&&-1==i)throw X;return i}function T(e){var t=N.text.charAt(N.pos++);if(e&&!t)throw X;return"\n"==t?(N.newline_before=!0,++N.line,N.col=0):++N.col,t}function M(){return N.text.charAt(N.pos)}var N={text:e.replace(/\r\n?|[\n\u2028\u2029]/g,"\n").replace(/^\uFEFF/,""),pos:0,tokpos:0,line:0,tokline:0,col:0,tokcol:0,newline_before:!1,regex_allowed:!1,comments_before:[]};return t.context=function(e){return e&&(N=e),N},t}function v(e,t,i){return e.type==t&&(null==i||e.value==i)}function b(e,t,i,n){throw new L(e,t,i,n)}function L(e,t,i,n){this.message=e,this.line=t,this.col=i,this.pos=n}function x(e){return M.test(e)?parseInt(e.substr(2),16):N.test(e)?parseInt(e.substr(1),8):R.test(e)?parseFloat(e):void 0}function C(e){return w(e)||O(e)}function w(e){return"$"==e||"_"==e||_(e)}function S(e){return O(e)||_(e)}function O(e){return e=e.charCodeAt(0),e>=48&&57>=e}function _(e){return e=e.charCodeAt(0),e>=65&&90>=e||e>=97&&122>=e}var E=d(["break","case","catch","const","continue","default","delete","do","else","finally","for","function","if","in","instanceof","new","return","switch","throw","try","typeof","var","void","while","with"]),T=d(["abstract","boolean","byte","char","class","debugger","double","enum","export","extends","final","float","goto","implements","import","int","interface","long","native","package","private","protected","public","short","static","super","synchronized","throws","transient","volatile"]),k=d(["return","new","delete","throw","else","case"]),P=d(["false","null","true","undefined"]),A=d(c("+-*&%=<>!?|~^")),M=/^0x[0-9a-f]+$/i,N=/^0[0-7]+$/,R=/^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i,D=d(["in","instanceof","typeof","new","void","delete","++","--","+","-","!","~","&","|","^","*","/","%",">>","<<",">>>","<",">","<=",">=","==","===","!=","!==","?","=","+=","-=","/=","*=","%=",">>=","<<=",">>>=","|=","^=","&=","&&","||"]),I=d(c(" \n\r ")),F=d(c("[{}(,.;:")),G=d(c("[]{}(),;:")),B=d(c("gmsiy"));L.prototype.toString=function(){return this.message+" (line: "+this.line+", col: "+this.col+", pos: "+this.pos+")"};var X={},z=d(["typeof","void","delete","--","++","!","~","-","+"]),j=d(["--","++"]),J=function(e,t,i){for(;e.length>i;)t[e[i]]=e[i].substr(0,e[i].length-1),i++;return t}(["+=","-=","/=","*=","%=",">>=","<<=",">>>=","|=","^=","&="],{"=":!0},0),U=function(e,t){for(var i=0,n=1;e.length>i;++i,++n)for(var r=e[i],s=0;r.length>s;++s)t[r[s]]=n;return t}([["||"],["&&"],["|"],["^"],["&"],["==","===","!=","!=="],["<",">","<=",">=","in","instanceof"],[">>","<<",">>>"],["+","-"],["*","/","%"]],{}),H=d(["for","do","while","switch"]),W=d(["atom","num","string","regexp","name"]);g.prototype.toString=function(){return this.name};var V=d(["name","array","object","string","dot","sub","call","regexp"]),Y=d(["if","while","do","for","for-in","with"]);return{parse:m,gen_code:r,tokenizer:y,ast_walker:a}},operators={"+":"add","-":"subtract","*":"multiply","/":"divide","%":"modulo","==":"equals","!=":"equals"},signOperators={"-":"negate"};return DomEvent.add(window,{load:load}),{compile:compile,evaluate:evaluate,load:load,getAttribute:handleAttribute("get"),hasAttribute:handleAttribute("has")}};return this.load=PaperScript.load,Base.each(this,function(e,t){e&&e.prototype instanceof Base&&(e._name=t)}),this.enumerable=!0,new(PaperScope.inject(this))}; \ No newline at end of file