server/php/basic/public_html/static/lib/paper/paper-full.js
changeset 495 444b80998255
parent 442 adb907bba956
child 598 eb4f4eceada0
equal deleted inserted replaced
494:fd7bfe49155a 495:444b80998255
     1 /*!
     1 /*!
     2  * Paper.js v0.9.22 - The Swiss Army Knife of Vector Graphics Scripting.
     2  * Paper.js v0.9.24 - The Swiss Army Knife of Vector Graphics Scripting.
     3  * http://paperjs.org/
     3  * http://paperjs.org/
     4  *
     4  *
     5  * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
     5  * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
     6  * http://scratchdisk.com/ & http://jonathanpuckey.com/
     6  * http://scratchdisk.com/ & http://jonathanpuckey.com/
     7  *
     7  *
     8  * Distributed under the MIT license. See LICENSE file for details.
     8  * Distributed under the MIT license. See LICENSE file for details.
     9  *
     9  *
    10  * All rights reserved.
    10  * All rights reserved.
    11  *
    11  *
    12  * Date: Sat Feb 28 19:20:48 2015 +0100
    12  * Date: Fri Aug 21 16:39:41 2015 +0200
    13  *
    13  *
    14  ***
    14  ***
    15  *
    15  *
    16  * Straps.js - Class inheritance library with support for bean-style accessors
    16  * Straps.js - Class inheritance library with support for bean-style accessors
    17  *
    17  *
    86 					&& (val.get ? val : val.value);
    86 					&& (val.get ? val : val.value);
    87 			if (typeof val === 'string' && val[0] === '#')
    87 			if (typeof val === 'string' && val[0] === '#')
    88 				val = dest[val.substring(1)] || val;
    88 				val = dest[val.substring(1)] || val;
    89 			var isFunc = typeof val === 'function',
    89 			var isFunc = typeof val === 'function',
    90 				res = val,
    90 				res = val,
    91 				prev = preserve || isFunc
    91 				prev = preserve || isFunc && !val.base
    92 						? (val && val.get ? name in dest : dest[name])
    92 						? (val && val.get ? name in dest : dest[name])
    93 						: null,
    93 						: null,
    94 				bean;
    94 				bean;
    95 			if (!preserve || !prev) {
    95 			if (!preserve || !prev) {
    96 				if (isFunc && prev)
    96 				if (isFunc && prev)
   159 			return this;
   159 			return this;
   160 		},
   160 		},
   161 
   161 
   162 		extend: function() {
   162 		extend: function() {
   163 			var base = this,
   163 			var base = this,
   164 				ctor;
   164 				ctor,
       
   165 				proto;
   165 			for (var i = 0, l = arguments.length; i < l; i++)
   166 			for (var i = 0, l = arguments.length; i < l; i++)
   166 				if (ctor = arguments[i].initialize)
   167 				if (ctor = arguments[i].initialize)
   167 					break;
   168 					break;
   168 			ctor = ctor || function() {
   169 			ctor = ctor || function() {
   169 				base.apply(this, arguments);
   170 				base.apply(this, arguments);
   170 			};
   171 			};
   171 			ctor.prototype = create(this.prototype);
   172 			proto = ctor.prototype = create(this.prototype);
   172 			ctor.base = base;
   173 			define(proto, 'constructor',
   173 			define(ctor.prototype, 'constructor',
       
   174 					{ value: ctor, writable: true, configurable: true });
   174 					{ value: ctor, writable: true, configurable: true });
   175 			inject(ctor, this, true);
   175 			inject(ctor, this, true);
   176 			return arguments.length ? this.inject.apply(ctor, arguments) : ctor;
   176 			if (arguments.length)
       
   177 				this.inject.apply(ctor, arguments);
       
   178 			ctor.base = base;
       
   179 			return ctor;
   177 		}
   180 		}
   178 	}, true).inject({
   181 	}, true).inject({
   179 		inject: function() {
   182 		inject: function() {
   180 			for (var i = 0, l = arguments.length; i < l; i++) {
   183 			for (var i = 0, l = arguments.length; i < l; i++) {
   181 				var src = arguments[i];
   184 				var src = arguments[i];
   257 		return Base.serialize(this);
   260 		return Base.serialize(this);
   258 	},
   261 	},
   259 
   262 
   260 	_set: function(props, exclude, dontCheck) {
   263 	_set: function(props, exclude, dontCheck) {
   261 		if (props && (dontCheck || Base.isPlainObject(props))) {
   264 		if (props && (dontCheck || Base.isPlainObject(props))) {
   262 			var orig = props._filtering || props;
   265 			var keys = Object.keys(props._filtering || props);
   263 			for (var key in orig) {
   266 			for (var i = 0, l = keys.length; i < l; i++) {
   264 				if (orig.hasOwnProperty(key) && !(exclude && exclude[key])) {
   267 				var key = keys[i];
       
   268 				if (!(exclude && exclude[key])) {
   265 					var value = props[key];
   269 					var value = props[key];
   266 					if (value !== undefined)
   270 					if (value !== undefined)
   267 						this[key] = value;
   271 						this[key] = value;
   268 				}
   272 				}
   269 			}
   273 			}
   284 				Base.exports[name] = res;
   288 				Base.exports[name] = res;
   285 			return res;
   289 			return res;
   286 		},
   290 		},
   287 
   291 
   288 		equals: function(obj1, obj2) {
   292 		equals: function(obj1, obj2) {
   289 			function checkKeys(o1, o2) {
       
   290 				for (var i in o1)
       
   291 					if (o1.hasOwnProperty(i) && !o2.hasOwnProperty(i))
       
   292 						return false;
       
   293 				return true;
       
   294 			}
       
   295 			if (obj1 === obj2)
   293 			if (obj1 === obj2)
   296 				return true;
   294 				return true;
   297 			if (obj1 && obj1.equals)
   295 			if (obj1 && obj1.equals)
   298 				return obj1.equals(obj2);
   296 				return obj1.equals(obj2);
   299 			if (obj2 && obj2.equals)
   297 			if (obj2 && obj2.equals)
   300 				return obj2.equals(obj1);
   298 				return obj2.equals(obj1);
   301 			if (Array.isArray(obj1) && Array.isArray(obj2)) {
   299 			if (obj1 && obj2
   302 				if (obj1.length !== obj2.length)
   300 					&& typeof obj1 === 'object' && typeof obj2 === 'object') {
   303 					return false;
   301 				if (Array.isArray(obj1) && Array.isArray(obj2)) {
   304 				for (var i = 0, l = obj1.length; i < l; i++) {
   302 					var length = obj1.length;
   305 					if (!Base.equals(obj1[i], obj2[i]))
   303 					if (length !== obj2.length)
   306 						return false;
   304 						return false;
   307 				}
   305 					while (length--) {
   308 				return true;
   306 						if (!Base.equals(obj1[length], obj2[length]))
   309 			}
   307 							return false;
   310 			if (obj1 && typeof obj1 === 'object'
   308 					}
   311 					&& obj2 && typeof obj2 === 'object') {
   309 				} else {
   312 				if (!checkKeys(obj1, obj2) || !checkKeys(obj2, obj1))
   310 					var keys = Object.keys(obj1),
   313 					return false;
   311 						length = keys.length;
   314 				for (var i in obj1) {
   312 					if (length !== Object.keys(obj2).length)
   315 					if (obj1.hasOwnProperty(i)
       
   316 							&& !Base.equals(obj1[i], obj2[i]))
       
   317 						return false;
   313 						return false;
       
   314 					while (length--) {
       
   315 						var key = keys[length];
       
   316 						if (!(obj2.hasOwnProperty(key)
       
   317 								&& Base.equals(obj1[key], obj2[key])))
       
   318 							return false;
       
   319 					}
   318 				}
   320 				}
   319 				return true;
   321 				return true;
   320 			}
   322 			}
   321 			return false;
   323 			return false;
   322 		},
   324 		},
   441 							dictionary);
   443 							dictionary);
   442 				if (compact)
   444 				if (compact)
   443 					res._compact = true;
   445 					res._compact = true;
   444 			} else if (Base.isPlainObject(obj)) {
   446 			} else if (Base.isPlainObject(obj)) {
   445 				res = {};
   447 				res = {};
   446 				for (var i in obj)
   448 				var keys = Object.keys(obj);
   447 					if (obj.hasOwnProperty(i))
   449 				for (var i = 0, l = keys.length; i < l; i++) {
   448 						res[i] = Base.serialize(obj[i], options, compact,
   450 					var key = keys[i];
   449 								dictionary);
   451 					res[key] = Base.serialize(obj[key], options, compact,
       
   452 							dictionary);
       
   453 				}
   450 			} else if (typeof obj === 'number') {
   454 			} else if (typeof obj === 'number') {
   451 				res = options.formatter.number(obj, options.precision);
   455 				res = options.formatter.number(obj, options.precision);
   452 			} else {
   456 			} else {
   453 				res = obj;
   457 				res = obj;
   454 			}
   458 			}
   455 			return root && dictionary.length > 0
   459 			return root && dictionary.length > 0
   456 					? [['dictionary', dictionary.definitions], res]
   460 					? [['dictionary', dictionary.definitions], res]
   457 					: res;
   461 					: res;
   458 		},
   462 		},
   459 
   463 
   460 		deserialize: function(json, create, _data) {
   464 		deserialize: function(json, create, _data, _isDictionary) {
   461 			var res = json,
   465 			var res = json,
   462 				isRoot = !_data;
   466 				isRoot = !_data;
   463 			_data = _data || {};
   467 			_data = _data || {};
   464 			if (Array.isArray(json)) {
   468 			if (Array.isArray(json)) {
   465 				var type = json[0],
   469 				var type = json[0],
   466 					isDictionary = type === 'dictionary';
   470 					isDictionary = type === 'dictionary';
   467 				if (!isDictionary) {
   471 				if (json.length == 1 && /^#/.test(type))
   468 					if (_data.dictionary && json.length == 1 && /^#/.test(type))
   472 					return _data.dictionary[type];
   469 						return _data.dictionary[type];
   473 				type = Base.exports[type];
   470 					type = Base.exports[type];
       
   471 				}
       
   472 				res = [];
   474 				res = [];
       
   475 				if (_isDictionary)
       
   476 					_data.dictionary = res;
   473 				for (var i = type ? 1 : 0, l = json.length; i < l; i++)
   477 				for (var i = type ? 1 : 0, l = json.length; i < l; i++)
   474 					res.push(Base.deserialize(json[i], create, _data));
   478 					res.push(Base.deserialize(json[i], create, _data,
   475 				if (isDictionary) {
   479 							isDictionary));
   476 					_data.dictionary = res[0];
   480 				if (type) {
   477 				} else if (type) {
       
   478 					var args = res;
   481 					var args = res;
   479 					if (create) {
   482 					if (create) {
   480 						res = create(type, args);
   483 						res = create(type, args);
   481 					} else {
   484 					} else {
   482 						res = Base.create(type.prototype);
   485 						res = Base.create(type.prototype);
   483 						type.apply(res, args);
   486 						type.apply(res, args);
   484 					}
   487 					}
   485 				}
   488 				}
   486 			} else if (Base.isPlainObject(json)) {
   489 			} else if (Base.isPlainObject(json)) {
   487 				res = {};
   490 				res = {};
       
   491 				if (_isDictionary)
       
   492 					_data.dictionary = res;
   488 				for (var key in json)
   493 				for (var key in json)
   489 					res[key] = Base.deserialize(json[key], create, _data);
   494 					res[key] = Base.deserialize(json[key], create, _data);
   490 			}
   495 			}
   491 			return isRoot && json && json.length && json[0][0] === 'dictionary'
   496 			return isRoot && json && json.length && json[0][0] === 'dictionary'
   492 					? res[1]
   497 					? res[1]
   568 		if (typeof type !== 'string') {
   573 		if (typeof type !== 'string') {
   569 			Base.each(type, function(value, key) {
   574 			Base.each(type, function(value, key) {
   570 				this.on(key, value);
   575 				this.on(key, value);
   571 			}, this);
   576 			}, this);
   572 		} else {
   577 		} else {
   573 			var entry = this._eventTypes[type];
   578 			var types = this._eventTypes,
   574 			if (entry) {
   579 				entry = types && types[type],
   575 				var handlers = this._callbacks = this._callbacks || {};
   580 				handlers = this._callbacks = this._callbacks || {};
   576 				handlers = handlers[type] = handlers[type] || [];
   581 			handlers = handlers[type] = handlers[type] || [];
   577 				if (handlers.indexOf(func) === -1) {
   582 			if (handlers.indexOf(func) === -1) {
   578 					handlers.push(func);
   583 				handlers.push(func);
   579 					if (entry.install && handlers.length == 1)
   584 				if (entry && entry.install && handlers.length == 1)
   580 						entry.install.call(this, type);
   585 					entry.install.call(this, type);
   581 				}
       
   582 			}
   586 			}
   583 		}
   587 		}
   584 		return this;
   588 		return this;
   585 	},
   589 	},
   586 
   590 
   589 			Base.each(type, function(value, key) {
   593 			Base.each(type, function(value, key) {
   590 				this.off(key, value);
   594 				this.off(key, value);
   591 			}, this);
   595 			}, this);
   592 			return;
   596 			return;
   593 		}
   597 		}
   594 		var entry = this._eventTypes[type],
   598 		var types = this._eventTypes,
       
   599 			entry = types && types[type],
   595 			handlers = this._callbacks && this._callbacks[type],
   600 			handlers = this._callbacks && this._callbacks[type],
   596 			index;
   601 			index;
   597 		if (entry && handlers) {
   602 		if (handlers) {
   598 			if (!func || (index = handlers.indexOf(func)) !== -1
   603 			if (!func || (index = handlers.indexOf(func)) !== -1
   599 					&& handlers.length === 1) {
   604 					&& handlers.length === 1) {
   600 				if (entry.uninstall)
   605 				if (entry && entry.uninstall)
   601 					entry.uninstall.call(this, type);
   606 					entry.uninstall.call(this, type);
   602 				delete this._callbacks[type];
   607 				delete this._callbacks[type];
   603 			} else if (index !== -1) {
   608 			} else if (index !== -1) {
   604 				handlers.splice(index, 1);
   609 				handlers.splice(index, 1);
   605 			}
   610 			}
   617 	emit: function(type, event) {
   622 	emit: function(type, event) {
   618 		var handlers = this._callbacks && this._callbacks[type];
   623 		var handlers = this._callbacks && this._callbacks[type];
   619 		if (!handlers)
   624 		if (!handlers)
   620 			return false;
   625 			return false;
   621 		var args = [].slice.call(arguments, 1);
   626 		var args = [].slice.call(arguments, 1);
       
   627 		handlers = handlers.slice();
   622 		for (var i = 0, l = handlers.length; i < l; i++) {
   628 		for (var i = 0, l = handlers.length; i < l; i++) {
   623 			if (handlers[i].apply(this, args) === false
   629 			if (handlers[i].apply(this, args) === false) {
   624 					&& event && event.stop) {
   630 				if (event && event.stop)
   625 				event.stop();
   631 					event.stop();
   626 				break;
   632 				break;
   627 			}
   633 			}
   628 		}
   634 		}
   629 		return true;
   635 		return true;
   630 	},
   636 	},
   640 	_installEvents: function(install) {
   646 	_installEvents: function(install) {
   641 		var handlers = this._callbacks,
   647 		var handlers = this._callbacks,
   642 			key = install ? 'install' : 'uninstall';
   648 			key = install ? 'install' : 'uninstall';
   643 		for (var type in handlers) {
   649 		for (var type in handlers) {
   644 			if (handlers[type].length > 0) {
   650 			if (handlers[type].length > 0) {
   645 				var entry = this._eventTypes[type],
   651 				var types = this._eventTypes,
   646 					func = entry[key];
   652 					entry = types && types[type],
       
   653 					func = entry && entry[key];
   647 				if (func)
   654 				if (func)
   648 					func.call(this, type);
   655 					func.call(this, type);
   649 			}
   656 			}
   650 		}
   657 		}
   651 	},
   658 	},
   706 			};
   713 			};
   707 			CanvasProvider.release(ctx);
   714 			CanvasProvider.release(ctx);
   708 		}
   715 		}
   709 
   716 
   710 		if (!this.browser) {
   717 		if (!this.browser) {
   711 			var browser = proto.browser = {};
   718 			var agent = navigator.userAgent.toLowerCase(),
   712 			navigator.userAgent.toLowerCase().replace(
   719 				platform = (/(win)/.exec(agent)
       
   720 						|| /(mac)/.exec(agent)
       
   721 						|| /(linux)/.exec(agent)
       
   722 						|| [])[0],
       
   723 				browser = proto.browser = { platform: platform };
       
   724 			if (platform)
       
   725 				browser[platform] = true;
       
   726 			agent.replace(
   713 				/(opera|chrome|safari|webkit|firefox|msie|trident|atom)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:([.\d]+))?/g,
   727 				/(opera|chrome|safari|webkit|firefox|msie|trident|atom)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:([.\d]+))?/g,
   714 				function(all, n, v1, v2, rv) {
   728 				function(all, n, v1, v2, rv) {
   715 					if (!browser.chrome) {
   729 					if (!browser.chrome) {
   716 						var v = n === 'opera' ? v2 : v1;
   730 						var v = n === 'opera' ? v2 : v1;
   717 						if (n === 'trident') {
   731 						if (n === 'trident') {
   730 			if (browser.atom)
   744 			if (browser.atom)
   731 				delete browser.chrome;
   745 				delete browser.chrome;
   732 		}
   746 		}
   733 	},
   747 	},
   734 
   748 
   735 	version: '0.9.22',
   749 	version: '0.9.24',
   736 
   750 
   737 	getView: function() {
   751 	getView: function() {
   738 		return this.project && this.project.getView();
   752 		return this.project && this.project.getView();
   739 	},
   753 	},
   740 
   754 
   967 				x1, x2 = Infinity,
   981 				x1, x2 = Infinity,
   968 				B = b,
   982 				B = b,
   969 				D;
   983 				D;
   970 			b /= 2;
   984 			b /= 2;
   971 			D = b * b - a * c;
   985 			D = b * b - a * c;
   972 			if (abs(D) < MACHINE_EPSILON) {
   986 			if (D !== 0 && abs(D) < MACHINE_EPSILON) {
   973 				var pow = Math.pow,
   987 				var gmC = pow(abs(a * b * c), 1 / 3);
   974 					gmC = pow(abs(a*b*c), 1/3);
       
   975 				if (gmC < 1e-8) {
   988 				if (gmC < 1e-8) {
   976 					/*
       
   977 					 * we multiply with a factor to normalize the
       
   978 					 * coefficients. The factor is just the nearest exponent
       
   979 					 * of 10, big enough to raise all the coefficients to
       
   980 					 * nearly [-1, +1] range.
       
   981 					 */
       
   982 					var mult = pow(10, abs(
   989 					var mult = pow(10, abs(
   983 						Math.floor(Math.log(gmC) * Math.LOG10E)));
   990 						Math.floor(Math.log(gmC) * Math.LOG10E)));
   984 					if (!isFinite(mult))
   991 					if (!isFinite(mult))
   985 						mult = 0;
   992 						mult = 0;
   986 					a *= mult;
   993 					a *= mult;
   987 					b *= mult;
   994 					b *= mult;
   988 					c *= mult;
   995 					c *= mult;
   989 					D = b * b - a * c;
   996 					D = b * b - a * c;
   990 				}
   997 				}
   991 			}
   998 			}
   992 			if (abs(a) < MACHINE_EPSILON) {
   999 			if (abs(a) < EPSILON) {
   993 				if (abs(B) < MACHINE_EPSILON)
  1000 				if (abs(B) < EPSILON)
   994 					return abs(c) < MACHINE_EPSILON ? -1 : 0;
  1001 					return abs(c) < EPSILON ? -1 : 0;
   995 				x1 = -c / B;
  1002 				x1 = -c / B;
   996 			} else {
  1003 			} else {
   997 				if (D >= -MACHINE_EPSILON) {
  1004 				if (D >= -MACHINE_EPSILON) {
   998 					D = D < 0 ? 0 : D;
  1005 					D = D < 0 ? 0 : D;
   999 					var R = sqrt(D);
  1006 					var R = sqrt(D);
  1014 				roots[count++] = x2;
  1021 				roots[count++] = x2;
  1015 			return count;
  1022 			return count;
  1016 		},
  1023 		},
  1017 
  1024 
  1018 		solveCubic: function(a, b, c, d, roots, min, max) {
  1025 		solveCubic: function(a, b, c, d, roots, min, max) {
  1019 			var x, b1, c2, count = 0;
  1026 			var count = 0,
  1020 			if (a === 0) {
  1027 				x, b1, c2;
       
  1028 			if (abs(a) < EPSILON) {
  1021 				a = b;
  1029 				a = b;
  1022 				b1 = c;
  1030 				b1 = c;
  1023 				c2 = d;
  1031 				c2 = d;
  1024 				x = Infinity;
  1032 				x = Infinity;
  1025 			} else if (d === 0) {
  1033 			} else if (abs(d) < EPSILON) {
  1026 				b1 = b;
  1034 				b1 = b;
  1027 				c2 = c;
  1035 				c2 = c;
  1028 				x = 0;
  1036 				x = 0;
  1029 			} else {
  1037 			} else {
  1030 				var ec = 1 + MACHINE_EPSILON,
  1038 				var ec = 1 + MACHINE_EPSILON,
  1068 			return count;
  1076 			return count;
  1069 		}
  1077 		}
  1070 	};
  1078 	};
  1071 };
  1079 };
  1072 
  1080 
       
  1081 var UID = {
       
  1082 	_id: 1,
       
  1083 	_pools: {},
       
  1084 
       
  1085 	get: function(ctor) {
       
  1086 		if (ctor) {
       
  1087 			var name = ctor._class,
       
  1088 				pool = this._pools[name];
       
  1089 			if (!pool)
       
  1090 				pool = this._pools[name] = { _id: 1 };
       
  1091 			return pool._id++;
       
  1092 		} else {
       
  1093 			return this._id++;
       
  1094 		}
       
  1095 	}
       
  1096 };
       
  1097 
  1073 var Point = Base.extend({
  1098 var Point = Base.extend({
  1074 	_class: 'Point',
  1099 	_class: 'Point',
  1075 	_readIndex: true,
  1100 	_readIndex: true,
  1076 
  1101 
  1077 	initialize: function Point(arg0, arg1) {
  1102 	initialize: function Point(arg0, arg1) {
  1282 
  1307 
  1283 	isClose: function(point, tolerance) {
  1308 	isClose: function(point, tolerance) {
  1284 		return this.getDistance(point) < tolerance;
  1309 		return this.getDistance(point) < tolerance;
  1285 	},
  1310 	},
  1286 
  1311 
  1287 	isColinear: function(point) {
  1312 	isCollinear: function(point) {
  1288 		return Math.abs(this.cross(point)) < 1e-12;
  1313 		return Math.abs(this.cross(point)) < 0.000001;
  1289 	},
  1314 	},
       
  1315 
       
  1316 	isColinear: '#isCollinear',
  1290 
  1317 
  1291 	isOrthogonal: function(point) {
  1318 	isOrthogonal: function(point) {
  1292 		return Math.abs(this.dot(point)) < 1e-12;
  1319 		return Math.abs(this.dot(point)) < 0.000001;
  1293 	},
  1320 	},
  1294 
  1321 
  1295 	isZero: function() {
  1322 	isZero: function() {
  1296 		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
  1323 		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
  1297 	},
  1324 	},
  2636 
  2663 
  2637 var Symbol = Base.extend({
  2664 var Symbol = Base.extend({
  2638 	_class: 'Symbol',
  2665 	_class: 'Symbol',
  2639 
  2666 
  2640 	initialize: function Symbol(item, dontCenter) {
  2667 	initialize: function Symbol(item, dontCenter) {
  2641 		this._id = Symbol._id = (Symbol._id || 0) + 1;
  2668 		this._id = UID.get();
  2642 		this.project = paper.project;
  2669 		this.project = paper.project;
  2643 		this.project.symbols.push(this);
  2670 		this.project.symbols.push(this);
  2644 		if (item)
  2671 		if (item)
  2645 			this.setDefinition(item, dontCenter);
  2672 			this.setDefinition(item, dontCenter);
  2646 	},
  2673 	},
  2733 		var hasProps = props && Base.isPlainObject(props),
  2760 		var hasProps = props && Base.isPlainObject(props),
  2734 			internal = hasProps && props.internal === true,
  2761 			internal = hasProps && props.internal === true,
  2735 			matrix = this._matrix = new Matrix(),
  2762 			matrix = this._matrix = new Matrix(),
  2736 			project = hasProps && props.project || paper.project;
  2763 			project = hasProps && props.project || paper.project;
  2737 		if (!internal)
  2764 		if (!internal)
  2738 			this._id = Item._id = (Item._id || 0) + 1;
  2765 			this._id = UID.get();
  2739 		this._applyMatrix = this._canApplyMatrix && paper.settings.applyMatrix;
  2766 		this._applyMatrix = this._canApplyMatrix && paper.settings.applyMatrix;
  2740 		if (point)
  2767 		if (point)
  2741 			matrix.translate(point);
  2768 			matrix.translate(point);
  2742 		matrix._owner = this;
  2769 		matrix._owner = this;
  2743 		this._style = new Style(project._currentStyle, this, project);
  2770 		this._style = new Style(project._currentStyle, this, project);
  2749 			} else {
  2776 			} else {
  2750 				(project._activeLayer || new Layer()).addChild(this);
  2777 				(project._activeLayer || new Layer()).addChild(this);
  2751 			}
  2778 			}
  2752 		}
  2779 		}
  2753 		if (hasProps && props !== Item.NO_INSERT)
  2780 		if (hasProps && props !== Item.NO_INSERT)
  2754 			this._set(props, { insert: true, parent: true }, true);
  2781 			this._set(props, { insert: true, project: true, parent: true },
       
  2782 					true);
  2755 		return hasProps;
  2783 		return hasProps;
  2756 	},
  2784 	},
  2757 
  2785 
  2758 	_events: new function() {
  2786 	_events: new function() {
  2759 
  2787 
  3044 		}
  3072 		}
  3045 		return pivot;
  3073 		return pivot;
  3046 	},
  3074 	},
  3047 
  3075 
  3048 	setPivot: function() {
  3076 	setPivot: function() {
  3049 		this._pivot = Point.read(arguments);
  3077 		this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
  3050 		this._position = undefined;
  3078 		this._position = undefined;
  3051 	},
  3079 	},
  3052 
  3080 
  3053 	_pivot: null,
  3081 	_pivot: null,
  3054 
       
  3055 	getRegistration: '#getPivot',
       
  3056 	setRegistration: '#setPivot'
       
  3057 }, Base.each(['bounds', 'strokeBounds', 'handleBounds', 'roughBounds',
  3082 }, Base.each(['bounds', 'strokeBounds', 'handleBounds', 'roughBounds',
  3058 		'internalBounds', 'internalRoughBounds'],
  3083 		'internalBounds', 'internalRoughBounds'],
  3059 	function(key) {
  3084 	function(key) {
  3060 		var getter = 'get' + Base.capitalize(key),
  3085 		var getter = 'get' + Base.capitalize(key),
  3061 			match = key.match(/^internal(.*)$/),
  3086 			match = key.match(/^internal(.*)$/),
  3078 
  3103 
  3079 	_getBounds: function(getter, matrix, cacheItem) {
  3104 	_getBounds: function(getter, matrix, cacheItem) {
  3080 		var children = this._children;
  3105 		var children = this._children;
  3081 		if (!children || children.length == 0)
  3106 		if (!children || children.length == 0)
  3082 			return new Rectangle();
  3107 			return new Rectangle();
       
  3108 		Item._updateBoundsCache(this, cacheItem);
  3083 		var x1 = Infinity,
  3109 		var x1 = Infinity,
  3084 			x2 = -x1,
  3110 			x2 = -x1,
  3085 			y1 = x1,
  3111 			y1 = x1,
  3086 			y2 = x2;
  3112 			y2 = x2;
  3087 		for (var i = 0, l = children.length; i < l; i++) {
  3113 		for (var i = 0, l = children.length; i < l; i++) {
  3118 
  3144 
  3119 	_getCachedBounds: function(getter, matrix, cacheItem, internalGetter) {
  3145 	_getCachedBounds: function(getter, matrix, cacheItem, internalGetter) {
  3120 		matrix = matrix && matrix.orNullIfIdentity();
  3146 		matrix = matrix && matrix.orNullIfIdentity();
  3121 		var _matrix = internalGetter ? null : this._matrix.orNullIfIdentity(),
  3147 		var _matrix = internalGetter ? null : this._matrix.orNullIfIdentity(),
  3122 			cache = (!matrix || matrix.equals(_matrix)) && getter;
  3148 			cache = (!matrix || matrix.equals(_matrix)) && getter;
  3123 		var cacheParent = this._parent || this._parentSymbol;
  3149 		Item._updateBoundsCache(this._parent || this._parentSymbol, cacheItem);
  3124 		if (cacheParent) {
       
  3125 			var id = cacheItem._id,
       
  3126 				ref = cacheParent._boundsCache = cacheParent._boundsCache || {
       
  3127 					ids: {},
       
  3128 					list: []
       
  3129 				};
       
  3130 			if (!ref.ids[id]) {
       
  3131 				ref.list.push(cacheItem);
       
  3132 				ref.ids[id] = cacheItem;
       
  3133 			}
       
  3134 		}
       
  3135 		if (cache && this._bounds && this._bounds[cache])
  3150 		if (cache && this._bounds && this._bounds[cache])
  3136 			return this._bounds[cache].clone();
  3151 			return this._bounds[cache].clone();
  3137 		var bounds = this._getBounds(internalGetter || getter,
  3152 		var bounds = this._getBounds(internalGetter || getter,
  3138 				matrix || _matrix, cacheItem);
  3153 				matrix || _matrix, cacheItem);
  3139 		if (cache) {
  3154 		if (cache) {
  3144 		}
  3159 		}
  3145 		return bounds;
  3160 		return bounds;
  3146 	},
  3161 	},
  3147 
  3162 
  3148 	statics: {
  3163 	statics: {
       
  3164 		_updateBoundsCache: function(parent, item) {
       
  3165 			if (parent) {
       
  3166 				var id = item._id,
       
  3167 					ref = parent._boundsCache = parent._boundsCache || {
       
  3168 						ids: {},
       
  3169 						list: []
       
  3170 					};
       
  3171 				if (!ref.ids[id]) {
       
  3172 					ref.list.push(item);
       
  3173 					ref.ids[id] = item;
       
  3174 				}
       
  3175 			}
       
  3176 		},
       
  3177 
  3149 		_clearBoundsCache: function(item) {
  3178 		_clearBoundsCache: function(item) {
  3150 			var cache = item._boundsCache;
  3179 			var cache = item._boundsCache;
  3151 			if (cache) {
  3180 			if (cache) {
  3152 				item._bounds = item._position = item._boundsCache = undefined;
  3181 				item._bounds = item._position = item._boundsCache = undefined;
  3153 				for (var i = 0, list = cache.list, l = list.length; i < l; i++) {
  3182 				for (var i = 0, list = cache.list, l = list.length; i < l; i++){
  3154 					var other = list[i];
  3183 					var other = list[i];
  3155 					if (other !== item) {
  3184 					if (other !== item) {
  3156 						other._bounds = other._position = undefined;
  3185 						other._bounds = other._position = undefined;
  3157 						if (other._boundsCache)
  3186 						if (other._boundsCache)
  3158 							Item._clearBoundsCache(other);
  3187 							Item._clearBoundsCache(other);
  3204 
  3233 
  3205 	getMatrix: function() {
  3234 	getMatrix: function() {
  3206 		return this._matrix;
  3235 		return this._matrix;
  3207 	},
  3236 	},
  3208 
  3237 
  3209 	setMatrix: function(matrix) {
  3238 	setMatrix: function() {
  3210 		this._matrix.initialize(matrix);
  3239 		var matrix = this._matrix;
       
  3240 		matrix.initialize.apply(matrix, arguments);
  3211 		if (this._applyMatrix) {
  3241 		if (this._applyMatrix) {
  3212 			this.transform(null, true);
  3242 			this.transform(null, true);
  3213 		} else {
  3243 		} else {
  3214 			this._changed(9);
  3244 			this._changed(9);
  3215 		}
  3245 		}
  3338 
  3368 
  3339 	clone: function(insert) {
  3369 	clone: function(insert) {
  3340 		return this._clone(new this.constructor(Item.NO_INSERT), insert);
  3370 		return this._clone(new this.constructor(Item.NO_INSERT), insert);
  3341 	},
  3371 	},
  3342 
  3372 
  3343 	_clone: function(copy, insert) {
  3373 	_clone: function(copy, insert, includeMatrix) {
       
  3374 		var keys = ['_locked', '_visible', '_blendMode', '_opacity',
       
  3375 				'_clipMask', '_guide'],
       
  3376 			children = this._children;
  3344 		copy.setStyle(this._style);
  3377 		copy.setStyle(this._style);
  3345 		if (this._children) {
  3378 		for (var i = 0, l = children && children.length; i < l; i++) {
  3346 			for (var i = 0, l = this._children.length; i < l; i++)
  3379 			copy.addChild(children[i].clone(false), true);
  3347 				copy.addChild(this._children[i].clone(false), true);
  3380 		}
  3348 		}
       
  3349 		if (insert || insert === undefined)
       
  3350 			copy.insertAbove(this);
       
  3351 		var keys = ['_locked', '_visible', '_blendMode', '_opacity',
       
  3352 				'_clipMask', '_guide', '_applyMatrix'];
       
  3353 		for (var i = 0, l = keys.length; i < l; i++) {
  3381 		for (var i = 0, l = keys.length; i < l; i++) {
  3354 			var key = keys[i];
  3382 			var key = keys[i];
  3355 			if (this.hasOwnProperty(key))
  3383 			if (this.hasOwnProperty(key))
  3356 				copy[key] = this[key];
  3384 				copy[key] = this[key];
  3357 		}
  3385 		}
  3358 		copy._matrix.initialize(this._matrix);
  3386 		if (includeMatrix !== false)
       
  3387 			copy._matrix.initialize(this._matrix);
       
  3388 		copy.setApplyMatrix(this._applyMatrix);
       
  3389 		copy.setPivot(this._pivot);
       
  3390 		copy.setSelected(this._selected);
  3359 		copy._data = this._data ? Base.clone(this._data) : null;
  3391 		copy._data = this._data ? Base.clone(this._data) : null;
  3360 		copy.setSelected(this._selected);
  3392 		if (insert || insert === undefined)
       
  3393 			copy.insertAbove(this);
  3361 		if (this._name)
  3394 		if (this._name)
  3362 			copy.setName(this._name, true);
  3395 			copy.setName(this._name, true);
  3363 		return copy;
  3396 		return copy;
  3364 	},
  3397 	},
  3365 
  3398 
  3515 					}
  3548 					}
  3516 				}
  3549 				}
  3517 			}
  3550 			}
  3518 			return true;
  3551 			return true;
  3519 		}
  3552 		}
  3520 		if (typeof name === 'object') {
  3553 		var type = typeof name;
       
  3554 		if (type === 'object') {
  3521 			for (var key in name) {
  3555 			for (var key in name) {
  3522 				if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
  3556 				if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
  3523 					return false;
  3557 					return false;
  3524 			}
  3558 			}
       
  3559 		} else if (type === 'function') {
       
  3560 			return name(this);
  3525 		} else {
  3561 		} else {
  3526 			var value = /^(empty|editable)$/.test(name)
  3562 			var value = /^(empty|editable)$/.test(name)
  3527 					? this['is' + Base.capitalize(name)]()
  3563 					? this['is' + Base.capitalize(name)]()
  3528 					: name === 'type'
  3564 					: name === 'type'
  3529 						? Base.hyphenate(this._class)
  3565 						? Base.hyphenate(this._class)
  3557 	},
  3593 	},
  3558 
  3594 
  3559 	statics: {
  3595 	statics: {
  3560 		_getItems: function _getItems(children, match, matrix, param,
  3596 		_getItems: function _getItems(children, match, matrix, param,
  3561 				firstOnly) {
  3597 				firstOnly) {
  3562 			if (!param) {
  3598 			if (!param && typeof match === 'object') {
  3563 				var overlapping = match.overlapping,
  3599 				var overlapping = match.overlapping,
  3564 					inside = match.inside,
  3600 					inside = match.inside,
  3565 					bounds = overlapping || inside,
  3601 					bounds = overlapping || inside,
  3566 					rect =	bounds && Rectangle.read([bounds]);
  3602 					rect =	bounds && Rectangle.read([bounds]);
  3567 				param = {
  3603 				param = {
  3568 					items: [],
  3604 					items: [],
  3569 					inside: rect,
  3605 					inside: !!inside,
  3570 					overlapping: overlapping && new Path.Rectangle({
  3606 					overlapping: !!overlapping,
       
  3607 					rect: rect,
       
  3608 					path: overlapping && new Path.Rectangle({
  3571 						rectangle: rect,
  3609 						rectangle: rect,
  3572 						insert: false
  3610 						insert: false
  3573 					})
  3611 					})
  3574 				};
  3612 				};
  3575 				if (bounds)
  3613 				if (bounds)
  3576 					match = Base.set({}, match,
  3614 					match = Base.set({}, match,
  3577 							{ inside: true, overlapping: true });
  3615 							{ inside: true, overlapping: true });
  3578 			}
  3616 			}
  3579 			var items = param.items,
  3617 			var items = param && param.items,
  3580 				inside = param.inside,
  3618 				rect = param && param.rect;
  3581 				overlapping = param.overlapping;
  3619 			matrix = rect && (matrix || new Matrix());
  3582 			matrix = inside && (matrix || new Matrix());
       
  3583 			for (var i = 0, l = children && children.length; i < l; i++) {
  3620 			for (var i = 0, l = children && children.length; i < l; i++) {
  3584 				var child = children[i],
  3621 				var child = children[i],
  3585 					childMatrix = matrix && matrix.chain(child._matrix),
  3622 					childMatrix = matrix && matrix.chain(child._matrix),
  3586 					add = true;
  3623 					add = true;
  3587 				if (inside) {
  3624 				if (rect) {
  3588 					var bounds = child.getBounds(childMatrix);
  3625 					var bounds = child.getBounds(childMatrix);
  3589 					if (!inside.intersects(bounds))
  3626 					if (!rect.intersects(bounds))
  3590 						continue;
  3627 						continue;
  3591 					if (!(inside && inside.contains(bounds)) && !(overlapping
  3628 					if (!(param.inside && rect.contains(bounds))
  3592 							&& overlapping.intersects(child, childMatrix)))
  3629 							&& !(param.overlapping && (bounds.contains(rect)
       
  3630 								|| param.path.intersects(child, childMatrix))))
  3593 						add = false;
  3631 						add = false;
  3594 				}
  3632 				}
  3595 				if (add && child.matches(match)) {
  3633 				if (add && child.matches(match)) {
  3596 					items.push(child);
  3634 					items.push(child);
  3597 					if (firstOnly)
  3635 					if (firstOnly)
  4064 			direct = normalBlend && opacity === 1
  4102 			direct = normalBlend && opacity === 1
  4065 					|| param.dontStart
  4103 					|| param.dontStart
  4066 					|| param.clip
  4104 					|| param.clip
  4067 					|| (nativeBlend || normalBlend && opacity < 1)
  4105 					|| (nativeBlend || normalBlend && opacity < 1)
  4068 						&& this._canComposite(),
  4106 						&& this._canComposite(),
  4069 			pixelRatio = param.pixelRatio,
  4107 			pixelRatio = param.pixelRatio || 1,
  4070 			mainCtx, itemOffset, prevOffset;
  4108 			mainCtx, itemOffset, prevOffset;
  4071 		if (!direct) {
  4109 		if (!direct) {
  4072 			var bounds = this.getStrokeBounds(getViewMatrix(globalMatrix));
  4110 			var bounds = this.getStrokeBounds(getViewMatrix(globalMatrix));
  4073 			if (!bounds.width || !bounds.height)
  4111 			if (!bounds.width || !bounds.height)
  4074 				return;
  4112 				return;
  4420 	isEmpty: function() {
  4458 	isEmpty: function() {
  4421 		return false;
  4459 		return false;
  4422 	},
  4460 	},
  4423 
  4461 
  4424 	toPath: function(insert) {
  4462 	toPath: function(insert) {
  4425 		var path = new Path[Base.capitalize(this._type)]({
  4463 		var path = this._clone(new Path[Base.capitalize(this._type)]({
  4426 			center: new Point(),
  4464 			center: new Point(),
  4427 			size: this._size,
  4465 			size: this._size,
  4428 			radius: this._radius,
  4466 			radius: this._radius,
  4429 			insert: false
  4467 			insert: false
  4430 		});
  4468 		}), insert);
  4431 		path.setStyle(this._style);
  4469 		if (paper.settings.applyMatrix)
  4432 		path.transform(this._matrix);
  4470 			path.setApplyMatrix(true);
  4433 		if (insert || insert === undefined)
       
  4434 			path.insertAbove(this);
       
  4435 		return path;
  4471 		return path;
  4436 	},
  4472 	},
  4437 
  4473 
  4438 	_draw: function(ctx, param, strokeMatrix) {
  4474 	_draw: function(ctx, param, strokeMatrix) {
  4439 		var style = this._style,
  4475 		var style = this._style,
  4453 				var rx = isCircle ? radius : radius.width,
  4489 				var rx = isCircle ? radius : radius.width,
  4454 					ry = isCircle ? radius : radius.height,
  4490 					ry = isCircle ? radius : radius.height,
  4455 					size = this._size,
  4491 					size = this._size,
  4456 					width = size.width,
  4492 					width = size.width,
  4457 					height = size.height;
  4493 					height = size.height;
  4458 				if (untransformed && type === 'rect' && rx === 0 && ry === 0) {
  4494 				if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
  4459 					ctx.rect(-width / 2, -height / 2, width, height);
  4495 					ctx.rect(-width / 2, -height / 2, width, height);
  4460 				} else {
  4496 				} else {
  4461 					var x = width / 2,
  4497 					var x = width / 2,
  4462 						y = height / 2,
  4498 						y = height / 2,
  4463 						kappa = 1 - 0.5522847498307936,
  4499 						kappa = 1 - 0.5522847498307936,
  4645 	_applyMatrix: false,
  4681 	_applyMatrix: false,
  4646 	_canApplyMatrix: false,
  4682 	_canApplyMatrix: false,
  4647 	_boundsGetter: 'getBounds',
  4683 	_boundsGetter: 'getBounds',
  4648 	_boundsSelected: true,
  4684 	_boundsSelected: true,
  4649 	_serializeFields: {
  4685 	_serializeFields: {
       
  4686 		crossOrigin: null,
  4650 		source: null
  4687 		source: null
  4651 	},
  4688 	},
  4652 
  4689 
  4653 	initialize: function Raster(object, position) {
  4690 	initialize: function Raster(object, position) {
  4654 		if (!this._initialize(object,
  4691 		if (!this._initialize(object,
  4678 		} else if (canvas) {
  4715 		} else if (canvas) {
  4679 			var copyCanvas = CanvasProvider.getCanvas(this._size);
  4716 			var copyCanvas = CanvasProvider.getCanvas(this._size);
  4680 			copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
  4717 			copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
  4681 			copy.setImage(copyCanvas);
  4718 			copy.setImage(copyCanvas);
  4682 		}
  4719 		}
       
  4720 		copy._crossOrigin = this._crossOrigin;
  4683 		return this._clone(copy, insert);
  4721 		return this._clone(copy, insert);
  4684 	},
  4722 	},
  4685 
  4723 
  4686 	getSize: function() {
  4724 	getSize: function() {
  4687 		var size = this._size;
  4725 		var size = this._size;
  4797 		return this._image && this._image.src || this.toDataURL();
  4835 		return this._image && this._image.src || this.toDataURL();
  4798 	},
  4836 	},
  4799 
  4837 
  4800 	setSource: function(src) {
  4838 	setSource: function(src) {
  4801 		var that = this,
  4839 		var that = this,
       
  4840 			crossOrigin = this._crossOrigin,
  4802 			image;
  4841 			image;
  4803 
  4842 
  4804 		function loaded() {
  4843 		function loaded() {
  4805 			var view = that.getView();
  4844 			var view = that.getView();
  4806 			if (view) {
  4845 			if (view) {
  4809 				that.emit('load');
  4848 				that.emit('load');
  4810 				view.update();
  4849 				view.update();
  4811 			}
  4850 			}
  4812 		}
  4851 		}
  4813 
  4852 
  4814 			image = document.getElementById(src) || new Image();
  4853 		image = document.getElementById(src) || new Image();
  4815 
  4854 		if (crossOrigin)
       
  4855 			image.crossOrigin = crossOrigin;
  4816 		if (image.naturalWidth && image.naturalHeight) {
  4856 		if (image.naturalWidth && image.naturalHeight) {
  4817 			setTimeout(loaded, 0);
  4857 			setTimeout(loaded, 0);
  4818 		} else {
  4858 		} else {
  4819 			DomEvent.add(image, {
  4859 			DomEvent.add(image, { load: loaded });
  4820 				load: loaded
       
  4821 			});
       
  4822 			if (!image.src)
  4860 			if (!image.src)
  4823 				image.src = src;
  4861 				image.src = src;
  4824 		}
  4862 		}
  4825 		this.setImage(image);
  4863 		this.setImage(image);
       
  4864 	},
       
  4865 
       
  4866 	getCrossOrigin: function() {
       
  4867 		return this._image && this._image.crossOrigin || this._crossOrigin || '';
       
  4868 	},
       
  4869 
       
  4870 	setCrossOrigin: function(crossOrigin) {
       
  4871 		this._crossOrigin = crossOrigin;
       
  4872 		if (this._image)
       
  4873 			this._image.crossOrigin = crossOrigin;
  4826 	},
  4874 	},
  4827 
  4875 
  4828 	getElement: function() {
  4876 	getElement: function() {
  4829 		return this._canvas || this._loaded && this._image;
  4877 		return this._canvas || this._loaded && this._image;
  4830 	}
  4878 	}
  5107 		new SegmentPoint(handleIn, this, '_handleIn');
  5155 		new SegmentPoint(handleIn, this, '_handleIn');
  5108 		new SegmentPoint(handleOut, this, '_handleOut');
  5156 		new SegmentPoint(handleOut, this, '_handleOut');
  5109 	},
  5157 	},
  5110 
  5158 
  5111 	_serialize: function(options) {
  5159 	_serialize: function(options) {
  5112 		return Base.serialize(this.isLinear() ? this._point
  5160 		return Base.serialize(this.isStraight() ? this._point
  5113 				: [this._point, this._handleIn, this._handleOut],
  5161 				: [this._point, this._handleIn, this._handleOut],
  5114 				options, true);
  5162 				options, true);
  5115 	},
  5163 	},
  5116 
  5164 
  5117 	_changed: function(point) {
  5165 	_changed: function(point) {
  5158 	setHandleOut: function() {
  5206 	setHandleOut: function() {
  5159 		var point = Point.read(arguments);
  5207 		var point = Point.read(arguments);
  5160 		this._handleOut.set(point.x, point.y);
  5208 		this._handleOut.set(point.x, point.y);
  5161 	},
  5209 	},
  5162 
  5210 
       
  5211 	hasHandles: function() {
       
  5212 		return !this.isStraight();
       
  5213 	},
       
  5214 
       
  5215 	isStraight: function() {
       
  5216 		return this._handleIn.isZero() && this._handleOut.isZero();
       
  5217 	},
       
  5218 
  5163 	isLinear: function() {
  5219 	isLinear: function() {
  5164 		return this._handleIn.isZero() && this._handleOut.isZero();
  5220 		return Segment.isLinear(this, this.getNext());
  5165 	},
  5221 	},
  5166 
  5222 
  5167 	setLinear: function(linear) {
  5223 	isCollinear: function(segment) {
  5168 		if (linear) {
  5224 		return Segment.isCollinear(this, this.getNext(),
  5169 			this._handleIn.set(0, 0);
  5225 				segment, segment.getNext());
  5170 			this._handleOut.set(0, 0);
  5226 	},
  5171 		} else {
  5227 
  5172 		}
  5228 	isColinear: '#isCollinear',
  5173 	},
       
  5174 
       
  5175 	isColinear: function(segment) {
       
  5176 		var next1 = this.getNext(),
       
  5177 			next2 = segment.getNext();
       
  5178 		return this._handleOut.isZero() && next1._handleIn.isZero()
       
  5179 				&& segment._handleOut.isZero() && next2._handleIn.isZero()
       
  5180 				&& next1._point.subtract(this._point).isColinear(
       
  5181 					next2._point.subtract(segment._point));
       
  5182 	},
       
  5183 
  5229 
  5184 	isOrthogonal: function() {
  5230 	isOrthogonal: function() {
  5185 		var prev = this.getPrevious(),
  5231 		return Segment.isOrthogonal(this.getPrevious(), this, this.getNext());
  5186 			next = this.getNext();
  5232 	},
  5187 		return prev._handleOut.isZero() && this._handleIn.isZero()
  5233 
  5188 			&& this._handleOut.isZero() && next._handleIn.isZero()
  5234 	isOrthogonalArc: function() {
  5189 			&& this._point.subtract(prev._point).isOrthogonal(
  5235 		return Segment.isOrthogonalArc(this, this.getNext());
  5190 					next._point.subtract(this._point));
  5236 	},
  5191 	},
  5237 
  5192 
  5238 	isArc: '#isOrthogonalArc',
  5193 	isArc: function() {
       
  5194 		var next = this.getNext(),
       
  5195 			handle1 = this._handleOut,
       
  5196 			handle2 = next._handleIn,
       
  5197 			kappa = 0.5522847498307936;
       
  5198 		if (handle1.isOrthogonal(handle2)) {
       
  5199 			var from = this._point,
       
  5200 				to = next._point,
       
  5201 				corner = new Line(from, handle1, true).intersect(
       
  5202 						new Line(to, handle2, true), true);
       
  5203 			return corner && Numerical.isZero(handle1.getLength() /
       
  5204 					corner.subtract(from).getLength() - kappa)
       
  5205 				&& Numerical.isZero(handle2.getLength() /
       
  5206 					corner.subtract(to).getLength() - kappa);
       
  5207 		}
       
  5208 		return false;
       
  5209 	},
       
  5210 
  5239 
  5211 	_selectionState: 0,
  5240 	_selectionState: 0,
  5212 
  5241 
  5213 	isSelected: function(_point) {
  5242 	isSelected: function(_point) {
  5214 		var state = this._selectionState;
  5243 		var state = this._selectionState;
  5359 					coords[i++] = y;
  5388 					coords[i++] = y;
  5360 				}
  5389 				}
  5361 			}
  5390 			}
  5362 		}
  5391 		}
  5363 		return coords;
  5392 		return coords;
       
  5393 	},
       
  5394 
       
  5395    statics: {
       
  5396 
       
  5397 		isLinear: function(seg1, seg2) {
       
  5398 			var l = seg2._point.subtract(seg1._point);
       
  5399 			return l.isCollinear(seg1._handleOut)
       
  5400 					&& l.isCollinear(seg2._handleIn);
       
  5401 		},
       
  5402 
       
  5403 		isCollinear: function(seg1, seg2, seg3, seg4) {
       
  5404 			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
       
  5405 					&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
       
  5406 					&& seg2._point.subtract(seg1._point).isCollinear(
       
  5407 						seg4._point.subtract(seg3._point));
       
  5408 		},
       
  5409 
       
  5410 		isOrthogonal: function(seg1, seg2, seg3) {
       
  5411 			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
       
  5412 				&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
       
  5413 				&& seg2._point.subtract(seg1._point).isOrthogonal(
       
  5414 						seg3._point.subtract(seg2._point));
       
  5415 		},
       
  5416 
       
  5417 		isOrthogonalArc: function(seg1, seg2) {
       
  5418 			var handle1 = seg1._handleOut,
       
  5419 				handle2 = seg2._handleIn,
       
  5420 				kappa = 0.5522847498307936;
       
  5421 			if (handle1.isOrthogonal(handle2)) {
       
  5422 				var pt1 = seg1._point,
       
  5423 					pt2 = seg2._point,
       
  5424 					corner = new Line(pt1, handle1, true).intersect(
       
  5425 							new Line(pt2, handle2, true), true);
       
  5426 				return corner && Numerical.isZero(handle1.getLength() /
       
  5427 						corner.subtract(pt1).getLength() - kappa)
       
  5428 					&& Numerical.isZero(handle2.getLength() /
       
  5429 						corner.subtract(pt2).getLength() - kappa);
       
  5430 			}
       
  5431 			return false;
       
  5432 		},
  5364 	}
  5433 	}
  5365 });
  5434 });
  5366 
  5435 
  5367 var SegmentPoint = Point.extend({
  5436 var SegmentPoint = Point.extend({
  5368 	initialize: function SegmentPoint(point, owner, key) {
  5437 	initialize: function SegmentPoint(point, owner, key) {
  5584 
  5653 
  5585 	getPartLength: function(from, to) {
  5654 	getPartLength: function(from, to) {
  5586 		return Curve.getLength(this.getValues(), from, to);
  5655 		return Curve.getLength(this.getValues(), from, to);
  5587 	},
  5656 	},
  5588 
  5657 
       
  5658 	hasHandles: function() {
       
  5659 		return !this._segment1._handleOut.isZero()
       
  5660 				|| !this._segment2._handleIn.isZero();
       
  5661 	},
       
  5662 
  5589 	isLinear: function() {
  5663 	isLinear: function() {
  5590 		return this._segment1._handleOut.isZero()
  5664 		return Segment.isLinear(this._segment1, this._segment2);
  5591 				&& this._segment2._handleIn.isZero();
  5665 	},
       
  5666 
       
  5667 	isCollinear: function(curve) {
       
  5668 		return Ssegment.isCollinear(this._segment1, this._segment2,
       
  5669 				curve._segment1, curve._segment2);
       
  5670 	},
       
  5671 
       
  5672 	isOrthogonalArc: function() {
       
  5673 		return Segment.isOrthogonalArc(this._segment1, this._segment2);
  5592 	},
  5674 	},
  5593 
  5675 
  5594 	getIntersections: function(curve) {
  5676 	getIntersections: function(curve) {
  5595 		return Curve.filterIntersections(Curve.getIntersections(
  5677 		return Curve.filterIntersections(Curve.getIntersections(
  5596 				this.getValues(), curve.getValues(), this, curve, []));
  5678 				this.getValues(), curve.getValues(), this, curve, []));
  5694 				p2._x, p2._y
  5776 				p2._x, p2._y
  5695 			];
  5777 			];
  5696 		if (matrix)
  5778 		if (matrix)
  5697 			matrix._transformCoordinates(values, values, 4);
  5779 			matrix._transformCoordinates(values, values, 4);
  5698 		return values;
  5780 		return values;
  5699 	},
       
  5700 
       
  5701 	evaluate: function(v, t, type) {
       
  5702 		var p1x = v[0], p1y = v[1],
       
  5703 			c1x = v[2], c1y = v[3],
       
  5704 			c2x = v[4], c2y = v[5],
       
  5705 			p2x = v[6], p2y = v[7],
       
  5706 			tolerance = 0.000001,
       
  5707 			x, y;
       
  5708 
       
  5709 		if (type === 0 && (t < tolerance || t > 1 - tolerance)) {
       
  5710 			var isZero = t < tolerance;
       
  5711 			x = isZero ? p1x : p2x;
       
  5712 			y = isZero ? p1y : p2y;
       
  5713 		} else {
       
  5714 			var cx = 3 * (c1x - p1x),
       
  5715 				bx = 3 * (c2x - c1x) - cx,
       
  5716 				ax = p2x - p1x - cx - bx,
       
  5717 
       
  5718 				cy = 3 * (c1y - p1y),
       
  5719 				by = 3 * (c2y - c1y) - cy,
       
  5720 				ay = p2y - p1y - cy - by;
       
  5721 			if (type === 0) {
       
  5722 				x = ((ax * t + bx) * t + cx) * t + p1x;
       
  5723 				y = ((ay * t + by) * t + cy) * t + p1y;
       
  5724 			} else {
       
  5725 				if (t < tolerance && c1x === p1x && c1y === p1y
       
  5726 						|| t > 1 - tolerance && c2x === p2x && c2y === p2y) {
       
  5727 					x = c2x - c1x;
       
  5728 					y = c2y - c1y;
       
  5729 				} else if (t < tolerance) {
       
  5730 					x = cx;
       
  5731 					y = cy;
       
  5732 				} else if (t > 1 - tolerance) {
       
  5733 					x = 3 * (p2x - c2x);
       
  5734 					y = 3 * (p2y - c2y);
       
  5735 				} else {
       
  5736 					x = (3 * ax * t + 2 * bx) * t + cx;
       
  5737 					y = (3 * ay * t + 2 * by) * t + cy;
       
  5738 				}
       
  5739 				if (type === 3) {
       
  5740 					var x2 = 6 * ax * t + 2 * bx,
       
  5741 						y2 = 6 * ay * t + 2 * by;
       
  5742 					return (x * y2 - y * x2) / Math.pow(x * x + y * y, 3 / 2);
       
  5743 				}
       
  5744 			}
       
  5745 		}
       
  5746 		return type === 2 ? new Point(y, -x) : new Point(x, y);
       
  5747 	},
  5781 	},
  5748 
  5782 
  5749 	subdivide: function(v, t) {
  5783 	subdivide: function(v, t) {
  5750 		var p1x = v[0], p1y = v[1],
  5784 		var p1x = v[0], p1y = v[1],
  5751 			c1x = v[2], c1y = v[3],
  5785 			c1x = v[2], c1y = v[3],
  5771 			c1 = v[coord + 2],
  5805 			c1 = v[coord + 2],
  5772 			c2 = v[coord + 4],
  5806 			c2 = v[coord + 4],
  5773 			p2 = v[coord + 6],
  5807 			p2 = v[coord + 6],
  5774 			c = 3 * (c1 - p1),
  5808 			c = 3 * (c1 - p1),
  5775 			b = 3 * (c2 - c1) - c,
  5809 			b = 3 * (c2 - c1) - c,
  5776 			a = p2 - p1 - c - b,
  5810 			a = p2 - p1 - c - b;
  5777 			isZero = Numerical.isZero;
       
  5778 		if (isZero(a) && isZero(b))
       
  5779 			a = b = 0;
       
  5780 		return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
  5811 		return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
  5781 	},
  5812 	},
  5782 
  5813 
  5783 	getParameterOf: function(v, x, y) {
  5814 	getParameterOf: function(v, x, y) {
  5784 		var tolerance = 0.000001;
  5815 		var tolerance = 0.000001;
  5789 		var txs = [],
  5820 		var txs = [],
  5790 			tys = [],
  5821 			tys = [],
  5791 			sx = Curve.solveCubic(v, 0, x, txs, 0, 1),
  5822 			sx = Curve.solveCubic(v, 0, x, txs, 0, 1),
  5792 			sy = Curve.solveCubic(v, 1, y, tys, 0, 1),
  5823 			sy = Curve.solveCubic(v, 1, y, tys, 0, 1),
  5793 			tx, ty;
  5824 			tx, ty;
  5794 		for (var cx = 0;  sx == -1 || cx < sx;) {
  5825 		for (var cx = 0;  sx === -1 || cx < sx;) {
  5795 			if (sx == -1 || (tx = txs[cx++]) >= 0 && tx <= 1) {
  5826 			if (sx === -1 || (tx = txs[cx++]) > 0 && tx < 1) {
  5796 				for (var cy = 0; sy == -1 || cy < sy;) {
  5827 				for (var cy = 0; sy === -1 || cy < sy;) {
  5797 					if (sy == -1 || (ty = tys[cy++]) >= 0 && ty <= 1) {
  5828 					if (sy === -1 || (ty = tys[cy++]) > 0 && ty < 1) {
  5798 						if (sx == -1) tx = ty;
  5829 						if (sx === -1) {
  5799 						else if (sy == -1) ty = tx;
  5830 							tx = ty;
       
  5831 						} else if (sy === -1) {
       
  5832 							ty = tx;
       
  5833 						}
  5800 						if (Math.abs(tx - ty) < tolerance)
  5834 						if (Math.abs(tx - ty) < tolerance)
  5801 							return (tx + ty) * 0.5;
  5835 							return (tx + ty) * 0.5;
  5802 					}
  5836 					}
  5803 				}
  5837 				}
  5804 				if (sx == -1)
  5838 				if (sx === -1)
  5805 					break;
  5839 					break;
  5806 			}
  5840 			}
  5807 		}
  5841 		}
  5808 		return null;
  5842 		return null;
  5809 	},
  5843 	},
  5814 		if (to < 1)
  5848 		if (to < 1)
  5815 			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
  5849 			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
  5816 		return v;
  5850 		return v;
  5817 	},
  5851 	},
  5818 
  5852 
       
  5853 	hasHandles: function(v) {
       
  5854 		var isZero = Numerical.isZero;
       
  5855 		return !(isZero(v[0] - v[2]) && isZero(v[1] - v[3])
       
  5856 				&& isZero(v[4] - v[6]) && isZero(v[5] - v[7]));
       
  5857 	},
       
  5858 
  5819 	isLinear: function(v) {
  5859 	isLinear: function(v) {
  5820 		var isZero = Numerical.isZero;
  5860 		var p1x = v[0], p1y = v[1],
  5821 		return isZero(v[0] - v[2]) && isZero(v[1] - v[3])
  5861 			p2x = v[6], p2y = v[7],
  5822 				&& isZero(v[4] - v[6]) && isZero(v[5] - v[7]);
  5862 			l = new Point(p2x - p1x, p2y - p1y);
       
  5863 		return l.isCollinear(new Point(v[2] - p1x, v[3] - p1y))
       
  5864 				&& l.isCollinear(new Point(v[4] - p2x, v[5] - p2y));
  5823 	},
  5865 	},
  5824 
  5866 
  5825 	isFlatEnough: function(v, tolerance) {
  5867 	isFlatEnough: function(v, tolerance) {
  5826 		var p1x = v[0], p1y = v[1],
  5868 		var p1x = v[0], p1y = v[1],
  5827 			c1x = v[2], c1y = v[3],
  5869 			c1x = v[2], c1y = v[3],
  5889 					+ 3 * u * t * t * v2
  5931 					+ 3 * u * t * t * v2
  5890 					+ t * t * t * v3,
  5932 					+ t * t * t * v3,
  5891 					padding);
  5933 					padding);
  5892 		}
  5934 		}
  5893 	}
  5935 	}
  5894 }}, Base.each(['getBounds', 'getStrokeBounds', 'getHandleBounds', 'getRoughBounds'],
  5936 }}, Base.each(
       
  5937 	['getBounds', 'getStrokeBounds', 'getHandleBounds', 'getRoughBounds'],
  5895 	function(name) {
  5938 	function(name) {
  5896 		this[name] = function() {
  5939 		this[name] = function() {
  5897 			if (!this._bounds)
  5940 			if (!this._bounds)
  5898 				this._bounds = {};
  5941 				this._bounds = {};
  5899 			var bounds = this._bounds[name];
  5942 			var bounds = this._bounds[name];
  5904 			return bounds.clone();
  5947 			return bounds.clone();
  5905 		};
  5948 		};
  5906 	},
  5949 	},
  5907 {
  5950 {
  5908 
  5951 
  5909 }), Base.each(['getPoint', 'getTangent', 'getNormal', 'getCurvature'],
  5952 }), {
  5910 	function(name, index) {
       
  5911 		this[name + 'At'] = function(offset, isParameter) {
       
  5912 			var values = this.getValues();
       
  5913 			return Curve.evaluate(values, isParameter
       
  5914 					? offset : Curve.getParameterAt(values, offset, 0), index);
       
  5915 		};
       
  5916 		this[name] = function(parameter) {
       
  5917 			return Curve.evaluate(this.getValues(), parameter, index);
       
  5918 		};
       
  5919 	},
       
  5920 {
       
  5921 	beans: false,
  5953 	beans: false,
  5922 
  5954 
  5923 	getParameterAt: function(offset, start) {
  5955 	getParameterAt: function(offset, start) {
  5924 		return Curve.getParameterAt(this.getValues(), offset, start);
  5956 		return Curve.getParameterAt(this.getValues(), offset, start);
  5925 	},
  5957 	},
  5928 		var point = Point.read(arguments);
  5960 		var point = Point.read(arguments);
  5929 		return Curve.getParameterOf(this.getValues(), point.x, point.y);
  5961 		return Curve.getParameterOf(this.getValues(), point.x, point.y);
  5930 	},
  5962 	},
  5931 
  5963 
  5932 	getLocationAt: function(offset, isParameter) {
  5964 	getLocationAt: function(offset, isParameter) {
  5933 		if (!isParameter)
  5965 		var t = isParameter ? offset : this.getParameterAt(offset);
  5934 			offset = this.getParameterAt(offset);
  5966 		return t != null && t >= 0 && t <= 1
  5935 		return offset >= 0 && offset <= 1 && new CurveLocation(this, offset);
  5967 				? new CurveLocation(this, t)
       
  5968 				: null;
  5936 	},
  5969 	},
  5937 
  5970 
  5938 	getLocationOf: function() {
  5971 	getLocationOf: function() {
  5939 		return this.getLocationAt(this.getParameterOf(Point.read(arguments)),
  5972 		return this.getLocationAt(this.getParameterOf(Point.read(arguments)),
  5940 				true);
  5973 				true);
  5952 			minDist = Infinity,
  5985 			minDist = Infinity,
  5953 			minT = 0;
  5986 			minT = 0;
  5954 
  5987 
  5955 		function refine(t) {
  5988 		function refine(t) {
  5956 			if (t >= 0 && t <= 1) {
  5989 			if (t >= 0 && t <= 1) {
  5957 				var dist = point.getDistance(
  5990 				var dist = point.getDistance(Curve.getPoint(values, t), true);
  5958 						Curve.evaluate(values, t, 0), true);
       
  5959 				if (dist < minDist) {
  5991 				if (dist < minDist) {
  5960 					minDist = dist;
  5992 					minDist = dist;
  5961 					minT = t;
  5993 					minT = t;
  5962 					return true;
  5994 					return true;
  5963 				}
  5995 				}
  5970 		var step = 1 / (count * 2);
  6002 		var step = 1 / (count * 2);
  5971 		while (step > 0.000001) {
  6003 		while (step > 0.000001) {
  5972 			if (!refine(minT - step) && !refine(minT + step))
  6004 			if (!refine(minT - step) && !refine(minT + step))
  5973 				step /= 2;
  6005 				step /= 2;
  5974 		}
  6006 		}
  5975 		var pt = Curve.evaluate(values, minT, 0);
  6007 		var pt = Curve.getPoint(values, minT);
  5976 		return new CurveLocation(this, minT, pt, null, null, null,
  6008 		return new CurveLocation(this, minT, pt, null, null, null,
  5977 				point.getDistance(pt));
  6009 				point.getDistance(pt));
  5978 	},
  6010 	},
  5979 
  6011 
  5980 	getNearestPoint: function() {
  6012 	getNearestPoint: function() {
  5981 		return this.getNearestLocation.apply(this, arguments).getPoint();
  6013 		return this.getNearestLocation.apply(this, arguments).getPoint();
  5982 	}
  6014 	}
  5983 
  6015 
  5984 }),
  6016 },
       
  6017 new function() {
       
  6018 	var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
       
  6019 		'getWeightedNormal', 'getCurvature'];
       
  6020 	return Base.each(methods,
       
  6021 	function(name) {
       
  6022 		this[name + 'At'] = function(offset, isParameter) {
       
  6023 			var values = this.getValues();
       
  6024 			return Curve[name](values, isParameter ? offset
       
  6025 					: Curve.getParameterAt(values, offset, 0));
       
  6026 		};
       
  6027 	}, {
       
  6028 		statics: {
       
  6029 			evaluateMethods: methods
       
  6030 		}
       
  6031 	})
       
  6032 },
  5985 new function() {
  6033 new function() {
  5986 
  6034 
  5987 	function getLengthIntegrand(v) {
  6035 	function getLengthIntegrand(v) {
  5988 		var p1x = v[0], p1y = v[1],
  6036 		var p1x = v[0], p1y = v[1],
  5989 			c1x = v[2], c1y = v[3],
  6037 			c1x = v[2], c1y = v[3],
  6005 		};
  6053 		};
  6006 	}
  6054 	}
  6007 
  6055 
  6008 	function getIterations(a, b) {
  6056 	function getIterations(a, b) {
  6009 		return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
  6057 		return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
       
  6058 	}
       
  6059 
       
  6060 	function evaluate(v, t, type, normalized) {
       
  6061 		if (t == null || t < 0 || t > 1)
       
  6062 			return null;
       
  6063 		var p1x = v[0], p1y = v[1],
       
  6064 			c1x = v[2], c1y = v[3],
       
  6065 			c2x = v[4], c2y = v[5],
       
  6066 			p2x = v[6], p2y = v[7],
       
  6067 			tolerance = 0.000001,
       
  6068 			x, y;
       
  6069 
       
  6070 		if (type === 0 && (t < tolerance || t > 1 - tolerance)) {
       
  6071 			var isZero = t < tolerance;
       
  6072 			x = isZero ? p1x : p2x;
       
  6073 			y = isZero ? p1y : p2y;
       
  6074 		} else {
       
  6075 			var cx = 3 * (c1x - p1x),
       
  6076 				bx = 3 * (c2x - c1x) - cx,
       
  6077 				ax = p2x - p1x - cx - bx,
       
  6078 
       
  6079 				cy = 3 * (c1y - p1y),
       
  6080 				by = 3 * (c2y - c1y) - cy,
       
  6081 				ay = p2y - p1y - cy - by;
       
  6082 			if (type === 0) {
       
  6083 				x = ((ax * t + bx) * t + cx) * t + p1x;
       
  6084 				y = ((ay * t + by) * t + cy) * t + p1y;
       
  6085 			} else {
       
  6086 				if (t < tolerance) {
       
  6087 					x = cx;
       
  6088 					y = cy;
       
  6089 				} else if (t > 1 - tolerance) {
       
  6090 					x = 3 * (p2x - c2x);
       
  6091 					y = 3 * (p2y - c2y);
       
  6092 				} else {
       
  6093 					x = (3 * ax * t + 2 * bx) * t + cx;
       
  6094 					y = (3 * ay * t + 2 * by) * t + cy;
       
  6095 				}
       
  6096 				if (normalized) {
       
  6097 					if (x === 0 && y === 0
       
  6098 							&& (t < tolerance || t > 1 - tolerance)) {
       
  6099 						x = c2x - c1x;
       
  6100 						y = c2y - c1y;
       
  6101 					}
       
  6102 					var len = Math.sqrt(x * x + y * y);
       
  6103 					x /= len;
       
  6104 					y /= len;
       
  6105 				}
       
  6106 				if (type === 3) {
       
  6107 					var x2 = 6 * ax * t + 2 * bx,
       
  6108 						y2 = 6 * ay * t + 2 * by,
       
  6109 						d = Math.pow(x * x + y * y, 3 / 2);
       
  6110 					x = d !== 0 ? (x * y2 - y * x2) / d : 0;
       
  6111 					y = 0;
       
  6112 				}
       
  6113 			}
       
  6114 		}
       
  6115 		return type === 2 ? new Point(y, -x) : new Point(x, y);
  6010 	}
  6116 	}
  6011 
  6117 
  6012 	return {
  6118 	return {
  6013 		statics: true,
  6119 		statics: true,
  6014 
  6120 
  6032 		getParameterAt: function(v, offset, start) {
  6138 		getParameterAt: function(v, offset, start) {
  6033 			if (start === undefined)
  6139 			if (start === undefined)
  6034 				start = offset < 0 ? 1 : 0
  6140 				start = offset < 0 ? 1 : 0
  6035 			if (offset === 0)
  6141 			if (offset === 0)
  6036 				return start;
  6142 				return start;
  6037 			var forward = offset > 0,
  6143 			var tolerance = 0.000001,
       
  6144 				abs = Math.abs,
       
  6145 				forward = offset > 0,
  6038 				a = forward ? start : 0,
  6146 				a = forward ? start : 0,
  6039 				b = forward ? 1 : start,
  6147 				b = forward ? 1 : start,
  6040 				ds = getLengthIntegrand(v),
  6148 				ds = getLengthIntegrand(v),
  6041 				rangeLength = Numerical.integrate(ds, a, b,
  6149 				rangeLength = Numerical.integrate(ds, a, b,
  6042 						getIterations(a, b));
  6150 						getIterations(a, b));
  6043 			if (Math.abs(offset) >= rangeLength)
  6151 			if (abs(offset - rangeLength) < tolerance) {
  6044 				return forward ? b : a;
  6152 				return forward ? b : a;
       
  6153 			} else if (abs(offset) > rangeLength) {
       
  6154 				return null;
       
  6155 			}
  6045 			var guess = offset / rangeLength,
  6156 			var guess = offset / rangeLength,
  6046 				length = 0;
  6157 				length = 0;
  6047 			function f(t) {
  6158 			function f(t) {
  6048 				length += Numerical.integrate(ds, start, t,
  6159 				length += Numerical.integrate(ds, start, t,
  6049 						getIterations(start, t));
  6160 						getIterations(start, t));
  6050 				start = t;
  6161 				start = t;
  6051 				return length - offset;
  6162 				return length - offset;
  6052 			}
  6163 			}
  6053 			return Numerical.findRoot(f, ds, start + guess, a, b, 16,
  6164 			return Numerical.findRoot(f, ds, start + guess, a, b, 16,
  6054 					0.000001);
  6165 					tolerance);
       
  6166 		},
       
  6167 
       
  6168 		getPoint: function(v, t) {
       
  6169 			return evaluate(v, t, 0, false);
       
  6170 		},
       
  6171 
       
  6172 		getTangent: function(v, t) {
       
  6173 			return evaluate(v, t, 1, true);
       
  6174 		},
       
  6175 
       
  6176 		getWeightedTangent: function(v, t) {
       
  6177 			return evaluate(v, t, 1, false);
       
  6178 		},
       
  6179 
       
  6180 		getNormal: function(v, t) {
       
  6181 			return evaluate(v, t, 2, true);
       
  6182 		},
       
  6183 
       
  6184 		getWeightedNormal: function(v, t) {
       
  6185 			return evaluate(v, t, 2, false);
       
  6186 		},
       
  6187 
       
  6188 		getCurvature: function(v, t) {
       
  6189 			return evaluate(v, t, 3, false).x;
  6055 		}
  6190 		}
  6056 	};
  6191 	};
  6057 }, new function() {
  6192 }, new function() {
  6058 	function addLocation(locations, include, curve1, t1, point1, curve2, t2,
  6193 	function addLocation(locations, include, curve1, t1, point1, curve2, t2,
  6059 			point2) {
  6194 			point2) {
  6077 			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
  6212 			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
  6078 			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
  6213 			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
  6079 			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
  6214 			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
  6080 			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
  6215 			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
  6081 			tMinNew, tMaxNew, tDiff;
  6216 			tMinNew, tMaxNew, tDiff;
  6082 		if (q0x === q3x && uMax - uMin <= tolerance && recursion > 3) {
  6217 		if (q0x === q3x && uMax - uMin < tolerance && recursion > 3) {
  6083 			tMaxNew = tMinNew = (tMax + tMin) / 2;
  6218 			tMaxNew = tMinNew = (tMax + tMin) / 2;
  6084 			tDiff = 0;
  6219 			tDiff = 0;
  6085 		} else {
  6220 		} else {
  6086 			var hull = getConvexHull(dp0, dp1, dp2, dp3),
  6221 			var hull = getConvexHull(dp0, dp1, dp2, dp3),
  6087 				top = hull[0],
  6222 				top = hull[0],
  6121 		} else if (Math.max(uMax - uMin, tMaxNew - tMinNew) < tolerance) {
  6256 		} else if (Math.max(uMax - uMin, tMaxNew - tMinNew) < tolerance) {
  6122 			var t1 = tMinNew + (tMaxNew - tMinNew) / 2,
  6257 			var t1 = tMinNew + (tMaxNew - tMinNew) / 2,
  6123 				t2 = uMin + (uMax - uMin) / 2;
  6258 				t2 = uMin + (uMax - uMin) / 2;
  6124 			if (reverse) {
  6259 			if (reverse) {
  6125 				addLocation(locations, include,
  6260 				addLocation(locations, include,
  6126 						curve2, t2, Curve.evaluate(v2, t2, 0),
  6261 						curve2, t2, Curve.getPoint(v2, t2),
  6127 						curve1, t1, Curve.evaluate(v1, t1, 0));
  6262 						curve1, t1, Curve.getPoint(v1, t1));
  6128 			} else {
  6263 			} else {
  6129 				addLocation(locations, include,
  6264 				addLocation(locations, include,
  6130 						curve1, t1, Curve.evaluate(v1, t1, 0),
  6265 						curve1, t1, Curve.getPoint(v1, t1),
  6131 						curve2, t2, Curve.evaluate(v2, t2, 0));
  6266 						curve2, t2, Curve.getPoint(v2, t2));
  6132 			}
  6267 			}
  6133 		} else if (tDiff > 0) {
  6268 		} else if (tDiff > 0) {
  6134 			addCurveIntersections(v2, v1, curve2, curve1, locations, include,
  6269 			addCurveIntersections(v2, v1, curve2, curve1, locations, include,
  6135 					uMin, uMax, tMinNew, tMaxNew, tDiff, !reverse, ++recursion);
  6270 					uMin, uMax, tMinNew, tMaxNew, tDiff, !reverse, ++recursion);
  6136 		}
  6271 		}
  6217 		}
  6352 		}
  6218 		var roots = [],
  6353 		var roots = [],
  6219 			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
  6354 			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
  6220 		for (var i = 0; i < count; i++) {
  6355 		for (var i = 0; i < count; i++) {
  6221 			var tc = roots[i],
  6356 			var tc = roots[i],
  6222 				x = Curve.evaluate(rvc, tc, 0).x;
  6357 				x = Curve.getPoint(rvc, tc).x;
  6223 			if (x >= 0 && x <= rlx2) {
  6358 			if (x >= 0 && x <= rlx2) {
  6224 				var tl = Curve.getParameterOf(rvl, x, 0),
  6359 				var tl = Curve.getParameterOf(rvl, x, 0),
  6225 					t1 = flip ? tl : tc,
  6360 					t1 = flip ? tl : tc,
  6226 					t2 = flip ? tc : tl;
  6361 					t2 = flip ? tc : tl;
  6227 				addLocation(locations, include,
  6362 				addLocation(locations, include,
  6228 						curve1, t1, Curve.evaluate(v1, t1, 0),
  6363 						curve1, t1, Curve.getPoint(v1, t1),
  6229 						curve2, t2, Curve.evaluate(v2, t2, 0));
  6364 						curve2, t2, Curve.getPoint(v2, t2));
  6230 			}
  6365 			}
  6231 		}
  6366 		}
  6232 	}
  6367 	}
  6233 
  6368 
  6234 	function addLineIntersection(v1, v2, curve1, curve2, locations, include) {
  6369 	function addLineIntersection(v1, v2, curve1, curve2, locations, include) {
  6320 	_class: 'CurveLocation',
  6455 	_class: 'CurveLocation',
  6321 	beans: true,
  6456 	beans: true,
  6322 
  6457 
  6323 	initialize: function CurveLocation(curve, parameter, point, _curve2,
  6458 	initialize: function CurveLocation(curve, parameter, point, _curve2,
  6324 			_parameter2, _point2, _distance) {
  6459 			_parameter2, _point2, _distance) {
  6325 		this._id = CurveLocation._id = (CurveLocation._id || 0) + 1;
  6460 		this._id = UID.get(CurveLocation);
       
  6461 		var path = curve._path;
       
  6462 		this._version = path ? path._version : 0;
  6326 		this._curve = curve;
  6463 		this._curve = curve;
  6327 		this._segment1 = curve._segment1;
       
  6328 		this._segment2 = curve._segment2;
       
  6329 		this._parameter = parameter;
  6464 		this._parameter = parameter;
  6330 		this._point = point;
  6465 		this._point = point || curve.getPointAt(parameter, true);
  6331 		this._curve2 = _curve2;
  6466 		this._curve2 = _curve2;
  6332 		this._parameter2 = _parameter2;
  6467 		this._parameter2 = _parameter2;
  6333 		this._point2 = _point2;
  6468 		this._point2 = _point2;
  6334 		this._distance = _distance;
  6469 		this._distance = _distance;
       
  6470 		this._segment1 = curve._segment1;
       
  6471 		this._segment2 = curve._segment2;
  6335 	},
  6472 	},
  6336 
  6473 
  6337 	getSegment: function(_preferFirst) {
  6474 	getSegment: function(_preferFirst) {
  6338 		if (!this._segment) {
  6475 		if (!this._segment) {
  6339 			var curve = this.getCurve(),
  6476 			var curve = this.getCurve(),
  6352 			}
  6489 			}
  6353 		}
  6490 		}
  6354 		return this._segment;
  6491 		return this._segment;
  6355 	},
  6492 	},
  6356 
  6493 
  6357 	getCurve: function(_uncached) {
  6494 	getCurve: function() {
  6358 		if (!this._curve || _uncached) {
  6495 		var curve = this._curve,
  6359 			this._curve = this._segment1.getCurve();
  6496 			path = curve && curve._path;
  6360 			if (this._curve.getParameterOf(this._point) == null)
  6497 		if (path && path._version !== this._version) {
  6361 				this._curve = this._segment2.getPrevious().getCurve();
  6498 			curve = null;
  6362 		}
  6499 			this._parameter = null;
  6363 		return this._curve;
  6500 		}
  6364 	},
  6501 		if (!curve) {
  6365 
  6502 			curve = this._segment1.getCurve();
  6366 	getIntersection: function() {
  6503 			if (curve.getParameterOf(this._point) == null)
  6367 		var intersection = this._intersection;
  6504 				curve = this._segment2.getPrevious().getCurve();
  6368 		if (!intersection && this._curve2) {
  6505 			this._curve = curve;
  6369 			var param = this._parameter2;
  6506 			path = curve._path;
  6370 			this._intersection = intersection = new CurveLocation(
  6507 			this._version = path ? path._version : 0;
  6371 					this._curve2, param, this._point2 || this._point, this);
  6508 		}
  6372 			intersection._intersection = this;
  6509 		return curve;
  6373 		}
       
  6374 		return intersection;
       
  6375 	},
  6510 	},
  6376 
  6511 
  6377 	getPath: function() {
  6512 	getPath: function() {
  6378 		var curve = this.getCurve();
  6513 		var curve = this.getCurve();
  6379 		return curve && curve._path;
  6514 		return curve && curve._path;
  6380 	},
  6515 	},
  6381 
  6516 
  6382 	getIndex: function() {
  6517 	getIndex: function() {
  6383 		var curve = this.getCurve();
  6518 		var curve = this.getCurve();
  6384 		return curve && curve.getIndex();
  6519 		return curve && curve.getIndex();
       
  6520 	},
       
  6521 
       
  6522 	getParameter: function() {
       
  6523 		var curve = this.getCurve(),
       
  6524 			parameter = this._parameter;
       
  6525 		return curve && parameter == null
       
  6526 			? this._parameter = curve.getParameterOf(this._point)
       
  6527 			: parameter;
       
  6528 	},
       
  6529 
       
  6530 	getPoint: function() {
       
  6531 		return this._point;
  6385 	},
  6532 	},
  6386 
  6533 
  6387 	getOffset: function() {
  6534 	getOffset: function() {
  6388 		var path = this.getPath();
  6535 		var path = this.getPath();
  6389 		return path ? path._getOffset(this) : this.getCurveOffset();
  6536 		return path ? path._getOffset(this) : this.getCurveOffset();
  6393 		var curve = this.getCurve(),
  6540 		var curve = this.getCurve(),
  6394 			parameter = this.getParameter();
  6541 			parameter = this.getParameter();
  6395 		return parameter != null && curve && curve.getPartLength(0, parameter);
  6542 		return parameter != null && curve && curve.getPartLength(0, parameter);
  6396 	},
  6543 	},
  6397 
  6544 
  6398 	getParameter: function(_uncached) {
  6545 	getIntersection: function() {
  6399 		if ((this._parameter == null || _uncached) && this._point) {
  6546 		var intersection = this._intersection;
  6400 			var curve = this.getCurve(_uncached);
  6547 		if (!intersection && this._curve2) {
  6401 			this._parameter = curve && curve.getParameterOf(this._point);
  6548 			this._intersection = intersection = new CurveLocation(this._curve2,
  6402 		}
  6549 					this._parameter2, this._point2 || this._point, this);
  6403 		return this._parameter;
  6550 			intersection._intersection = this;
  6404 	},
  6551 		}
  6405 
  6552 		return intersection;
  6406 	getPoint: function(_uncached) {
       
  6407 		if ((!this._point || _uncached) && this._parameter != null) {
       
  6408 			var curve = this.getCurve(_uncached);
       
  6409 			this._point = curve && curve.getPointAt(this._parameter, true);
       
  6410 		}
       
  6411 		return this._point;
       
  6412 	},
  6553 	},
  6413 
  6554 
  6414 	getDistance: function() {
  6555 	getDistance: function() {
  6415 		return this._distance;
  6556 		return this._distance;
  6416 	},
  6557 	},
  6417 
  6558 
  6418 	divide: function() {
  6559 	divide: function() {
  6419 		var curve = this.getCurve(true);
  6560 		var curve = this.getCurve();
  6420 		return curve && curve.divide(this.getParameter(true), true);
  6561 		return curve && curve.divide(this.getParameter(), true);
  6421 	},
  6562 	},
  6422 
  6563 
  6423 	split: function() {
  6564 	split: function() {
  6424 		var curve = this.getCurve(true);
  6565 		var curve = this.getCurve();
  6425 		return curve && curve.split(this.getParameter(true), true);
  6566 		return curve && curve.split(this.getParameter(), true);
  6426 	},
  6567 	},
  6427 
  6568 
  6428 	equals: function(loc) {
  6569 	equals: function(loc) {
  6429 		var abs = Math.abs,
  6570 		var abs = Math.abs,
  6430 			tolerance = 0.000001;
  6571 			tolerance = 0.000001;
  6431 		return this === loc
  6572 		return this === loc
  6432 				|| loc
  6573 				|| loc instanceof CurveLocation
  6433 					&& this._curve === loc._curve
  6574 					&& this.getCurve() === loc.getCurve()
       
  6575 					&& abs(this.getParameter() - loc.getParameter()) < tolerance
  6434 					&& this._curve2 === loc._curve2
  6576 					&& this._curve2 === loc._curve2
  6435 					&& abs(this._parameter - loc._parameter) <= tolerance
  6577 					&& abs(this._parameter2 - loc._parameter2) < tolerance
  6436 					&& abs(this._parameter2 - loc._parameter2) <= tolerance
       
  6437 				|| false;
  6578 				|| false;
  6438 	},
  6579 	},
  6439 
  6580 
  6440 	toString: function() {
  6581 	toString: function() {
  6441 		var parts = [],
  6582 		var parts = [],
  6451 			parts.push('parameter: ' + f.number(parameter));
  6592 			parts.push('parameter: ' + f.number(parameter));
  6452 		if (this._distance != null)
  6593 		if (this._distance != null)
  6453 			parts.push('distance: ' + f.number(this._distance));
  6594 			parts.push('distance: ' + f.number(this._distance));
  6454 		return '{ ' + parts.join(', ') + ' }';
  6595 		return '{ ' + parts.join(', ') + ' }';
  6455 	}
  6596 	}
  6456 }, Base.each(['getTangent', 'getNormal', 'getCurvature'], function(name) {
  6597 }, Base.each(Curve.evaluateMethods, function(name) {
  6457 	var get = name + 'At';
  6598 	if (name !== 'getPoint') {
  6458 	this[name] = function() {
  6599 		var get = name + 'At';
  6459 		var parameter = this.getParameter(),
  6600 		this[name] = function() {
  6460 			curve = this.getCurve();
  6601 			var parameter = this.getParameter(),
  6461 		return parameter != null && curve && curve[get](parameter, true);
  6602 				curve = this.getCurve();
  6462 	};
  6603 			return parameter != null && curve && curve[get](parameter, true);
       
  6604 		};
       
  6605 	}
  6463 }, {}));
  6606 }, {}));
  6464 
  6607 
  6465 var PathItem = Item.extend({
  6608 var PathItem = Item.extend({
  6466 	_class: 'PathItem',
  6609 	_class: 'PathItem',
  6467 
  6610 
  6565 				this.moveTo(current = start);
  6708 				this.moveTo(current = start);
  6566 			switch (lower) {
  6709 			switch (lower) {
  6567 			case 'm':
  6710 			case 'm':
  6568 			case 'l':
  6711 			case 'l':
  6569 				var move = lower === 'm';
  6712 				var move = lower === 'm';
  6570 				if (move && previous && previous !== 'z')
       
  6571 					this.closePath(true);
       
  6572 				for (var j = 0; j < length; j += 2)
  6713 				for (var j = 0; j < length; j += 2)
  6573 					this[j === 0 && move ? 'moveTo' : 'lineTo'](
  6714 					this[j === 0 && move ? 'moveTo' : 'lineTo'](
  6574 							current = getPoint(j));
  6715 							current = getPoint(j));
  6575 				control = current;
  6716 				control = current;
  6576 				if (move)
  6717 				if (move)
  6655 	},
  6796 	},
  6656 
  6797 
  6657 	initialize: function Path(arg) {
  6798 	initialize: function Path(arg) {
  6658 		this._closed = false;
  6799 		this._closed = false;
  6659 		this._segments = [];
  6800 		this._segments = [];
       
  6801 		this._version = 0;
  6660 		var segments = Array.isArray(arg)
  6802 		var segments = Array.isArray(arg)
  6661 			? typeof arg[0] === 'object'
  6803 			? typeof arg[0] === 'object'
  6662 				? arg
  6804 				? arg
  6663 				: arguments
  6805 				: arguments
  6664 			: arg && (arg.size === undefined && (arg.x !== undefined
  6806 			: arg && (arg.size === undefined && (arg.x !== undefined
  6697 		if (flags & 8) {
  6839 		if (flags & 8) {
  6698 			var parent = this._parent;
  6840 			var parent = this._parent;
  6699 			if (parent)
  6841 			if (parent)
  6700 				parent._currentPath = undefined;
  6842 				parent._currentPath = undefined;
  6701 			this._length = this._clockwise = undefined;
  6843 			this._length = this._clockwise = undefined;
  6702 			if (this._curves && !(flags & 16)) {
  6844 			if (flags & 16) {
  6703 				for (var i = 0, l = this._curves.length; i < l; i++)
  6845 				this._version++;
       
  6846 			} else if (this._curves) {
       
  6847 			   for (var i = 0, l = this._curves.length; i < l; i++)
  6704 					this._curves[i]._changed();
  6848 					this._curves[i]._changed();
  6705 			}
  6849 			}
  6706 			this._monoCurves = undefined;
  6850 			this._monoCurves = undefined;
  6707 		} else if (flags & 32) {
  6851 		} else if (flags & 32) {
  6708 			this._bounds = undefined;
  6852 			this._bounds = undefined;
  6831 
  6975 
  6832 	isEmpty: function() {
  6976 	isEmpty: function() {
  6833 		return this._segments.length === 0;
  6977 		return this._segments.length === 0;
  6834 	},
  6978 	},
  6835 
  6979 
  6836 	isPolygon: function() {
  6980 	isLinear: function() {
  6837 		for (var i = 0, l = this._segments.length; i < l; i++) {
  6981 		var segments = this._segments;
  6838 			if (!this._segments[i].isLinear())
  6982 		for (var i = 0, l = segments.length; i < l; i++) {
       
  6983 			if (!segments[i].isLinear())
  6839 				return false;
  6984 				return false;
  6840 		}
  6985 		}
  6841 		return true;
  6986 		return true;
       
  6987 	},
       
  6988 
       
  6989 	hasHandles: function() {
       
  6990 		var segments = this._segments;
       
  6991 		for (var i = 0, l = segments.length; i < l; i++) {
       
  6992 			if (segments[i].hasHandles())
       
  6993 				return true;
       
  6994 		}
       
  6995 		return false;
  6842 	},
  6996 	},
  6843 
  6997 
  6844 	_transformContent: function(matrix) {
  6998 	_transformContent: function(matrix) {
  6845 		var coords = new Array(6);
  6999 		var coords = new Array(6);
  6846 		for (var i = 0, l = this._segments.length; i < l; i++)
  7000 		for (var i = 0, l = this._segments.length; i < l; i++)
  7037 			pos = 0,
  7191 			pos = 0,
  7038 			step = iterator.length / Math.ceil(iterator.length / maxDistance),
  7192 			step = iterator.length / Math.ceil(iterator.length / maxDistance),
  7039 			end = iterator.length + (this._closed ? -step : step) / 2;
  7193 			end = iterator.length + (this._closed ? -step : step) / 2;
  7040 		var segments = [];
  7194 		var segments = [];
  7041 		while (pos <= end) {
  7195 		while (pos <= end) {
  7042 			segments.push(new Segment(iterator.evaluate(pos, 0)));
  7196 			segments.push(new Segment(iterator.getPointAt(pos)));
  7043 			pos += step;
  7197 			pos += step;
  7044 		}
  7198 		}
  7045 		this.setSegments(segments);
  7199 		this.setSegments(segments);
  7046 	},
  7200 	},
  7047 
  7201 
  7173 			type,
  7327 			type,
  7174 			size,
  7328 			size,
  7175 			radius,
  7329 			radius,
  7176 			topCenter;
  7330 			topCenter;
  7177 
  7331 
  7178 		function isColinear(i, j) {
  7332 		function isCollinear(i, j) {
  7179 			return segments[i].isColinear(segments[j]);
  7333 			return segments[i].isCollinear(segments[j]);
  7180 		}
  7334 		}
  7181 
  7335 
  7182 		function isOrthogonal(i) {
  7336 		function isOrthogonal(i) {
  7183 			return segments[i].isOrthogonal();
  7337 			return segments[i].isOrthogonal();
  7184 		}
  7338 		}
  7185 
  7339 
  7186 		function isArc(i) {
  7340 		function isArc(i) {
  7187 			return segments[i].isArc();
  7341 			return segments[i].isOrthogonalArc();
  7188 		}
  7342 		}
  7189 
  7343 
  7190 		function getDistance(i, j) {
  7344 		function getDistance(i, j) {
  7191 			return segments[i]._point.getDistance(segments[j]._point);
  7345 			return segments[i]._point.getDistance(segments[j]._point);
  7192 		}
  7346 		}
  7193 
  7347 
  7194 		if (this.isPolygon() && segments.length === 4
  7348 		if (!this.hasHandles() && segments.length === 4
  7195 				&& isColinear(0, 2) && isColinear(1, 3) && isOrthogonal(1)) {
  7349 				&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {
  7196 			type = Shape.Rectangle;
  7350 			type = Shape.Rectangle;
  7197 			size = new Size(getDistance(0, 3), getDistance(0, 1));
  7351 			size = new Size(getDistance(0, 3), getDistance(0, 1));
  7198 			topCenter = segments[1]._point.add(segments[2]._point).divide(2);
  7352 			topCenter = segments[1]._point.add(segments[2]._point).divide(2);
  7199 		} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
  7353 		} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
  7200 				&& isArc(6) && isColinear(1, 5) && isColinear(3, 7)) {
  7354 				&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {
  7201 			type = Shape.Rectangle;
  7355 			type = Shape.Rectangle;
  7202 			size = new Size(getDistance(1, 6), getDistance(0, 3));
  7356 			size = new Size(getDistance(1, 6), getDistance(0, 3));
  7203 			radius = size.subtract(new Size(getDistance(0, 7),
  7357 			radius = size.subtract(new Size(getDistance(0, 7),
  7204 					getDistance(1, 2))).divide(2);
  7358 					getDistance(1, 2))).divide(2);
  7205 			topCenter = segments[3]._point.add(segments[4]._point).divide(2);
  7359 			topCenter = segments[3]._point.add(segments[4]._point).divide(2);
  7215 			topCenter = segments[1]._point;
  7369 			topCenter = segments[1]._point;
  7216 		}
  7370 		}
  7217 
  7371 
  7218 		if (type) {
  7372 		if (type) {
  7219 			var center = this.getPosition(true),
  7373 			var center = this.getPosition(true),
  7220 				shape = new type({
  7374 				shape = this._clone(new type({
  7221 					center: center,
  7375 					center: center,
  7222 					size: size,
  7376 					size: size,
  7223 					radius: radius,
  7377 					radius: radius,
  7224 					insert: false
  7378 					insert: false
  7225 				});
  7379 				}), insert, false);
  7226 			shape.rotate(topCenter.subtract(center).getAngle() + 90);
  7380 			shape.rotate(topCenter.subtract(center).getAngle() + 90);
  7227 			shape.setStyle(this._style);
       
  7228 			if (insert || insert === undefined)
       
  7229 				shape.insertAbove(this);
       
  7230 			return shape;
  7381 			return shape;
  7231 		}
  7382 		}
  7232 		return null;
  7383 		return null;
  7233 	},
  7384 	},
  7234 
  7385 
  7352 							point: loc.getPoint()
  7503 							point: loc.getPoint()
  7353 						})
  7504 						})
  7354 						: null;
  7505 						: null;
  7355 	}
  7506 	}
  7356 
  7507 
  7357 }, Base.each(['getPoint', 'getTangent', 'getNormal', 'getCurvature'],
  7508 }, Base.each(Curve.evaluateMethods,
  7358 	function(name) {
  7509 	function(name) {
  7359 		this[name + 'At'] = function(offset, isParameter) {
  7510 		this[name + 'At'] = function(offset, isParameter) {
  7360 			var loc = this.getLocationAt(offset, isParameter);
  7511 			var loc = this.getLocationAt(offset, isParameter);
  7361 			return loc && loc[name]();
  7512 			return loc && loc[name]();
  7362 		};
  7513 		};
  7398 
  7549 
  7399 	getLocationAt: function(offset, isParameter) {
  7550 	getLocationAt: function(offset, isParameter) {
  7400 		var curves = this.getCurves(),
  7551 		var curves = this.getCurves(),
  7401 			length = 0;
  7552 			length = 0;
  7402 		if (isParameter) {
  7553 		if (isParameter) {
  7403 			var index = ~~offset;
  7554 			var index = ~~offset,
  7404 			return curves[index].getLocationAt(offset - index, true);
  7555 				curve = curves[index];
       
  7556 			return curve ? curve.getLocationAt(offset - index, true) : null;
  7405 		}
  7557 		}
  7406 		for (var i = 0, l = curves.length; i < l; i++) {
  7558 		for (var i = 0, l = curves.length; i < l; i++) {
  7407 			var start = length,
  7559 			var start = length,
  7408 				curve = curves[i];
  7560 				curve = curves[i];
  7409 			length += curve.getLength();
  7561 			length += curve.getLength();
  7987 
  8139 
  7988 		function addJoin(segment, join) {
  8140 		function addJoin(segment, join) {
  7989 			var handleIn = segment._handleIn,
  8141 			var handleIn = segment._handleIn,
  7990 				handleOut = segment._handleOut;
  8142 				handleOut = segment._handleOut;
  7991 			if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
  8143 			if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
  7992 					&& handleIn.isColinear(handleOut)) {
  8144 					&& handleIn.isCollinear(handleOut)) {
  7993 				addRound(segment);
  8145 				addRound(segment);
  7994 			} else {
  8146 			} else {
  7995 				Path._addBevelJoin(segment, join, radius, miterLimit, add);
  8147 				Path._addBevelJoin(segment, join, radius, miterLimit, add);
  7996 			}
  8148 			}
  7997 		}
  8149 		}
  8066 	},
  8218 	},
  8067 
  8219 
  8068 	_addSquareCap: function(segment, cap, radius, addPoint, area) {
  8220 	_addSquareCap: function(segment, cap, radius, addPoint, area) {
  8069 		var point = segment._point,
  8221 		var point = segment._point,
  8070 			loc = segment.getLocation(),
  8222 			loc = segment.getLocation(),
  8071 			normal = loc.getNormal().normalize(radius);
  8223 			normal = loc.getNormal().multiply(radius);
  8072 		if (area) {
  8224 		if (area) {
  8073 			addPoint(point.subtract(normal));
  8225 			addPoint(point.subtract(normal));
  8074 			addPoint(point.add(normal));
  8226 			addPoint(point.add(normal));
  8075 		}
  8227 		}
  8076 		if (cap === 'square')
  8228 		if (cap === 'square')
  8520 				totalLength += length;
  8672 				totalLength += length;
  8521 				segment = segment.getNext();
  8673 				segment = segment.getNext();
  8522 			} while (segment && !segment._intersection && segment !== startSeg);
  8674 			} while (segment && !segment._intersection && segment !== startSeg);
  8523 			for (var j = 0; j < 3; j++) {
  8675 			for (var j = 0; j < 3; j++) {
  8524 				var length = totalLength * (j + 1) / 4;
  8676 				var length = totalLength * (j + 1) / 4;
  8525 				for (k = 0, m = chain.length; k < m; k++) {
  8677 				for (var k = 0, m = chain.length; k < m; k++) {
  8526 					var node = chain[k],
  8678 					var node = chain[k],
  8527 						curveLength = node.length;
  8679 						curveLength = node.length;
  8528 					if (length <= curveLength) {
  8680 					if (length <= curveLength) {
  8529 						if (length <= tolerance
  8681 						if (length < tolerance
  8530 								|| curveLength - length <= tolerance)
  8682 								|| curveLength - length < tolerance)
  8531 							length = curveLength / 2;
  8683 							length = curveLength / 2;
  8532 						var curve = node.segment.getCurve(),
  8684 						var curve = node.segment.getCurve(),
  8533 							pt = curve.getPointAt(length),
  8685 							pt = curve.getPointAt(length),
  8534 							hor = curve.isLinear() && Math.abs(curve
  8686 							hor = curve.isLinear() && Math.abs(curve
  8535 									.getTangentAt(0.5, true).y) <= tolerance,
  8687 									.getTangentAt(0.5, true).y) < tolerance,
  8536 							path = curve._path;
  8688 							path = curve._path;
  8537 						if (path._parent instanceof CompoundPath)
  8689 						if (path._parent instanceof CompoundPath)
  8538 							path = path._parent;
  8690 							path = path._parent;
  8539 						windingSum += operation === 'subtract' && _path2
  8691 						windingSum += operation === 'subtract' && _path2
  8540 							&& (path === _path1 && _path2._getWinding(pt, hor)
  8692 							&& (path === _path1 && _path2._getWinding(pt, hor)
  8623 				yAfter = py + tolerance;
  8775 				yAfter = py + tolerance;
  8624 			for (var i = 0, l = curves.length; i < l; i++) {
  8776 			for (var i = 0, l = curves.length; i < l; i++) {
  8625 				var values = curves[i].values;
  8777 				var values = curves[i].values;
  8626 				if (Curve.solveCubic(values, 0, px, roots, 0, 1) > 0) {
  8778 				if (Curve.solveCubic(values, 0, px, roots, 0, 1) > 0) {
  8627 					for (var j = roots.length - 1; j >= 0; j--) {
  8779 					for (var j = roots.length - 1; j >= 0; j--) {
  8628 						var y = Curve.evaluate(values, roots[j], 0).y;
  8780 						var y = Curve.getPoint(values, roots[j]).y;
  8629 						if (y < yBefore && y > yTop) {
  8781 						if (y < yBefore && y > yTop) {
  8630 							yTop = y;
  8782 							yTop = y;
  8631 						} else if (y > yAfter && y < yBottom) {
  8783 						} else if (y > yAfter && y < yBottom) {
  8632 							yBottom = y;
  8784 							yBottom = y;
  8633 						}
  8785 						}
  8641 			if (yBottom < Infinity)
  8793 			if (yBottom < Infinity)
  8642 				windRight = getWinding(new Point(px, yBottom), curves);
  8794 				windRight = getWinding(new Point(px, yBottom), curves);
  8643 		} else {
  8795 		} else {
  8644 			var xBefore = px - tolerance,
  8796 			var xBefore = px - tolerance,
  8645 				xAfter = px + tolerance;
  8797 				xAfter = px + tolerance;
       
  8798 			var startCounted = false,
       
  8799 				prevCurve,
       
  8800 				prevT;
  8646 			for (var i = 0, l = curves.length; i < l; i++) {
  8801 			for (var i = 0, l = curves.length; i < l; i++) {
  8647 				var curve = curves[i],
  8802 				var curve = curves[i],
  8648 					values = curve.values,
  8803 					values = curve.values,
  8649 					winding = curve.winding,
  8804 					winding = curve.winding;
  8650 					prevT,
       
  8651 					prevX;
       
  8652 				if (winding && (winding === 1
  8805 				if (winding && (winding === 1
  8653 						&& py >= values[1] && py <= values[7]
  8806 						&& py >= values[1] && py <= values[7]
  8654 						|| py >= values[7] && py <= values[1])
  8807 						|| py >= values[7] && py <= values[1])
  8655 					&& Curve.solveCubic(values, 1, py, roots, 0, 1) === 1) {
  8808 					&& Curve.solveCubic(values, 1, py, roots, 0, 1) === 1) {
  8656 					var t = roots[0],
  8809 					var t = roots[0];
  8657 						x = Curve.evaluate(values, t, 0).x,
  8810 					if (!(
  8658 						slope = Curve.evaluate(values, t, 1).y;
  8811 						t > tMax && startCounted && curve.next !== curves[i + 1]
  8659 					if (!(t > tMax
  8812 						|| t < tMin && prevT > tMax
  8660 							&& (i === l - 1 || curve.next !== curves[i + 1])
  8813 							&& curve.previous === prevCurve)) {
  8661 							&& abs(Curve.evaluate(curve.next.values, 0, 0).x -x)
  8814 						var x = Curve.getPoint(values, t).x,
  8662 								<= tolerance
  8815 							slope = Curve.getTangent(values, t).y,
  8663 						|| i > 0 && curve.previous === curves[i - 1]
  8816 							counted = false;
  8664 							&& abs(prevX - x) < tolerance
       
  8665 							&& prevT > tMax && t < tMin)) {
       
  8666 						if (Numerical.isZero(slope) && !Curve.isLinear(values)
  8817 						if (Numerical.isZero(slope) && !Curve.isLinear(values)
  8667 								|| t < tMin && slope * Curve.evaluate(
  8818 								|| t < tMin && slope * Curve.getTangent(
  8668 									curve.previous.values, 1, 1).y < 0
  8819 									curve.previous.values, 1).y < 0
  8669 								|| t > tMax && slope * Curve.evaluate(
  8820 								|| t > tMax && slope * Curve.getTangent(
  8670 									curve.next.values, 0, 1).y < 0) {
  8821 									curve.next.values, 0).y < 0) {
  8671 							if (testContains && x >= xBefore && x <= xAfter) {
  8822 							if (testContains && x >= xBefore && x <= xAfter) {
  8672 								++windLeft;
  8823 								++windLeft;
  8673 								++windRight;
  8824 								++windRight;
       
  8825 								counted = true;
  8674 							}
  8826 							}
  8675 						} else if (x <= xBefore) {
  8827 						} else if (x <= xBefore) {
  8676 							windLeft += winding;
  8828 							windLeft += winding;
       
  8829 							counted = true;
  8677 						} else if (x >= xAfter) {
  8830 						} else if (x >= xAfter) {
  8678 							windRight += winding;
  8831 							windRight += winding;
       
  8832 							counted = true;
  8679 						}
  8833 						}
       
  8834 						if (curve.previous !== curves[i - 1])
       
  8835 							startCounted = t < tMin && counted;
  8680 					}
  8836 					}
       
  8837 					prevCurve = curve;
  8681 					prevT = t;
  8838 					prevT = t;
  8682 					prevX = x;
       
  8683 				}
  8839 				}
  8684 			}
  8840 			}
  8685 		}
  8841 		}
  8686 		return Math.max(abs(windLeft), abs(windRight));
  8842 		return Math.max(abs(windLeft), abs(windRight));
  8687 	}
  8843 	}
  8757 				path.setClosed(true);
  8913 				path.setClosed(true);
  8758 			} else {
  8914 			} else {
  8759 				path.lastSegment._handleOut.set(0, 0);
  8915 				path.lastSegment._handleOut.set(0, 0);
  8760 			}
  8916 			}
  8761 			if (path._segments.length >
  8917 			if (path._segments.length >
  8762 					(path._closed ? path.isPolygon() ? 2 : 0 : 1))
  8918 					(path._closed ? path.isLinear() ? 2 : 0 : 1))
  8763 				paths.push(path);
  8919 				paths.push(path);
  8764 		}
  8920 		}
  8765 		return paths;
  8921 		return paths;
  8766 	}
  8922 	}
  8767 
  8923 
  8887 				if ((curves[i].winding === 1
  9043 				if ((curves[i].winding === 1
  8888 						&& y >= values[1] && y <= values[7]
  9044 						&& y >= values[1] && y <= values[7]
  8889 						|| y >= values[7] && y <= values[1])
  9045 						|| y >= values[7] && y <= values[1])
  8890 						&& Curve.solveCubic(values, 1, y, roots, 0, 1) > 0) {
  9046 						&& Curve.solveCubic(values, 1, y, roots, 0, 1) > 0) {
  8891 					for (var j = roots.length - 1; j >= 0; j--)
  9047 					for (var j = roots.length - 1; j >= 0; j--)
  8892 						xIntercepts.push(Curve.evaluate(values, roots[j], 0).x);
  9048 						xIntercepts.push(Curve.getPoint(values, roots[j]).x);
  8893 				}
  9049 				}
  8894 				if (xIntercepts.length > 1)
  9050 				if (xIntercepts.length > 1)
  8895 					break;
  9051 					break;
  8896 			}
  9052 			}
  8897 			point.x = (xIntercepts[0] + xIntercepts[1]) / 2;
  9053 			point.x = (xIntercepts[0] + xIntercepts[1]) / 2;
  9015 			value: 1,
  9171 			value: 1,
  9016 			index: part.index
  9172 			index: part.index
  9017 		};
  9173 		};
  9018 	},
  9174 	},
  9019 
  9175 
  9020 	evaluate: function(offset, type) {
       
  9021 		var param = this.getParameterAt(offset);
       
  9022 		return Curve.evaluate(this.curves[param.index], param.value, type);
       
  9023 	},
       
  9024 
       
  9025 	drawPart: function(ctx, from, to) {
  9176 	drawPart: function(ctx, from, to) {
  9026 		from = this.getParameterAt(from);
  9177 		from = this.getParameterAt(from);
  9027 		to = this.getParameterAt(to);
  9178 		to = this.getParameterAt(to);
  9028 		for (var i = from.index; i <= to.index; i++) {
  9179 		for (var i = from.index; i <= to.index; i++) {
  9029 			var curve = Curve.getPart(this.curves[i],
  9180 			var curve = Curve.getPart(this.curves[i],
  9032 			if (i == from.index)
  9183 			if (i == from.index)
  9033 				ctx.moveTo(curve[0], curve[1]);
  9184 				ctx.moveTo(curve[0], curve[1]);
  9034 			ctx.bezierCurveTo.apply(ctx, curve.slice(2));
  9185 			ctx.bezierCurveTo.apply(ctx, curve.slice(2));
  9035 		}
  9186 		}
  9036 	}
  9187 	}
  9037 }, Base.each(['getPoint', 'getTangent', 'getNormal', 'getCurvature'],
  9188 }, Base.each(Curve.evaluateMethods,
  9038 	function(name, index) {
  9189 	function(name) {
  9039 		this[name + 'At'] = function(offset) {
  9190 		this[name + 'At'] = function(offset, weighted) {
  9040 			return this.evaluate(offset, index);
  9191 			var param = this.getParameterAt(offset);
       
  9192 			return Curve[name](this.curves[param.index], param.value, weighted);
  9041 		};
  9193 		};
  9042 	}, {})
  9194 	}, {})
  9043 );
  9195 );
  9044 
  9196 
  9045 var PathFitter = Base.extend({
  9197 var PathFitter = Base.extend({
  9091 					pt2.add(tan2.normalize(dist)), pt2]);
  9243 					pt2.add(tan2.normalize(dist)), pt2]);
  9092 			return;
  9244 			return;
  9093 		}
  9245 		}
  9094 		var uPrime = this.chordLengthParameterize(first, last),
  9246 		var uPrime = this.chordLengthParameterize(first, last),
  9095 			maxError = Math.max(this.error, this.error * this.error),
  9247 			maxError = Math.max(this.error, this.error * this.error),
  9096 			split;
  9248 			split,
       
  9249 			parametersInOrder = true;
  9097 		for (var i = 0; i <= 4; i++) {
  9250 		for (var i = 0; i <= 4; i++) {
  9098 			var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
  9251 			var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
  9099 			var max = this.findMaxError(first, last, curve, uPrime);
  9252 			var max = this.findMaxError(first, last, curve, uPrime);
  9100 			if (max.error < this.error) {
  9253 			if (max.error < this.error && parametersInOrder) {
  9101 				this.addCurve(curve);
  9254 				this.addCurve(curve);
  9102 				return;
  9255 				return;
  9103 			}
  9256 			}
  9104 			split = max.index;
  9257 			split = max.index;
  9105 			if (max.error >= maxError)
  9258 			if (max.error >= maxError)
  9106 				break;
  9259 				break;
  9107 			this.reparameterize(first, last, uPrime, curve);
  9260 			parametersInOrder = this.reparameterize(first, last, uPrime, curve);
  9108 			maxError = max.error;
  9261 			maxError = max.error;
  9109 		}
  9262 		}
  9110 		var V1 = this.points[split - 1].subtract(this.points[split]),
  9263 		var V1 = this.points[split - 1].subtract(this.points[split]),
  9111 			V2 = this.points[split].subtract(this.points[split + 1]),
  9264 			V2 = this.points[split].subtract(this.points[split + 1]),
  9112 			tanCenter = V1.add(V2).divide(2).normalize();
  9265 			tanCenter = V1.add(V2).divide(2).normalize();
  9166 			} else {
  9319 			} else {
  9167 				alpha1 = alpha2 = 0;
  9320 				alpha1 = alpha2 = 0;
  9168 			}
  9321 			}
  9169 		}
  9322 		}
  9170 
  9323 
  9171 		var segLength = pt2.getDistance(pt1);
  9324 		var segLength = pt2.getDistance(pt1),
  9172 		epsilon *= segLength;
  9325 			eps = epsilon * segLength,
  9173 		if (alpha1 < epsilon || alpha2 < epsilon) {
  9326 			handle1,
       
  9327 			handle2;
       
  9328 		if (alpha1 < eps || alpha2 < eps) {
  9174 			alpha1 = alpha2 = segLength / 3;
  9329 			alpha1 = alpha2 = segLength / 3;
  9175 		}
  9330 		} else {
  9176 
  9331 			var line = pt2.subtract(pt1);
  9177 		return [pt1, pt1.add(tan1.normalize(alpha1)),
  9332 			handle1 = tan1.normalize(alpha1);
  9178 				pt2.add(tan2.normalize(alpha2)), pt2];
  9333 			handle2 = tan2.normalize(alpha2);
       
  9334 			if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
       
  9335 				alpha1 = alpha2 = segLength / 3;
       
  9336 				handle1 = handle2 = null;
       
  9337 			}
       
  9338 		}
       
  9339 
       
  9340 		return [pt1, pt1.add(handle1 || tan1.normalize(alpha1)),
       
  9341 				pt2.add(handle2 || tan2.normalize(alpha2)), pt2];
  9179 	},
  9342 	},
  9180 
  9343 
  9181 	reparameterize: function(first, last, u, curve) {
  9344 	reparameterize: function(first, last, u, curve) {
  9182 		for (var i = first; i <= last; i++) {
  9345 		for (var i = first; i <= last; i++) {
  9183 			u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
  9346 			u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
  9184 		}
  9347 		}
       
  9348 		for (var i = 1, l = u.length; i < l; i++) {
       
  9349 			if (u[i] <= u[i - 1])
       
  9350 				return false;
       
  9351 		}
       
  9352 		return true;
  9185 	},
  9353 	},
  9186 
  9354 
  9187 	findRoot: function(curve, point, u) {
  9355 	findRoot: function(curve, point, u) {
  9188 		var curve1 = [],
  9356 		var curve1 = [],
  9189 			curve2 = [];
  9357 			curve2 = [];
  9264 
  9432 
  9265 	_equals: function(item) {
  9433 	_equals: function(item) {
  9266 		return this._content === item._content;
  9434 		return this._content === item._content;
  9267 	},
  9435 	},
  9268 
  9436 
  9269 	_clone: function _clone(copy, insert) {
  9437 	_clone: function _clone(copy, insert, includeMatrix) {
  9270 		copy.setContent(this._content);
  9438 		copy.setContent(this._content);
  9271 		return _clone.base.call(this, copy, insert);
  9439 		return _clone.base.call(this, copy, insert, includeMatrix);
  9272 	},
  9440 	},
  9273 
  9441 
  9274 	getContent: function() {
  9442 	getContent: function() {
  9275 		return this._content;
  9443 		return this._content;
  9276 	},
  9444 	},
  9545 						&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {
  9713 						&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {
  9546 					this._components = this._convert(type);
  9714 					this._components = this._convert(type);
  9547 					this._properties = types[type];
  9715 					this._properties = types[type];
  9548 					this._type = type;
  9716 					this._type = type;
  9549 				}
  9717 				}
  9550 				value = parser.call(this, value);
  9718 				this._components[index] = parser.call(this, value);
  9551 				if (value != null) {
  9719 				this._changed();
  9552 					this._components[index] = value;
       
  9553 					this._changed();
       
  9554 				}
       
  9555 			};
  9720 			};
  9556 		}, this);
  9721 		}, this);
  9557 	}, {
  9722 	}, {
  9558 		_class: 'Color',
  9723 		_class: 'Color',
  9559 		_readIndex: true,
  9724 		_readIndex: true,
  9657 				}
  9822 				}
  9658 				if (this.__read && type)
  9823 				if (this.__read && type)
  9659 					read = 1;
  9824 					read = 1;
  9660 			}
  9825 			}
  9661 			this._type = type || 'rgb';
  9826 			this._type = type || 'rgb';
  9662 			if (type === 'gradient')
  9827 			this._id = UID.get(Color);
  9663 				this._id = Color._id = (Color._id || 0) + 1;
       
  9664 			if (!components) {
  9828 			if (!components) {
  9665 				this._components = components = [];
  9829 				this._components = components = [];
  9666 				var parsers = componentParsers[this._type];
  9830 				var parsers = componentParsers[this._type];
  9667 				for (var i = 0, l = parsers.length; i < l; i++) {
  9831 				for (var i = 0, l = parsers.length; i < l; i++) {
  9668 					var value = parsers[i].call(this, values && values[i]);
  9832 					var value = parsers[i].call(this, values && values[i]);
  9895 
 10059 
  9896 var Gradient = Base.extend({
 10060 var Gradient = Base.extend({
  9897 	_class: 'Gradient',
 10061 	_class: 'Gradient',
  9898 
 10062 
  9899 	initialize: function Gradient(stops, radial) {
 10063 	initialize: function Gradient(stops, radial) {
  9900 		this._id = Gradient._id = (Gradient._id || 0) + 1;
 10064 		this._id = UID.get();
  9901 		if (stops && this._set(stops))
 10065 		if (stops && this._set(stops))
  9902 			stops = radial = null;
 10066 			stops = radial = null;
  9903 		if (!this._stops)
 10067 		if (!this._stops)
  9904 			this.setStops(stops || ['white', 'black']);
 10068 			this.setStops(stops || ['white', 'black']);
  9905 		if (this._radial == null)
 10069 		if (this._radial == null)
  9936 
 10100 
  9937 	clone: function() {
 10101 	clone: function() {
  9938 		var stops = [];
 10102 		var stops = [];
  9939 		for (var i = 0, l = this._stops.length; i < l; i++)
 10103 		for (var i = 0, l = this._stops.length; i < l; i++)
  9940 			stops[i] = this._stops[i].clone();
 10104 			stops[i] = this._stops[i].clone();
  9941 		return new Gradient(stops);
 10105 		return new Gradient(stops, this._radial);
  9942 	},
 10106 	},
  9943 
 10107 
  9944 	getStops: function() {
 10108 	getStops: function() {
  9945 		return this._stops;
 10109 		return this._stops;
  9946 	},
 10110 	},
 10898 			this._context.scale(pixelRatio, pixelRatio);
 11062 			this._context.scale(pixelRatio, pixelRatio);
 10899 		}
 11063 		}
 10900 	},
 11064 	},
 10901 
 11065 
 10902 	getPixelSize: function(size) {
 11066 	getPixelSize: function(size) {
 10903 		var ctx = this._context,
 11067 		var browser = paper.browser,
 10904 			prevFont = ctx.font;
 11068 			pixels;
 10905 		ctx.font = size + ' serif';
 11069 		if (browser && browser.firefox) {
 10906 		size = parseFloat(ctx.font);
 11070 			var parent = this._element.parentNode,
 10907 		ctx.font = prevFont;
 11071 				temp = document.createElement('div');
 10908 		return size;
 11072 			temp.style.fontSize = size;
       
 11073 			parent.appendChild(temp);
       
 11074 			pixels = parseFloat(DomElement.getStyles(temp).fontSize);
       
 11075 			parent.removeChild(temp);
       
 11076 		} else {
       
 11077 			var ctx = this._context,
       
 11078 				prevFont = ctx.font;
       
 11079 			ctx.font = size + ' serif';
       
 11080 			pixels = parseFloat(ctx.font);
       
 11081 			ctx.font = prevFont;
       
 11082 		}
       
 11083 		return pixels;
 10909 	},
 11084 	},
 10910 
 11085 
 10911 	getTextWidth: function(font, lines) {
 11086 	getTextWidth: function(font, lines) {
 10912 		var ctx = this._context,
 11087 		var ctx = this._context,
 10913 			prevFont = ctx.font,
 11088 			prevFont = ctx.font,
 10917 			width = Math.max(width, ctx.measureText(lines[i]).width);
 11092 			width = Math.max(width, ctx.measureText(lines[i]).width);
 10918 		ctx.font = prevFont;
 11093 		ctx.font = prevFont;
 10919 		return width;
 11094 		return width;
 10920 	},
 11095 	},
 10921 
 11096 
 10922 	update: function() {
 11097 	update: function(force) {
 10923 		var project = this._project;
 11098 		var project = this._project;
 10924 		if (!project || !project._needsUpdate)
 11099 		if (!project || !force && !project._needsUpdate)
 10925 			return false;
 11100 			return false;
 10926 		var ctx = this._context,
 11101 		var ctx = this._context,
 10927 			size = this._viewSize;
 11102 			size = this._viewSize;
 10928 		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
 11103 		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
 10929 		project.draw(ctx, this._matrix, this._pixelRatio);
 11104 		project.draw(ctx, this._matrix, this._pixelRatio);
 11123 		space: false
 11298 		space: false
 11124 	}),
 11299 	}),
 11125 
 11300 
 11126 	charCodeMap = {},
 11301 	charCodeMap = {},
 11127 	keyMap = {},
 11302 	keyMap = {},
       
 11303 	commandFixMap,
 11128 	downCode;
 11304 	downCode;
 11129 
 11305 
 11130 	function handleKey(down, keyCode, charCode, event) {
 11306 	function handleKey(down, keyCode, charCode, event) {
 11131 		var character = charCode ? String.fromCharCode(charCode) : '',
 11307 		var character = charCode ? String.fromCharCode(charCode) : '',
 11132 			specialKey = specialKeys[keyCode],
 11308 			specialKey = specialKeys[keyCode],
 11135 			view = View._focused,
 11311 			view = View._focused,
 11136 			scope = view && view.isVisible() && view._scope,
 11312 			scope = view && view.isVisible() && view._scope,
 11137 			tool = scope && scope.tool,
 11313 			tool = scope && scope.tool,
 11138 			name;
 11314 			name;
 11139 		keyMap[key] = down;
 11315 		keyMap[key] = down;
 11140 		if (specialKey && (name = Base.camelize(specialKey)) in modifiers)
       
 11141 			modifiers[name] = down;
       
 11142 		if (down) {
 11316 		if (down) {
 11143 			charCodeMap[keyCode] = charCode;
 11317 			charCodeMap[keyCode] = charCode;
 11144 		} else {
 11318 		} else {
 11145 			delete charCodeMap[keyCode];
 11319 			delete charCodeMap[keyCode];
       
 11320 		}
       
 11321 		if (specialKey && (name = Base.camelize(specialKey)) in modifiers) {
       
 11322 			modifiers[name] = down;
       
 11323 			var browser = paper.browser;
       
 11324 			if (name === 'command' && browser && browser.mac) {
       
 11325 				if (down) {
       
 11326 					commandFixMap = {};
       
 11327 				} else {
       
 11328 					for (var code in commandFixMap) {
       
 11329 						if (code in charCodeMap)
       
 11330 							handleKey(false, code, commandFixMap[code], event);
       
 11331 					}
       
 11332 					commandFixMap = null;
       
 11333 				}
       
 11334 			}
       
 11335 		} else if (down && commandFixMap) {
       
 11336 			commandFixMap[keyCode] = charCode;
 11146 		}
 11337 		}
 11147 		if (tool && tool.responds(type)) {
 11338 		if (tool && tool.responds(type)) {
 11148 			paper = scope;
 11339 			paper = scope;
 11149 			tool.emit(type, new KeyEvent(down, key, character, event));
 11340 			tool.emit(type, new KeyEvent(down, key, character, event));
 11150 			if (view)
 11341 			if (view)
 11334 		return this._minDistance;
 11525 		return this._minDistance;
 11335 	},
 11526 	},
 11336 
 11527 
 11337 	setMinDistance: function(minDistance) {
 11528 	setMinDistance: function(minDistance) {
 11338 		this._minDistance = minDistance;
 11529 		this._minDistance = minDistance;
 11339 		if (this._minDistance != null && this._maxDistance != null
 11530 		if (minDistance != null && this._maxDistance != null
 11340 				&& this._minDistance > this._maxDistance) {
 11531 				&& minDistance > this._maxDistance) {
 11341 			this._maxDistance = this._minDistance;
 11532 			this._maxDistance = minDistance;
 11342 		}
 11533 		}
 11343 	},
 11534 	},
 11344 
 11535 
 11345 	getMaxDistance: function() {
 11536 	getMaxDistance: function() {
 11346 		return this._maxDistance;
 11537 		return this._maxDistance;
 11347 	},
 11538 	},
 11348 
 11539 
 11349 	setMaxDistance: function(maxDistance) {
 11540 	setMaxDistance: function(maxDistance) {
 11350 		this._maxDistance = maxDistance;
 11541 		this._maxDistance = maxDistance;
 11351 		if (this._minDistance != null && this._maxDistance != null
 11542 		if (this._minDistance != null && maxDistance != null
 11352 				&& this._maxDistance < this._minDistance) {
 11543 				&& maxDistance < this._minDistance) {
 11353 			this._minDistance = maxDistance;
 11544 			this._minDistance = maxDistance;
 11354 		}
 11545 		}
 11355 	},
 11546 	},
 11356 
 11547 
 11357 	getFixedDistance: function() {
 11548 	getFixedDistance: function() {
 11371 				var minDist = minDistance != null ? minDistance : 0,
 11562 				var minDist = minDistance != null ? minDistance : 0,
 11372 					vector = point.subtract(this._point),
 11563 					vector = point.subtract(this._point),
 11373 					distance = vector.getLength();
 11564 					distance = vector.getLength();
 11374 				if (distance < minDist)
 11565 				if (distance < minDist)
 11375 					return false;
 11566 					return false;
 11376 				var maxDist = maxDistance != null ? maxDistance : 0;
 11567 				if (maxDistance != null && maxDistance != 0) {
 11377 				if (maxDist != 0) {
 11568 					if (distance > maxDistance) {
 11378 					if (distance > maxDist) {
 11569 						point = this._point.add(vector.normalize(maxDistance));
 11379 						point = this._point.add(vector.normalize(maxDist));
       
 11380 					} else if (matchMaxDistance) {
 11570 					} else if (matchMaxDistance) {
 11381 						return false;
 11571 						return false;
 11382 					}
 11572 					}
 11383 				}
 11573 				}
 11384 			}
 11574 			}
 11468 	}
 11658 	}
 11469 
 11659 
 11470 });
 11660 });
 11471 
 11661 
 11472 var Http = {
 11662 var Http = {
 11473 	request: function(method, url, callback) {
 11663 	request: function(method, url, callback, async) {
       
 11664 		async = (async === undefined) ? true : async;
 11474 		var xhr = new (window.ActiveXObject || XMLHttpRequest)(
 11665 		var xhr = new (window.ActiveXObject || XMLHttpRequest)(
 11475 					'Microsoft.XMLHTTP');
 11666 					'Microsoft.XMLHTTP');
 11476 		xhr.open(method.toUpperCase(), url, true);
 11667 		xhr.open(method.toUpperCase(), url, async);
 11477 		if ('overrideMimeType' in xhr)
 11668 		if ('overrideMimeType' in xhr)
 11478 			xhr.overrideMimeType('text/plain');
 11669 			xhr.overrideMimeType('text/plain');
 11479 		xhr.onreadystatechange = function() {
 11670 		xhr.onreadystatechange = function() {
 11480 			if (xhr.readyState === 4) {
 11671 			if (xhr.readyState === 4) {
 11481 				var status = xhr.status;
 11672 				var status = xhr.status;
 11902 			}
 12093 			}
 11903 		}
 12094 		}
 11904 		return node;
 12095 		return node;
 11905 	}
 12096 	}
 11906 
 12097 
 11907 	function exportRaster(item) {
 12098 	function exportRaster(item, options) {
 11908 		var attrs = getTransform(item._matrix, true),
 12099 		var attrs = getTransform(item._matrix, true),
 11909 			size = item.getSize();
 12100 			size = item.getSize(),
       
 12101 			image = item.getImage();
 11910 		attrs.x -= size.width / 2;
 12102 		attrs.x -= size.width / 2;
 11911 		attrs.y -= size.height / 2;
 12103 		attrs.y -= size.height / 2;
 11912 		attrs.width = size.width;
 12104 		attrs.width = size.width;
 11913 		attrs.height = size.height;
 12105 		attrs.height = size.height;
 11914 		attrs.href = item.toDataURL();
 12106 		attrs.href = options.embedImages === false && image && image.src
       
 12107 				|| item.toDataURL();
 11915 		return createElement('image', attrs);
 12108 		return createElement('image', attrs);
 11916 	}
 12109 	}
 11917 
 12110 
 11918 	function exportPath(item, options) {
 12111 	function exportPath(item, options) {
 11919 		if (options.matchShapes) {
 12112 		var matchShapes = options.matchShapes;
       
 12113 		if (matchShapes) {
 11920 			var shape = item.toShape(false);
 12114 			var shape = item.toShape(false);
 11921 			if (shape)
 12115 			if (shape)
 11922 				return exportShape(shape, options);
 12116 				return exportShape(shape, options);
 11923 		}
 12117 		}
 11924 		var segments = item._segments,
 12118 		var segments = item._segments,
 11925 			type,
 12119 			type,
 11926 			attrs = getTransform(item._matrix);
 12120 			attrs = getTransform(item._matrix);
 11927 		if (segments.length === 0)
 12121 		if (segments.length === 0)
 11928 			return null;
 12122 			return null;
 11929 		if (item.isPolygon()) {
 12123 		if (matchShapes && !item.hasHandles()) {
 11930 			if (segments.length >= 3) {
 12124 			if (segments.length >= 3) {
 11931 				type = item._closed ? 'polygon' : 'polyline';
 12125 				type = item._closed ? 'polygon' : 'polyline';
 11932 				var parts = [];
 12126 				var parts = [];
 11933 				for(i = 0, l = segments.length; i < l; i++)
 12127 				for(var i = 0, l = segments.length; i < l; i++)
 11934 					parts.push(formatter.point(segments[i]._point));
 12128 					parts.push(formatter.point(segments[i]._point));
 11935 				attrs.points = parts.join(' ');
 12129 				attrs.points = parts.join(' ');
 11936 			} else {
 12130 			} else {
 11937 				type = 'line';
 12131 				type = 'line';
 11938 				var first = segments[0]._point,
 12132 				var first = segments[0]._point,
 12268 			children = [];
 12462 			children = [];
 12269 		if (!isClip) {
 12463 		if (!isClip) {
 12270 			item = applyAttributes(item, node, isRoot);
 12464 			item = applyAttributes(item, node, isRoot);
 12271 			project._currentStyle = item._style.clone();
 12465 			project._currentStyle = item._style.clone();
 12272 		}
 12466 		}
       
 12467 		if (isRoot) {
       
 12468 			var defs = node.querySelectorAll('defs');
       
 12469 			for (var i = 0, l = defs.length; i < l; i++) {
       
 12470 				importSVG(defs[i], options, false);
       
 12471 			}
       
 12472 		}
 12273 		for (var i = 0, l = nodes.length; i < l; i++) {
 12473 		for (var i = 0, l = nodes.length; i < l; i++) {
 12274 			var childNode = nodes[i],
 12474 			var childNode = nodes[i],
 12275 				child;
 12475 				child;
 12276 			if (childNode.nodeType === 1
 12476 			if (childNode.nodeType === 1
       
 12477 					&& childNode.nodeName.toLowerCase() !== 'defs'
 12277 					&& (child = importSVG(childNode, options, false))
 12478 					&& (child = importSVG(childNode, options, false))
 12278 					&& !(child instanceof Symbol))
 12479 					&& !(child instanceof Symbol))
 12279 				children.push(child);
 12480 				children.push(child);
 12280 		}
 12481 		}
 12281 		item.addChildren(children);
 12482 		item.addChildren(children);
 12471 				: 'getStrokeColor']();
 12672 				: 'getStrokeColor']();
 12472 		if (color)
 12673 		if (color)
 12473 			color.setAlpha(parseFloat(value));
 12674 			color.setAlpha(parseFloat(value));
 12474 	}
 12675 	}
 12475 
 12676 
 12476 	var attributes = Base.each(SVGStyles, function(entry) {
 12677 	var attributes = Base.set(Base.each(SVGStyles, function(entry) {
 12477 		this[entry.attribute] = function(item, value) {
 12678 		this[entry.attribute] = function(item, value) {
 12478 			item[entry.set](convertValue(value, entry.type, entry.fromSVG));
 12679 			item[entry.set](convertValue(value, entry.type, entry.fromSVG));
 12479 			if (entry.type === 'color' && item instanceof Shape) {
 12680 			if (entry.type === 'color' && item instanceof Shape) {
 12480 				var color = item[entry.get]();
 12681 				var color = item[entry.get]();
 12481 				if (color)
 12682 				if (color)
 12482 					color.transform(new Matrix().translate(
 12683 					color.transform(new Matrix().translate(
 12483 							item.getPosition(true).negate()));
 12684 							item.getPosition(true).negate()));
 12484 			}
 12685 			}
 12485 		};
 12686 		};
 12486 	}, {
 12687 	}, {}), {
 12487 		id: function(item, value) {
 12688 		id: function(item, value) {
 12488 			definitions[value] = item;
 12689 			definitions[value] = item;
 12489 			if (item.setName)
 12690 			if (item.setName)
 12490 				item.setName(value);
 12691 				item.setName(value);
 12491 		},
 12692 		},
 12655 			if (data)
 12856 			if (data)
 12656 				item._data = JSON.parse(data);
 12857 				item._data = JSON.parse(data);
 12657 		}
 12858 		}
 12658 		if (isRoot) {
 12859 		if (isRoot) {
 12659 			definitions = {};
 12860 			definitions = {};
 12660 			if (applyMatrix && item)
 12861 			if (item && Base.pick(options.applyMatrix, applyMatrix))
 12661 				item.matrix.apply(true, true);
 12862 				item.matrix.apply(true, true);
 12662 		}
 12863 		}
 12663 		return item;
 12864 		return item;
 12664 	}
 12865 	}
 12665 
 12866 
 12825 						|| parentType === 'BinaryExpression'
 13026 						|| parentType === 'BinaryExpression'
 12826 							&& /^[=!<>]/.test(parent.operator)
 13027 							&& /^[=!<>]/.test(parent.operator)
 12827 						|| parentType === 'MemberExpression' && parent.computed
 13028 						|| parentType === 'MemberExpression' && parent.computed
 12828 				)) {
 13029 				)) {
 12829 					if (node.type === 'UpdateExpression') {
 13030 					if (node.type === 'UpdateExpression') {
 12830 						var arg = getCode(node.argument);
 13031 						var arg = getCode(node.argument),
 12831 						var str = arg + ' = __$__(' + arg
 13032 							exp = '__$__(' + arg + ', "' + node.operator[0]
 12832 								+ ', "' + node.operator[0] + '", 1)';
 13033 									+ '", 1)',
       
 13034 							str = arg + ' = ' + exp;
 12833 						if (!node.prefix
 13035 						if (!node.prefix
 12834 								&& (parentType === 'AssignmentExpression'
 13036 								&& (parentType === 'AssignmentExpression'
 12835 									|| parentType === 'VariableDeclarator'))
 13037 									|| parentType === 'VariableDeclarator')) {
       
 13038 							if (getCode(parent.left || parent.id) === arg)
       
 13039 								str = exp;
 12836 							str = arg + '; ' + str;
 13040 							str = arg + '; ' + str;
       
 13041 						}
 12837 						replaceCode(node, str);
 13042 						replaceCode(node, str);
 12838 					} else {
 13043 					} else {
 12839 						if (/^.=$/.test(node.operator)
 13044 						if (/^.=$/.test(node.operator)
 12840 								&& node.left.type !== 'Literal') {
 13045 								&& node.left.type !== 'Literal') {
 12841 							var left = getCode(node.left),
 13046 							var left = getCode(node.left),
 12956 	function loadScript(script) {
 13161 	function loadScript(script) {
 12957 		if (/^text\/(?:x-|)paperscript$/.test(script.type)
 13162 		if (/^text\/(?:x-|)paperscript$/.test(script.type)
 12958 				&& PaperScope.getAttribute(script, 'ignore') !== 'true') {
 13163 				&& PaperScope.getAttribute(script, 'ignore') !== 'true') {
 12959 			var canvasId = PaperScope.getAttribute(script, 'canvas'),
 13164 			var canvasId = PaperScope.getAttribute(script, 'canvas'),
 12960 				canvas = document.getElementById(canvasId),
 13165 				canvas = document.getElementById(canvasId),
 12961 				src = script.src,
 13166 				src = script.src || script.getAttribute('data-src'),
       
 13167 				async = PaperScope.hasAttribute(script, 'async'),
 12962 				scopeAttribute = 'data-paper-scope';
 13168 				scopeAttribute = 'data-paper-scope';
 12963 			if (!canvas)
 13169 			if (!canvas)
 12964 				throw new Error('Unable to find canvas with id "'
 13170 				throw new Error('Unable to find canvas with id "'
 12965 						+ canvasId + '"');
 13171 						+ canvasId + '"');
 12966 			var scope = PaperScope.get(canvas.getAttribute(scopeAttribute))
 13172 			var scope = PaperScope.get(canvas.getAttribute(scopeAttribute))
 12967 						|| new PaperScope().setup(canvas);
 13173 						|| new PaperScope().setup(canvas);
 12968 			canvas.setAttribute(scopeAttribute, scope._id);
 13174 			canvas.setAttribute(scopeAttribute, scope._id);
 12969 			if (src) {
 13175 			if (src) {
 12970 				Http.request('get', src, function(code) {
 13176 				Http.request('get', src, function(code) {
 12971 					execute(code, scope, src);
 13177 					execute(code, scope, src);
 12972 				});
 13178 				}, async);
 12973 			} else {
 13179 			} else {
 12974 				execute(script.innerHTML, scope, script.baseURI);
 13180 				execute(script.innerHTML, scope, script.baseURI);
 12975 			}
 13181 			}
 12976 			script.setAttribute('data-paper-ignore', 'true');
 13182 			script.setAttribute('data-paper-ignore', 'true');
 12977 			return scope;
 13183 			return scope;