server/php/basic/public_html/static/lib/paper/paper-full.js
changeset 598 eb4f4eceada0
parent 495 444b80998255
equal deleted inserted replaced
597:ebdd1d769158 598:eb4f4eceada0
     1 /*!
     1 /*!
     2  * Paper.js v0.9.24 - The Swiss Army Knife of Vector Graphics Scripting.
     2  * Paper.js v0.9.25 - 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: Fri Aug 21 16:39:41 2015 +0200
    12  * Date: Sun Oct 25 11:23:38 2015 +0100
    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  *
   579 				entry = types && types[type],
   579 				entry = types && types[type],
   580 				handlers = this._callbacks = this._callbacks || {};
   580 				handlers = this._callbacks = this._callbacks || {};
   581 			handlers = handlers[type] = handlers[type] || [];
   581 			handlers = handlers[type] = handlers[type] || [];
   582 			if (handlers.indexOf(func) === -1) {
   582 			if (handlers.indexOf(func) === -1) {
   583 				handlers.push(func);
   583 				handlers.push(func);
   584 				if (entry && entry.install && handlers.length == 1)
   584 				if (entry && entry.install && handlers.length === 1)
   585 					entry.install.call(this, type);
   585 					entry.install.call(this, type);
   586 			}
   586 			}
   587 		}
   587 		}
   588 		return this;
   588 		return this;
   589 	},
   589 	},
   744 			if (browser.atom)
   744 			if (browser.atom)
   745 				delete browser.chrome;
   745 				delete browser.chrome;
   746 		}
   746 		}
   747 	},
   747 	},
   748 
   748 
   749 	version: '0.9.24',
   749 	version: "0.9.25",
   750 
   750 
   751 	getView: function() {
   751 	getView: function() {
   752 		return this.project && this.project.getView();
   752 		return this.project && this.project.getView();
   753 	},
   753 	},
   754 
   754 
   927 	];
   927 	];
   928 
   928 
   929 	var abs = Math.abs,
   929 	var abs = Math.abs,
   930 		sqrt = Math.sqrt,
   930 		sqrt = Math.sqrt,
   931 		pow = Math.pow,
   931 		pow = Math.pow,
   932 		TOLERANCE = 1e-6,
       
   933 		EPSILON = 1e-12,
   932 		EPSILON = 1e-12,
   934 		MACHINE_EPSILON = 1.12e-16;
   933 		MACHINE_EPSILON = 1.12e-16;
   935 
   934 
       
   935 	function clip(value, min, max) {
       
   936 		return value < min ? min : value > max ? max : value;
       
   937 	}
       
   938 
   936 	return {
   939 	return {
   937 		TOLERANCE: TOLERANCE,
   940 		TOLERANCE: 1e-6,
   938 		EPSILON: EPSILON,
   941 		EPSILON: EPSILON,
   939 		MACHINE_EPSILON: MACHINE_EPSILON,
   942 		MACHINE_EPSILON: MACHINE_EPSILON,
       
   943 		CURVETIME_EPSILON: 4e-7,
       
   944 		GEOMETRIC_EPSILON: 2e-7,
       
   945 		WINDING_EPSILON: 2e-7,
       
   946 		TRIGONOMETRIC_EPSILON: 1e-7,
       
   947 		CLIPPING_EPSILON: 1e-7,
   940 		KAPPA: 4 * (sqrt(2) - 1) / 3,
   948 		KAPPA: 4 * (sqrt(2) - 1) / 3,
   941 
   949 
   942 		isZero: function(val) {
   950 		isZero: function(val) {
   943 			return abs(val) <= EPSILON;
   951 			return val >= -EPSILON && val <= EPSILON;
   944 		},
   952 		},
   945 
   953 
   946 		integrate: function(f, a, b, n) {
   954 		integrate: function(f, a, b, n) {
   947 			var x = abscissas[n - 2],
   955 			var x = abscissas[n - 2],
   948 				w = weights[n - 2],
   956 				w = weights[n - 2],
   976 			return x;
   984 			return x;
   977 		},
   985 		},
   978 
   986 
   979 		solveQuadratic: function(a, b, c, roots, min, max) {
   987 		solveQuadratic: function(a, b, c, roots, min, max) {
   980 			var count = 0,
   988 			var count = 0,
       
   989 				eMin = min - EPSILON,
       
   990 				eMax = max + EPSILON,
   981 				x1, x2 = Infinity,
   991 				x1, x2 = Infinity,
   982 				B = b,
   992 				B = b,
   983 				D;
   993 				D;
   984 			b /= 2;
   994 			b /= -2;
   985 			D = b * b - a * c;
   995 			D = b * b - a * c;
   986 			if (D !== 0 && abs(D) < MACHINE_EPSILON) {
   996 			if (D !== 0 && abs(D) < MACHINE_EPSILON) {
   987 				var gmC = pow(abs(a * b * c), 1 / 3);
   997 				var gmC = pow(abs(a * b * c), 1 / 3);
   988 				if (gmC < 1e-8) {
   998 				if (gmC < 1e-8) {
   989 					var mult = pow(10, abs(
   999 					var mult = pow(10,
   990 						Math.floor(Math.log(gmC) * Math.LOG10E)));
  1000 							abs(Math.floor(Math.log(gmC) * Math.LOG10E)));
   991 					if (!isFinite(mult))
  1001 					if (!isFinite(mult))
   992 						mult = 0;
  1002 						mult = 0;
   993 					a *= mult;
  1003 					a *= mult;
   994 					b *= mult;
  1004 					b *= mult;
   995 					c *= mult;
  1005 					c *= mult;
   998 			}
  1008 			}
   999 			if (abs(a) < EPSILON) {
  1009 			if (abs(a) < EPSILON) {
  1000 				if (abs(B) < EPSILON)
  1010 				if (abs(B) < EPSILON)
  1001 					return abs(c) < EPSILON ? -1 : 0;
  1011 					return abs(c) < EPSILON ? -1 : 0;
  1002 				x1 = -c / B;
  1012 				x1 = -c / B;
  1003 			} else {
  1013 			} else if (D >= -MACHINE_EPSILON) {
  1004 				if (D >= -MACHINE_EPSILON) {
  1014 				var Q = D < 0 ? 0 : sqrt(D),
  1005 					D = D < 0 ? 0 : D;
  1015 					R = b + (b < 0 ? -Q : Q);
  1006 					var R = sqrt(D);
  1016 				if (R === 0) {
  1007 					if (b >= MACHINE_EPSILON && b <= MACHINE_EPSILON) {
  1017 					x1 = c / a;
  1008 						x1 = abs(a) >= abs(c) ? R / a : -c / R;
  1018 					x2 = -x1;
  1009 						x2 = -x1;
  1019 				} else {
  1010 					} else {
  1020 					x1 = R / a;
  1011 						var q = -(b + (b < 0 ? -1 : 1) * R);
  1021 					x2 = c / R;
  1012 						x1 = q / a;
       
  1013 						x2 = c / q;
       
  1014 					}
       
  1015 				}
  1022 				}
  1016 			}
  1023 			}
  1017 			if (isFinite(x1) && (min == null || x1 >= min && x1 <= max))
  1024 			if (isFinite(x1) && (min == null || x1 > eMin && x1 < eMax))
  1018 				roots[count++] = x1;
  1025 				roots[count++] = min == null ? x1 : clip(x1, min, max);
  1019 			if (x2 !== x1
  1026 			if (x2 !== x1
  1020 					&& isFinite(x2) && (min == null || x2 >= min && x2 <= max))
  1027 					&& isFinite(x2) && (min == null || x2 > eMin && x2 < eMax))
  1021 				roots[count++] = x2;
  1028 				roots[count++] = min == null ? x2 : clip(x2, min, max);
  1022 			return count;
  1029 			return count;
  1023 		},
  1030 		},
  1024 
  1031 
  1025 		solveCubic: function(a, b, c, d, roots, min, max) {
  1032 		solveCubic: function(a, b, c, d, roots, min, max) {
  1026 			var count = 0,
  1033 			var count = 0,
  1069 					}
  1076 					}
  1070 				}
  1077 				}
  1071 			}
  1078 			}
  1072 			var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max);
  1079 			var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max);
  1073 			if (isFinite(x) && (count === 0 || x !== roots[count - 1])
  1080 			if (isFinite(x) && (count === 0 || x !== roots[count - 1])
  1074 					&& (min == null || x >= min && x <= max))
  1081 					&& (min == null || x > min - EPSILON && x < max + EPSILON))
  1075 				roots[count++] = x;
  1082 				roots[count++] = min == null ? x : clip(x, min, max);
  1076 			return count;
  1083 			return count;
  1077 		}
  1084 		}
  1078 	};
  1085 	};
  1079 };
  1086 };
  1080 
  1087 
  1257 	rotate: function(angle, center) {
  1264 	rotate: function(angle, center) {
  1258 		if (angle === 0)
  1265 		if (angle === 0)
  1259 			return this.clone();
  1266 			return this.clone();
  1260 		angle = angle * Math.PI / 180;
  1267 		angle = angle * Math.PI / 180;
  1261 		var point = center ? this.subtract(center) : this,
  1268 		var point = center ? this.subtract(center) : this,
  1262 			s = Math.sin(angle),
  1269 			sin = Math.sin(angle),
  1263 			c = Math.cos(angle);
  1270 			cos = Math.cos(angle);
  1264 		point = new Point(
  1271 		point = new Point(
  1265 			point.x * c - point.y * s,
  1272 			point.x * cos - point.y * sin,
  1266 			point.x * s + point.y * c
  1273 			point.x * sin + point.y * cos
  1267 		);
  1274 		);
  1268 		return center ? point.add(center) : point;
  1275 		return center ? point.add(center) : point;
  1269 	},
  1276 	},
  1270 
  1277 
  1271 	transform: function(matrix) {
  1278 	transform: function(matrix) {
  1303 
  1310 
  1304 	isInside: function() {
  1311 	isInside: function() {
  1305 		return Rectangle.read(arguments).contains(this);
  1312 		return Rectangle.read(arguments).contains(this);
  1306 	},
  1313 	},
  1307 
  1314 
  1308 	isClose: function(point, tolerance) {
  1315 	isClose: function() {
       
  1316 		var point = Point.read(arguments),
       
  1317 			tolerance = Base.read(arguments);
  1309 		return this.getDistance(point) < tolerance;
  1318 		return this.getDistance(point) < tolerance;
  1310 	},
  1319 	},
  1311 
  1320 
  1312 	isCollinear: function(point) {
  1321 	isCollinear: function() {
  1313 		return Math.abs(this.cross(point)) < 0.000001;
  1322 		var point = Point.read(arguments);
       
  1323 		return Point.isCollinear(this.x, this.y, point.x, point.y);
  1314 	},
  1324 	},
  1315 
  1325 
  1316 	isColinear: '#isCollinear',
  1326 	isColinear: '#isCollinear',
  1317 
  1327 
  1318 	isOrthogonal: function(point) {
  1328 	isOrthogonal: function() {
  1319 		return Math.abs(this.dot(point)) < 0.000001;
  1329 		var point = Point.read(arguments);
       
  1330 		return Point.isOrthogonal(this.x, this.y, point.x, point.y);
  1320 	},
  1331 	},
  1321 
  1332 
  1322 	isZero: function() {
  1333 	isZero: function() {
  1323 		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
  1334 		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
  1324 	},
  1335 	},
  1336 		var point = Point.read(arguments);
  1347 		var point = Point.read(arguments);
  1337 		return this.x * point.y - this.y * point.x;
  1348 		return this.x * point.y - this.y * point.x;
  1338 	},
  1349 	},
  1339 
  1350 
  1340 	project: function() {
  1351 	project: function() {
  1341 		var point = Point.read(arguments);
  1352 		var point = Point.read(arguments),
  1342 		if (point.isZero()) {
  1353 			scale = point.isZero() ? 0 : this.dot(point) / point.dot(point);
  1343 			return new Point(0, 0);
  1354 		return new Point(
  1344 		} else {
  1355 			point.x * scale,
  1345 			var scale = this.dot(point) / point.dot(point);
  1356 			point.y * scale
  1346 			return new Point(
  1357 		);
  1347 				point.x * scale,
       
  1348 				point.y * scale
       
  1349 			);
       
  1350 		}
       
  1351 	},
  1358 	},
  1352 
  1359 
  1353 	statics: {
  1360 	statics: {
  1354 		min: function() {
  1361 		min: function() {
  1355 			var point1 = Point.read(arguments),
  1362 			var point1 = Point.read(arguments),
  1369 			);
  1376 			);
  1370 		},
  1377 		},
  1371 
  1378 
  1372 		random: function() {
  1379 		random: function() {
  1373 			return new Point(Math.random(), Math.random());
  1380 			return new Point(Math.random(), Math.random());
       
  1381 		},
       
  1382 
       
  1383 		isCollinear: function(x1, y1, x2, y2) {
       
  1384 			return Math.abs(x1 * y2 - y1 * x2)
       
  1385 					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
       
  1386 						* 1e-7;
       
  1387 		},
       
  1388 
       
  1389 		isOrthogonal: function(x1, y1, x2, y2) {
       
  1390 			return Math.abs(x1 * x2 + y1 * y2)
       
  1391 					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
       
  1392 						* 1e-7;
  1374 		}
  1393 		}
  1375 	}
  1394 	}
  1376 }, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
  1395 }, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
  1377 	var op = Math[name];
  1396 	var op = Math[name];
  1378 	this[name] = function() {
  1397 	this[name] = function() {
  1920 		this._height = height;
  1939 		this._height = height;
  1921 		if (!_dontNotify)
  1940 		if (!_dontNotify)
  1922 			this._owner[this._setter](this);
  1941 			this._owner[this._setter](this);
  1923 		return this;
  1942 		return this;
  1924 	}
  1943 	}
  1925 }, new function() {
  1944 },
       
  1945 new function() {
  1926 	var proto = Rectangle.prototype;
  1946 	var proto = Rectangle.prototype;
  1927 
  1947 
  1928 	return Base.each(['x', 'y', 'width', 'height'], function(key) {
  1948 	return Base.each(['x', 'y', 'width', 'height'], function(key) {
  1929 		var part = Base.capitalize(key);
  1949 		var part = Base.capitalize(key);
  1930 		var internal = '_' + key;
  1950 		var internal = '_' + key;
  2253 	},
  2273 	},
  2254 
  2274 
  2255 	_transformBounds: function(bounds, dest, _dontNotify) {
  2275 	_transformBounds: function(bounds, dest, _dontNotify) {
  2256 		var coords = this._transformCorners(bounds),
  2276 		var coords = this._transformCorners(bounds),
  2257 			min = coords.slice(0, 2),
  2277 			min = coords.slice(0, 2),
  2258 			max = coords.slice();
  2278 			max = min.slice();
  2259 		for (var i = 2; i < 8; i++) {
  2279 		for (var i = 2; i < 8; i++) {
  2260 			var val = coords[i],
  2280 			var val = coords[i],
  2261 				j = i & 1;
  2281 				j = i & 1;
  2262 			if (val < min[j])
  2282 			if (val < min[j])
  2263 				min[j] = val;
  2283 				min[j] = val;
  2415 				this._px, this._py, this._vx, this._vy,
  2435 				this._px, this._py, this._vx, this._vy,
  2416 				line._px, line._py, line._vx, line._vy,
  2436 				line._px, line._py, line._vx, line._vy,
  2417 				true, isInfinite);
  2437 				true, isInfinite);
  2418 	},
  2438 	},
  2419 
  2439 
  2420 	getSide: function(point) {
  2440 	getSide: function(point, isInfinite) {
  2421 		return Line.getSide(
  2441 		return Line.getSide(
  2422 				this._px, this._py, this._vx, this._vy,
  2442 				this._px, this._py, this._vx, this._vy,
  2423 				point.x, point.y, true);
  2443 				point.x, point.y, true, isInfinite);
  2424 	},
  2444 	},
  2425 
  2445 
  2426 	getDistance: function(point) {
  2446 	getDistance: function(point) {
  2427 		return Math.abs(Line.getSignedDistance(
  2447 		return Math.abs(Line.getSignedDistance(
  2428 				this._px, this._py, this._vx, this._vy,
  2448 				this._px, this._py, this._vx, this._vy,
  2429 				point.x, point.y, true));
  2449 				point.x, point.y, true));
  2430 	},
  2450 	},
  2431 
  2451 
       
  2452 	isCollinear: function(line) {
       
  2453 		return Point.isCollinear(this._vx, this._vy, line._vx, line._vy);
       
  2454 	},
       
  2455 
       
  2456 	isOrthogonal: function(line) {
       
  2457 		return Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);
       
  2458 	},
       
  2459 
  2432 	statics: {
  2460 	statics: {
  2433 		intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector,
  2461 		intersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,
  2434 				isInfinite) {
  2462 				isInfinite) {
  2435 			if (!asVector) {
  2463 			if (!asVector) {
  2436 				avx -= apx;
  2464 				v1x -= p1x;
  2437 				avy -= apy;
  2465 				v1y -= p1y;
  2438 				bvx -= bpx;
  2466 				v2x -= p2x;
  2439 				bvy -= bpy;
  2467 				v2y -= p2y;
  2440 			}
  2468 			}
  2441 			var cross = avx * bvy - avy * bvx;
  2469 			var cross = v1x * v2y - v1y * v2x;
  2442 			if (!Numerical.isZero(cross)) {
  2470 			if (!Numerical.isZero(cross)) {
  2443 				var dx = apx - bpx,
  2471 				var dx = p1x - p2x,
  2444 					dy = apy - bpy,
  2472 					dy = p1y - p2y,
  2445 					ta = (bvx * dy - bvy * dx) / cross,
  2473 					u1 = (v2x * dy - v2y * dx) / cross,
  2446 					tb = (avx * dy - avy * dx) / cross;
  2474 					u2 = (v1x * dy - v1y * dx) / cross,
  2447 				if (isInfinite || 0 <= ta && ta <= 1 && 0 <= tb && tb <= 1)
  2475 					epsilon = 1e-12,
       
  2476 					uMin = -epsilon,
       
  2477 					uMax = 1 + epsilon;
       
  2478 				if (isInfinite
       
  2479 						|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {
       
  2480 					if (!isInfinite) {
       
  2481 						u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;
       
  2482 					}
  2448 					return new Point(
  2483 					return new Point(
  2449 								apx + ta * avx,
  2484 							p1x + u1 * v1x,
  2450 								apy + ta * avy);
  2485 							p1y + u1 * v1y);
  2451 			}
  2486 				}
  2452 		},
  2487 			}
  2453 
  2488 		},
  2454 		getSide: function(px, py, vx, vy, x, y, asVector) {
  2489 
       
  2490 		getSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {
  2455 			if (!asVector) {
  2491 			if (!asVector) {
  2456 				vx -= px;
  2492 				vx -= px;
  2457 				vy -= py;
  2493 				vy -= py;
  2458 			}
  2494 			}
  2459 			var v2x = x - px,
  2495 			var v2x = x - px,
  2460 				v2y = y - py,
  2496 				v2y = y - py,
  2461 				ccw = v2x * vy - v2y * vx;
  2497 				ccw = v2x * vy - v2y * vx;
  2462 			if (ccw === 0) {
  2498 			if (ccw === 0 && !isInfinite) {
  2463 				ccw = v2x * vx + v2y * vy;
  2499 				ccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);
  2464 				if (ccw > 0) {
  2500 				if (ccw >= 0 && ccw <= 1)
  2465 					v2x -= vx;
  2501 					ccw = 0;
  2466 					v2y -= vy;
       
  2467 					ccw = v2x * vx + v2y * vy;
       
  2468 					if (ccw < 0)
       
  2469 						ccw = 0;
       
  2470 				}
       
  2471 			}
  2502 			}
  2472 			return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
  2503 			return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
  2473 		},
  2504 		},
  2474 
  2505 
  2475 		getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
  2506 		getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
  2476 			if (!asVector) {
  2507 			if (!asVector) {
  2477 				vx -= px;
  2508 				vx -= px;
  2478 				vy -= py;
  2509 				vy -= py;
  2479 			}
  2510 			}
  2480 			return Numerical.isZero(vx)
  2511 			return vx === 0 ? vy > 0 ? x - px : px - x
  2481 					? vy >= 0 ? px - x : x - px
  2512 				 : vy === 0 ? vx < 0 ? y - py : py - y
  2482 					: Numerical.isZero(vy)
  2513 				 : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);
  2483 						? vx >= 0 ? y - py : py - y
       
  2484 						: (vx * (y - py) - vy * (x - px)) / Math.sqrt(vx * vx + vy * vy);
       
  2485 		}
  2514 		}
  2486 	}
  2515 	}
  2487 });
  2516 });
  2488 
  2517 
  2489 var Project = PaperScopeItem.extend({
  2518 var Project = PaperScopeItem.extend({
  2781 			this._set(props, { insert: true, project: true, parent: true },
  2810 			this._set(props, { insert: true, project: true, parent: true },
  2782 					true);
  2811 					true);
  2783 		return hasProps;
  2812 		return hasProps;
  2784 	},
  2813 	},
  2785 
  2814 
  2786 	_events: new function() {
  2815 	_events: Base.each(['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
  2787 
  2816 			'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'],
  2788 		var mouseFlags = {
  2817 		function(name) {
  2789 			mousedown: {
  2818 			this[name] = {
  2790 				mousedown: 1,
  2819 				install: function(type) {
  2791 				mousedrag: 1,
  2820 					this.getView()._installEvent(type);
  2792 				click: 1,
  2821 				},
  2793 				doubleclick: 1
  2822 
  2794 			},
  2823 				uninstall: function(type) {
  2795 			mouseup: {
  2824 					this.getView()._uninstallEvent(type);
  2796 				mouseup: 1,
  2825 				}
  2797 				mousedrag: 1,
  2826 			};
  2798 				click: 1,
  2827 		}, {
  2799 				doubleclick: 1
  2828 			onFrame: {
  2800 			},
  2829 				install: function() {
  2801 			mousemove: {
  2830 					this.getView()._animateItem(this, true);
  2802 				mousedrag: 1,
  2831 				},
  2803 				mousemove: 1,
  2832 
  2804 				mouseenter: 1,
  2833 				uninstall: function() {
  2805 				mouseleave: 1
  2834 					this.getView()._animateItem(this, false);
  2806 			}
       
  2807 		};
       
  2808 
       
  2809 		var mouseEvent = {
       
  2810 			install: function(type) {
       
  2811 				var counters = this.getView()._eventCounters;
       
  2812 				if (counters) {
       
  2813 					for (var key in mouseFlags) {
       
  2814 						counters[key] = (counters[key] || 0)
       
  2815 								+ (mouseFlags[key][type] || 0);
       
  2816 					}
       
  2817 				}
  2835 				}
  2818 			},
  2836 			},
  2819 			uninstall: function(type) {
  2837 
  2820 				var counters = this.getView()._eventCounters;
  2838 			onLoad: {}
  2821 				if (counters) {
  2839 		}
  2822 					for (var key in mouseFlags)
  2840 	),
  2823 						counters[key] -= mouseFlags[key][type] || 0;
       
  2824 				}
       
  2825 			}
       
  2826 		};
       
  2827 
       
  2828 		return Base.each(['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
       
  2829 			'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'],
       
  2830 			function(name) {
       
  2831 				this[name] = mouseEvent;
       
  2832 			}, {
       
  2833 				onFrame: {
       
  2834 					install: function() {
       
  2835 						this._animateItem(true);
       
  2836 					},
       
  2837 					uninstall: function() {
       
  2838 						this._animateItem(false);
       
  2839 					}
       
  2840 				},
       
  2841 
       
  2842 				onLoad: {}
       
  2843 			}
       
  2844 		);
       
  2845 	},
       
  2846 
       
  2847 	_animateItem: function(animate) {
       
  2848 		this.getView()._animateItem(this, animate);
       
  2849 	},
       
  2850 
  2841 
  2851 	_serialize: function(options, dictionary) {
  2842 	_serialize: function(options, dictionary) {
  2852 		var props = {},
  2843 		var props = {},
  2853 			that = this;
  2844 			that = this;
  2854 
  2845 
  3450 	},
  3441 	},
  3451 
  3442 
  3452 	intersects: function(item, _matrix) {
  3443 	intersects: function(item, _matrix) {
  3453 		if (!(item instanceof Item))
  3444 		if (!(item instanceof Item))
  3454 			return false;
  3445 			return false;
  3455 		return this._asPathItem().getIntersections(item._asPathItem(),
  3446 		return this._asPathItem().getIntersections(item._asPathItem(), null,
  3456 				_matrix || item._matrix).length > 0;
  3447 				_matrix || item._matrix, true).length > 0;
  3457 	},
  3448 	},
  3458 
  3449 
  3459 	hitTest: function() {
  3450 	hitTest: function() {
  3460 		return this._hitTest(
  3451 		return this._hitTest(
  3461 				Point.read(arguments),
  3452 				Point.read(arguments),
  3474 					? parentTotalMatrix.chain(matrix)
  3465 					? parentTotalMatrix.chain(matrix)
  3475 					: this.getGlobalMatrix().preConcatenate(view._matrix),
  3466 					: this.getGlobalMatrix().preConcatenate(view._matrix),
  3476 			tolerancePadding = options._tolerancePadding = new Size(
  3467 			tolerancePadding = options._tolerancePadding = new Size(
  3477 						Path._getPenPadding(1, totalMatrix.inverted())
  3468 						Path._getPenPadding(1, totalMatrix.inverted())
  3478 					).multiply(
  3469 					).multiply(
  3479 						Math.max(options.tolerance, 0.000001)
  3470 						Math.max(options.tolerance, 1e-6)
  3480 					);
  3471 					);
  3481 		point = matrix._inverseTransform(point);
  3472 		point = matrix._inverseTransform(point);
  3482 
  3473 
  3483 		if (!this._children && !this.getInternalRoughBounds()
  3474 		if (!this._children && !this.getInternalRoughBounds()
  3484 				.expand(tolerancePadding.multiply(2))._containsPoint(point))
  3475 				.expand(tolerancePadding.multiply(2))._containsPoint(point))
  3597 				firstOnly) {
  3588 				firstOnly) {
  3598 			if (!param && typeof match === 'object') {
  3589 			if (!param && typeof match === 'object') {
  3599 				var overlapping = match.overlapping,
  3590 				var overlapping = match.overlapping,
  3600 					inside = match.inside,
  3591 					inside = match.inside,
  3601 					bounds = overlapping || inside,
  3592 					bounds = overlapping || inside,
  3602 					rect =	bounds && Rectangle.read([bounds]);
  3593 					rect = bounds && Rectangle.read([bounds]);
  3603 				param = {
  3594 				param = {
  3604 					items: [],
  3595 					items: [],
  3605 					inside: !!inside,
  3596 					inside: !!inside,
  3606 					overlapping: !!overlapping,
  3597 					overlapping: !!overlapping,
  3607 					rect: rect,
  3598 					rect: rect,
  3899 		return false;
  3890 		return false;
  3900 	},
  3891 	},
  3901 
  3892 
  3902 	isAncestor: function(item) {
  3893 	isAncestor: function(item) {
  3903 		return item ? item.isDescendant(this) : false;
  3894 		return item ? item.isDescendant(this) : false;
       
  3895 	},
       
  3896 
       
  3897 	isSibling: function(item) {
       
  3898 		return this._parent === item._parent;
  3904 	},
  3899 	},
  3905 
  3900 
  3906 	isGroupedWith: function(item) {
  3901 	isGroupedWith: function(item) {
  3907 		var parent = this._parent;
  3902 		var parent = this._parent;
  3908 		while (parent) {
  3903 		while (parent) {
  4176 			ctx.strokeStyle = ctx.fillStyle = color
  4171 			ctx.strokeStyle = ctx.fillStyle = color
  4177 					? color.toCanvasStyle(ctx) : '#009dec';
  4172 					? color.toCanvasStyle(ctx) : '#009dec';
  4178 			if (this._drawSelected)
  4173 			if (this._drawSelected)
  4179 				this._drawSelected(ctx, mx, selectedItems);
  4174 				this._drawSelected(ctx, mx, selectedItems);
  4180 			if (this._boundsSelected) {
  4175 			if (this._boundsSelected) {
  4181 				var half = size / 2;
  4176 				var half = size / 2,
  4182 					coords = mx._transformCorners(this.getInternalBounds());
  4177 					coords = mx._transformCorners(this.getInternalBounds());
  4183 				ctx.beginPath();
  4178 				ctx.beginPath();
  4184 				for (var i = 0; i < 8; i++)
  4179 				for (var i = 0; i < 8; i++)
  4185 					ctx[i === 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);
  4180 					ctx[i === 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);
  4186 				ctx.closePath();
  4181 				ctx.closePath();
  4555 			rect = rect.expand(this.getStrokeWidth());
  4550 			rect = rect.expand(this.getStrokeWidth());
  4556 		return matrix ? matrix._transformBounds(rect) : rect;
  4551 		return matrix ? matrix._transformBounds(rect) : rect;
  4557 	}
  4552 	}
  4558 },
  4553 },
  4559 new function() {
  4554 new function() {
  4560 
       
  4561 	function getCornerCenter(that, point, expand) {
  4555 	function getCornerCenter(that, point, expand) {
  4562 		var radius = that._radius;
  4556 		var radius = that._radius;
  4563 		if (!radius.isZero()) {
  4557 		if (!radius.isZero()) {
  4564 			var halfSize = that._size.divide(2);
  4558 			var halfSize = that._size.divide(2);
  4565 			for (var i = 0; i < 4; i++) {
  4559 			for (var i = 0; i < 4; i++) {
  4900 	toDataURL: function() {
  4894 	toDataURL: function() {
  4901 		var src = this._image && this._image.src;
  4895 		var src = this._image && this._image.src;
  4902 		if (/^data:/.test(src))
  4896 		if (/^data:/.test(src))
  4903 			return src;
  4897 			return src;
  4904 		var canvas = this.getCanvas();
  4898 		var canvas = this.getCanvas();
  4905 		return canvas ? canvas.toDataURL() : null;
  4899 		return canvas ? canvas.toDataURL.apply(canvas, arguments) : null;
  4906 	},
  4900 	},
  4907 
  4901 
  4908 	drawImage: function(image ) {
  4902 	drawImage: function(image ) {
  4909 		var point = Point.read(arguments, 1);
  4903 		var point = Point.read(arguments, 1);
  4910 		this.getContext(true).drawImage(image, point.x, point.y);
  4904 		this.getContext(true).drawImage(image, point.x, point.y);
  5131 	initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
  5125 	initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
  5132 		var count = arguments.length,
  5126 		var count = arguments.length,
  5133 			point, handleIn, handleOut;
  5127 			point, handleIn, handleOut;
  5134 		if (count === 0) {
  5128 		if (count === 0) {
  5135 		} else if (count === 1) {
  5129 		} else if (count === 1) {
  5136 			if (arg0.point) {
  5130 			if ('point' in arg0) {
  5137 				point = arg0.point;
  5131 				point = arg0.point;
  5138 				handleIn = arg0.handleIn;
  5132 				handleIn = arg0.handleIn;
  5139 				handleOut = arg0.handleOut;
  5133 				handleOut = arg0.handleOut;
  5140 			} else {
  5134 			} else {
  5141 				point = arg0;
  5135 				point = arg0;
  5155 		new SegmentPoint(handleIn, this, '_handleIn');
  5149 		new SegmentPoint(handleIn, this, '_handleIn');
  5156 		new SegmentPoint(handleOut, this, '_handleOut');
  5150 		new SegmentPoint(handleOut, this, '_handleOut');
  5157 	},
  5151 	},
  5158 
  5152 
  5159 	_serialize: function(options) {
  5153 	_serialize: function(options) {
  5160 		return Base.serialize(this.isStraight() ? this._point
  5154 		return Base.serialize(this.hasHandles()
  5161 				: [this._point, this._handleIn, this._handleOut],
  5155 				? [this._point, this._handleIn, this._handleOut]
       
  5156 				: this._point,
  5162 				options, true);
  5157 				options, true);
  5163 	},
  5158 	},
  5164 
  5159 
  5165 	_changed: function(point) {
  5160 	_changed: function(point) {
  5166 		var path = this._path;
  5161 		var path = this._path;
  5207 		var point = Point.read(arguments);
  5202 		var point = Point.read(arguments);
  5208 		this._handleOut.set(point.x, point.y);
  5203 		this._handleOut.set(point.x, point.y);
  5209 	},
  5204 	},
  5210 
  5205 
  5211 	hasHandles: function() {
  5206 	hasHandles: function() {
  5212 		return !this.isStraight();
  5207 		return !this._handleIn.isZero() || !this._handleOut.isZero();
  5213 	},
  5208 	},
  5214 
  5209 
  5215 	isStraight: function() {
  5210 	clearHandles: function() {
  5216 		return this._handleIn.isZero() && this._handleOut.isZero();
  5211 		this._handleIn.set(0, 0);
  5217 	},
  5212 		this._handleOut.set(0, 0);
  5218 
  5213 	},
  5219 	isLinear: function() {
       
  5220 		return Segment.isLinear(this, this.getNext());
       
  5221 	},
       
  5222 
       
  5223 	isCollinear: function(segment) {
       
  5224 		return Segment.isCollinear(this, this.getNext(),
       
  5225 				segment, segment.getNext());
       
  5226 	},
       
  5227 
       
  5228 	isColinear: '#isCollinear',
       
  5229 
       
  5230 	isOrthogonal: function() {
       
  5231 		return Segment.isOrthogonal(this.getPrevious(), this, this.getNext());
       
  5232 	},
       
  5233 
       
  5234 	isOrthogonalArc: function() {
       
  5235 		return Segment.isOrthogonalArc(this, this.getNext());
       
  5236 	},
       
  5237 
       
  5238 	isArc: '#isOrthogonalArc',
       
  5239 
  5214 
  5240 	_selectionState: 0,
  5215 	_selectionState: 0,
  5241 
  5216 
  5242 	isSelected: function(_point) {
  5217 	isSelected: function(_point) {
  5243 		var state = this._selectionState;
  5218 		var state = this._selectionState;
  5307 		var segments = this._path && this._path._segments;
  5282 		var segments = this._path && this._path._segments;
  5308 		return segments && (segments[this._index - 1]
  5283 		return segments && (segments[this._index - 1]
  5309 				|| this._path._closed && segments[segments.length - 1]) || null;
  5284 				|| this._path._closed && segments[segments.length - 1]) || null;
  5310 	},
  5285 	},
  5311 
  5286 
       
  5287 	isFirst: function() {
       
  5288 		return this._index === 0;
       
  5289 	},
       
  5290 
       
  5291 	isLast: function() {
       
  5292 		var path = this._path;
       
  5293 		return path && this._index === path._segments.length - 1 || false;
       
  5294 	},
       
  5295 
  5312 	reverse: function() {
  5296 	reverse: function() {
       
  5297 		var handleIn = this._handleIn,
       
  5298 			handleOut = this._handleOut,
       
  5299 			inX = handleIn._x,
       
  5300 			inY = handleIn._y;
       
  5301 		handleIn.set(handleOut._x, handleOut._y);
       
  5302 		handleOut.set(inX, inY);
       
  5303 	},
       
  5304 
       
  5305 	reversed: function() {
  5313 		return new Segment(this._point, this._handleOut, this._handleIn);
  5306 		return new Segment(this._point, this._handleOut, this._handleIn);
  5314 	},
  5307 	},
  5315 
  5308 
  5316 	remove: function() {
  5309 	remove: function() {
  5317 		return this._path ? !!this._path.removeSegment(this._index) : false;
  5310 		return this._path ? !!this._path.removeSegment(this._index) : false;
  5388 					coords[i++] = y;
  5381 					coords[i++] = y;
  5389 				}
  5382 				}
  5390 			}
  5383 			}
  5391 		}
  5384 		}
  5392 		return coords;
  5385 		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 		},
       
  5433 	}
  5386 	}
  5434 });
  5387 });
  5435 
  5388 
  5436 var SegmentPoint = Point.extend({
  5389 var SegmentPoint = Point.extend({
  5437 	initialize: function SegmentPoint(point, owner, key) {
  5390 	initialize: function SegmentPoint(point, owner, key) {
  5506 
  5459 
  5507 var Curve = Base.extend({
  5460 var Curve = Base.extend({
  5508 	_class: 'Curve',
  5461 	_class: 'Curve',
  5509 
  5462 
  5510 	initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
  5463 	initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
  5511 		var count = arguments.length;
  5464 		var count = arguments.length,
       
  5465 			seg1, seg2,
       
  5466 			point1, point2,
       
  5467 			handle1, handle2;
  5512 		if (count === 3) {
  5468 		if (count === 3) {
  5513 			this._path = arg0;
  5469 			this._path = arg0;
  5514 			this._segment1 = arg1;
  5470 			seg1 = arg1;
  5515 			this._segment2 = arg2;
  5471 			seg2 = arg2;
  5516 		} else if (count === 0) {
  5472 		} else if (count === 0) {
  5517 			this._segment1 = new Segment();
  5473 			seg1 = new Segment();
  5518 			this._segment2 = new Segment();
  5474 			seg2 = new Segment();
  5519 		} else if (count === 1) {
  5475 		} else if (count === 1) {
  5520 			this._segment1 = new Segment(arg0.segment1);
  5476 			if ('segment1' in arg0) {
  5521 			this._segment2 = new Segment(arg0.segment2);
  5477 				seg1 = new Segment(arg0.segment1);
       
  5478 				seg2 = new Segment(arg0.segment2);
       
  5479 			} else if ('point1' in arg0) {
       
  5480 				point1 = arg0.point1;
       
  5481 				handle1 = arg0.handle1;
       
  5482 				handle2 = arg0.handle2;
       
  5483 				point2 = arg0.point2;
       
  5484 			} else if (Array.isArray(arg0)) {
       
  5485 				point1 = [arg0[0], arg0[1]];
       
  5486 				point2 = [arg0[6], arg0[7]];
       
  5487 				handle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];
       
  5488 				handle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];
       
  5489 			}
  5522 		} else if (count === 2) {
  5490 		} else if (count === 2) {
  5523 			this._segment1 = new Segment(arg0);
  5491 			seg1 = new Segment(arg0);
  5524 			this._segment2 = new Segment(arg1);
  5492 			seg2 = new Segment(arg1);
  5525 		} else {
  5493 		} else if (count === 4) {
  5526 			var point1, handle1, handle2, point2;
  5494 			point1 = arg0;
  5527 			if (count === 4) {
  5495 			handle1 = arg1;
  5528 				point1 = arg0;
  5496 			handle2 = arg2;
  5529 				handle1 = arg1;
  5497 			point2 = arg3;
  5530 				handle2 = arg2;
  5498 		} else if (count === 8) {
  5531 				point2 = arg3;
  5499 			point1 = [arg0, arg1];
  5532 			} else if (count === 8) {
  5500 			point2 = [arg6, arg7];
  5533 				point1 = [arg0, arg1];
  5501 			handle1 = [arg2 - arg0, arg3 - arg1];
  5534 				point2 = [arg6, arg7];
  5502 			handle2 = [arg4 - arg6, arg5 - arg7];
  5535 				handle1 = [arg2 - arg0, arg3 - arg1];
  5503 		}
  5536 				handle2 = [arg4 - arg6, arg5 - arg7];
  5504 		this._segment1 = seg1 || new Segment(point1, null, handle1);
  5537 			}
  5505 		this._segment2 = seg2 || new Segment(point2, handle2, null);
  5538 			this._segment1 = new Segment(point1, null, handle1);
  5506 	},
  5539 			this._segment2 = new Segment(point2, handle2, null);
  5507 
  5540 		}
  5508 	_serialize: function(options) {
       
  5509 		return Base.serialize(this.hasHandles()
       
  5510 				? [this.getPoint1(), this.getHandle1(), this.getHandle2(),
       
  5511 					this.getPoint2()]
       
  5512 				: [this.getPoint1(), this.getPoint2()],
       
  5513 				options, true);
  5541 	},
  5514 	},
  5542 
  5515 
  5543 	_changed: function() {
  5516 	_changed: function() {
  5544 		this._length = this._bounds = undefined;
  5517 		this._length = this._bounds = undefined;
       
  5518 	},
       
  5519 
       
  5520 	clone: function() {
       
  5521 		return new Curve(this._segment1, this._segment2);
       
  5522 	},
       
  5523 
       
  5524 	toString: function() {
       
  5525 		var parts = [ 'point1: ' + this._segment1._point ];
       
  5526 		if (!this._segment1._handleOut.isZero())
       
  5527 			parts.push('handle1: ' + this._segment1._handleOut);
       
  5528 		if (!this._segment2._handleIn.isZero())
       
  5529 			parts.push('handle2: ' + this._segment2._handleIn);
       
  5530 		parts.push('point2: ' + this._segment2._point);
       
  5531 		return '{ ' + parts.join(', ') + ' }';
       
  5532 	},
       
  5533 
       
  5534 	remove: function() {
       
  5535 		var removed = false;
       
  5536 		if (this._path) {
       
  5537 			var segment2 = this._segment2,
       
  5538 				handleOut = segment2._handleOut;
       
  5539 			removed = segment2.remove();
       
  5540 			if (removed)
       
  5541 				this._segment1._handleOut.set(handleOut.x, handleOut.y);
       
  5542 		}
       
  5543 		return removed;
  5545 	},
  5544 	},
  5546 
  5545 
  5547 	getPoint1: function() {
  5546 	getPoint1: function() {
  5548 		return this._segment1._point;
  5547 		return this._segment1._point;
  5549 	},
  5548 	},
  5604 
  5603 
  5605 	getPrevious: function() {
  5604 	getPrevious: function() {
  5606 		var curves = this._path && this._path._curves;
  5605 		var curves = this._path && this._path._curves;
  5607 		return curves && (curves[this._segment1._index - 1]
  5606 		return curves && (curves[this._segment1._index - 1]
  5608 				|| this._path._closed && curves[curves.length - 1]) || null;
  5607 				|| this._path._closed && curves[curves.length - 1]) || null;
       
  5608 	},
       
  5609 
       
  5610 	isFirst: function() {
       
  5611 		return this._segment1._index === 0;
       
  5612 	},
       
  5613 
       
  5614 	isLast: function() {
       
  5615 		var path = this._path;
       
  5616 		return path && this._segment1._index === path._curves.length - 1
       
  5617 				|| false;
  5609 	},
  5618 	},
  5610 
  5619 
  5611 	isSelected: function() {
  5620 	isSelected: function() {
  5612 		return this.getPoint1().isSelected()
  5621 		return this.getPoint1().isSelected()
  5613 				&& this.getHandle2().isSelected()
  5622 				&& this.getHandle2().isSelected()
  5633 			points.push(new Point(coords[i], coords[i + 1]));
  5642 			points.push(new Point(coords[i], coords[i + 1]));
  5634 		return points;
  5643 		return points;
  5635 	},
  5644 	},
  5636 
  5645 
  5637 	getLength: function() {
  5646 	getLength: function() {
  5638 		if (this._length == null) {
  5647 		if (this._length == null)
  5639 			this._length = this.isLinear()
  5648 			this._length = Curve.getLength(this.getValues(), 0, 1);
  5640 				? this._segment2._point.getDistance(this._segment1._point)
       
  5641 				: Curve.getLength(this.getValues(), 0, 1);
       
  5642 		}
       
  5643 		return this._length;
  5649 		return this._length;
  5644 	},
  5650 	},
  5645 
  5651 
  5646 	getArea: function() {
  5652 	getArea: function() {
  5647 		return Curve.getArea(this.getValues());
  5653 		return Curve.getArea(this.getValues());
  5648 	},
  5654 	},
  5649 
  5655 
       
  5656 	getLine: function() {
       
  5657 		return new Line(this._segment1._point, this._segment2._point);
       
  5658 	},
       
  5659 
  5650 	getPart: function(from, to) {
  5660 	getPart: function(from, to) {
  5651 		return new Curve(Curve.getPart(this.getValues(), from, to));
  5661 		return new Curve(Curve.getPart(this.getValues(), from, to));
  5652 	},
  5662 	},
  5653 
  5663 
  5654 	getPartLength: function(from, to) {
  5664 	getPartLength: function(from, to) {
  5655 		return Curve.getLength(this.getValues(), from, to);
  5665 		return Curve.getLength(this.getValues(), from, to);
  5656 	},
  5666 	},
  5657 
  5667 
  5658 	hasHandles: function() {
       
  5659 		return !this._segment1._handleOut.isZero()
       
  5660 				|| !this._segment2._handleIn.isZero();
       
  5661 	},
       
  5662 
       
  5663 	isLinear: function() {
       
  5664 		return Segment.isLinear(this._segment1, this._segment2);
       
  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);
       
  5674 	},
       
  5675 
       
  5676 	getIntersections: function(curve) {
  5668 	getIntersections: function(curve) {
  5677 		return Curve.filterIntersections(Curve.getIntersections(
  5669 		return Curve._getIntersections(this.getValues(),
  5678 				this.getValues(), curve.getValues(), this, curve, []));
  5670 				curve && curve !== this ? curve.getValues() : null,
       
  5671 				this, curve, [], {});
  5679 	},
  5672 	},
  5680 
  5673 
  5681 	_getParameter: function(offset, isParameter) {
  5674 	_getParameter: function(offset, isParameter) {
  5682 		return isParameter
  5675 		return isParameter
  5683 				? offset
  5676 				? offset
  5686 					: offset === undefined && isParameter === undefined
  5679 					: offset === undefined && isParameter === undefined
  5687 						? 0.5
  5680 						? 0.5
  5688 						: this.getParameterAt(offset, 0);
  5681 						: this.getParameterAt(offset, 0);
  5689 	},
  5682 	},
  5690 
  5683 
  5691 	divide: function(offset, isParameter, ignoreLinear) {
  5684 	divide: function(offset, isParameter, _setHandles) {
  5692 		var parameter = this._getParameter(offset, isParameter),
  5685 		var parameter = this._getParameter(offset, isParameter),
  5693 			tolerance = 0.000001,
  5686 			tMin = 4e-7,
       
  5687 			tMax = 1 - tMin,
  5694 			res = null;
  5688 			res = null;
  5695 		if (parameter > tolerance && parameter < 1 - tolerance) {
  5689 		if (parameter >= tMin && parameter <= tMax) {
  5696 			var parts = Curve.subdivide(this.getValues(), parameter),
  5690 			var parts = Curve.subdivide(this.getValues(), parameter),
  5697 				isLinear = ignoreLinear ? false : this.isLinear(),
       
  5698 				left = parts[0],
  5691 				left = parts[0],
  5699 				right = parts[1];
  5692 				right = parts[1],
  5700 
  5693 				setHandles = _setHandles || this.hasHandles(),
  5701 			if (!isLinear) {
  5694 				segment1 = this._segment1,
  5702 				this._segment1._handleOut.set(left[2] - left[0],
  5695 				segment2 = this._segment2,
       
  5696 				path = this._path;
       
  5697 			if (setHandles) {
       
  5698 				segment1._handleOut.set(left[2] - left[0],
  5703 						left[3] - left[1]);
  5699 						left[3] - left[1]);
  5704 				this._segment2._handleIn.set(right[4] - right[6],
  5700 				segment2._handleIn.set(right[4] - right[6],
  5705 						right[5] - right[7]);
  5701 						right[5] - right[7]);
  5706 			}
  5702 			}
  5707 
       
  5708 			var x = left[6], y = left[7],
  5703 			var x = left[6], y = left[7],
  5709 				segment = new Segment(new Point(x, y),
  5704 				segment = new Segment(new Point(x, y),
  5710 						!isLinear && new Point(left[4] - x, left[5] - y),
  5705 						setHandles && new Point(left[4] - x, left[5] - y),
  5711 						!isLinear && new Point(right[2] - x, right[3] - y));
  5706 						setHandles && new Point(right[2] - x, right[3] - y));
  5712 
  5707 			if (path) {
  5713 			if (this._path) {
  5708 				path.insert(segment1._index + 1, segment);
  5714 				if (this._segment1._index > 0 && this._segment2._index === 0) {
  5709 				res = this.getNext();
  5715 					this._path.add(segment);
       
  5716 				} else {
       
  5717 					this._path.insert(this._segment2._index, segment);
       
  5718 				}
       
  5719 				res = this;
       
  5720 			} else {
  5710 			} else {
  5721 				var end = this._segment2;
       
  5722 				this._segment2 = segment;
  5711 				this._segment2 = segment;
  5723 				res = new Curve(segment, end);
  5712 				res = new Curve(segment, segment2);
  5724 			}
  5713 			}
  5725 		}
  5714 		}
  5726 		return res;
  5715 		return res;
  5727 	},
  5716 	},
  5728 
  5717 
  5731 			? this._path.split(this._segment1._index,
  5720 			? this._path.split(this._segment1._index,
  5732 					this._getParameter(offset, isParameter))
  5721 					this._getParameter(offset, isParameter))
  5733 			: null;
  5722 			: null;
  5734 	},
  5723 	},
  5735 
  5724 
  5736 	reverse: function() {
  5725 	reversed: function() {
  5737 		return new Curve(this._segment2.reverse(), this._segment1.reverse());
  5726 		return new Curve(this._segment2.reversed(), this._segment1.reversed());
  5738 	},
  5727 	},
  5739 
  5728 
  5740 	remove: function() {
  5729 	clearHandles: function() {
  5741 		var removed = false;
  5730 		this._segment1._handleOut.set(0, 0);
  5742 		if (this._path) {
  5731 		this._segment2._handleIn.set(0, 0);
  5743 			var segment2 = this._segment2,
       
  5744 				handleOut = segment2._handleOut;
       
  5745 			removed = segment2.remove();
       
  5746 			if (removed)
       
  5747 				this._segment1._handleOut.set(handleOut.x, handleOut.y);
       
  5748 		}
       
  5749 		return removed;
       
  5750 	},
       
  5751 
       
  5752 	clone: function() {
       
  5753 		return new Curve(this._segment1, this._segment2);
       
  5754 	},
       
  5755 
       
  5756 	toString: function() {
       
  5757 		var parts = [ 'point1: ' + this._segment1._point ];
       
  5758 		if (!this._segment1._handleOut.isZero())
       
  5759 			parts.push('handle1: ' + this._segment1._handleOut);
       
  5760 		if (!this._segment2._handleIn.isZero())
       
  5761 			parts.push('handle2: ' + this._segment2._handleIn);
       
  5762 		parts.push('point2: ' + this._segment2._point);
       
  5763 		return '{ ' + parts.join(', ') + ' }';
       
  5764 	},
  5732 	},
  5765 
  5733 
  5766 statics: {
  5734 statics: {
  5767 	getValues: function(segment1, segment2, matrix) {
  5735 	getValues: function(segment1, segment2, matrix) {
  5768 		var p1 = segment1._point,
  5736 		var p1 = segment1._point,
  5809 			b = 3 * (c2 - c1) - c,
  5777 			b = 3 * (c2 - c1) - c,
  5810 			a = p2 - p1 - c - b;
  5778 			a = p2 - p1 - c - b;
  5811 		return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
  5779 		return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
  5812 	},
  5780 	},
  5813 
  5781 
  5814 	getParameterOf: function(v, x, y) {
  5782 	getParameterOf: function(v, point) {
  5815 		var tolerance = 0.000001;
  5783 		var p1 = new Point(v[0], v[1]),
  5816 		if (Math.abs(v[0] - x) < tolerance && Math.abs(v[1] - y) < tolerance)
  5784 			p2 = new Point(v[6], v[7]),
  5817 			return 0;
  5785 			epsilon = 1e-12,
  5818 		if (Math.abs(v[6] - x) < tolerance && Math.abs(v[7] - y) < tolerance)
  5786 			t = point.isClose(p1, epsilon) ? 0
  5819 			return 1;
  5787 			  : point.isClose(p2, epsilon) ? 1
  5820 		var txs = [],
  5788 			  : null;
  5821 			tys = [],
  5789 		if (t !== null)
  5822 			sx = Curve.solveCubic(v, 0, x, txs, 0, 1),
  5790 			return t;
  5823 			sy = Curve.solveCubic(v, 1, y, tys, 0, 1),
  5791 		var coords = [point.x, point.y],
  5824 			tx, ty;
  5792 			roots = [],
  5825 		for (var cx = 0;  sx === -1 || cx < sx;) {
  5793 			geomEpsilon = 2e-7;
  5826 			if (sx === -1 || (tx = txs[cx++]) > 0 && tx < 1) {
  5794 		for (var c = 0; c < 2; c++) {
  5827 				for (var cy = 0; sy === -1 || cy < sy;) {
  5795 			var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);
  5828 					if (sy === -1 || (ty = tys[cy++]) > 0 && ty < 1) {
  5796 			for (var i = 0; i < count; i++) {
  5829 						if (sx === -1) {
  5797 				t = roots[i];
  5830 							tx = ty;
  5798 				if (point.isClose(Curve.getPoint(v, t), geomEpsilon))
  5831 						} else if (sy === -1) {
  5799 					return t;
  5832 							ty = tx;
  5800 			}
  5833 						}
  5801 		}
  5834 						if (Math.abs(tx - ty) < tolerance)
  5802 		return point.isClose(p1, geomEpsilon) ? 0
  5835 							return (tx + ty) * 0.5;
  5803 			 : point.isClose(p2, geomEpsilon) ? 1
  5836 					}
  5804 			 : null;
       
  5805 	},
       
  5806 
       
  5807 	getNearestParameter: function(v, point) {
       
  5808 		if (Curve.isStraight(v)) {
       
  5809 			var p1x = v[0], p1y = v[1],
       
  5810 				p2x = v[6], p2y = v[7],
       
  5811 				vx = p2x - p1x, vy = p2y - p1y,
       
  5812 				det = vx * vx + vy * vy;
       
  5813 			if (det === 0)
       
  5814 				return 0;
       
  5815 			var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
       
  5816 			return u < 1e-12 ? 0
       
  5817 				 : u > 0.999999999999 ? 1
       
  5818 				 : Curve.getParameterOf(v,
       
  5819 					new Point(p1x + u * vx, p1y + u * vy));
       
  5820 		}
       
  5821 
       
  5822 		var count = 100,
       
  5823 			minDist = Infinity,
       
  5824 			minT = 0;
       
  5825 
       
  5826 		function refine(t) {
       
  5827 			if (t >= 0 && t <= 1) {
       
  5828 				var dist = point.getDistance(Curve.getPoint(v, t), true);
       
  5829 				if (dist < minDist) {
       
  5830 					minDist = dist;
       
  5831 					minT = t;
       
  5832 					return true;
  5837 				}
  5833 				}
  5838 				if (sx === -1)
  5834 			}
  5839 					break;
  5835 		}
  5840 			}
  5836 
  5841 		}
  5837 		for (var i = 0; i <= count; i++)
  5842 		return null;
  5838 			refine(i / count);
       
  5839 
       
  5840 		var step = 1 / (count * 2);
       
  5841 		while (step > 4e-7) {
       
  5842 			if (!refine(minT - step) && !refine(minT + step))
       
  5843 				step /= 2;
       
  5844 		}
       
  5845 		return minT;
  5843 	},
  5846 	},
  5844 
  5847 
  5845 	getPart: function(v, from, to) {
  5848 	getPart: function(v, from, to) {
       
  5849 		var flip = from > to;
       
  5850 		if (flip) {
       
  5851 			var tmp = from;
       
  5852 			from = to;
       
  5853 			to = tmp;
       
  5854 		}
  5846 		if (from > 0)
  5855 		if (from > 0)
  5847 			v = Curve.subdivide(v, from)[1];
  5856 			v = Curve.subdivide(v, from)[1];
  5848 		if (to < 1)
  5857 		if (to < 1)
  5849 			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
  5858 			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
  5850 		return v;
  5859 		return flip
       
  5860 				? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]
       
  5861 				: v;
  5851 	},
  5862 	},
  5852 
  5863 
  5853 	hasHandles: function(v) {
  5864 	hasHandles: function(v) {
  5854 		var isZero = Numerical.isZero;
  5865 		var isZero = Numerical.isZero;
  5855 		return !(isZero(v[0] - v[2]) && isZero(v[1] - v[3])
  5866 		return !(isZero(v[0] - v[2]) && isZero(v[1] - v[3])
  5856 				&& isZero(v[4] - v[6]) && isZero(v[5] - v[7]));
  5867 				&& isZero(v[4] - v[6]) && isZero(v[5] - v[7]));
  5857 	},
       
  5858 
       
  5859 	isLinear: function(v) {
       
  5860 		var p1x = v[0], p1y = v[1],
       
  5861 			p2x = v[6], p2y = 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));
       
  5865 	},
  5868 	},
  5866 
  5869 
  5867 	isFlatEnough: function(v, tolerance) {
  5870 	isFlatEnough: function(v, tolerance) {
  5868 		var p1x = v[0], p1y = v[1],
  5871 		var p1x = v[0], p1y = v[1],
  5869 			c1x = v[2], c1y = v[3],
  5872 			c1x = v[2], c1y = v[3],
  5877 				< 10 * tolerance * tolerance;
  5880 				< 10 * tolerance * tolerance;
  5878 	},
  5881 	},
  5879 
  5882 
  5880 	getArea: function(v) {
  5883 	getArea: function(v) {
  5881 		var p1x = v[0], p1y = v[1],
  5884 		var p1x = v[0], p1y = v[1],
  5882 			c1x = v[2], c1y = v[3],
  5885 			p2x = v[6], p2y = v[7],
  5883 			c2x = v[4], c2y = v[5],
  5886 			h1x = (v[2] + p1x) / 2,
  5884 			p2x = v[6], p2y = v[7];
  5887 			h1y = (v[3] + p1y) / 2,
  5885 		return (  3.0 * c1y * p1x - 1.5 * c1y * c2x
  5888 			h2x = (v[4] + v[6]) / 2,
  5886 				- 1.5 * c1y * p2x - 3.0 * p1y * c1x
  5889 			h2y = (v[5] + v[7]) / 2;
  5887 				- 1.5 * p1y * c2x - 0.5 * p1y * p2x
  5890 		return 6 * ((p1x - h1x) * (h1y + p1y)
  5888 				+ 1.5 * c2y * p1x + 1.5 * c2y * c1x
  5891 				  + (h1x - h2x) * (h2y + h1y)
  5889 				- 3.0 * c2y * p2x + 0.5 * p2y * p1x
  5892 				  + (h2x - p2x) * (p2y + h2y)) / 10;
  5890 				+ 1.5 * p2y * c1x + 3.0 * p2y * c2x) / 10;
       
  5891 	},
       
  5892 
       
  5893 	getEdgeSum: function(v) {
       
  5894 		return	  (v[0] - v[2]) * (v[3] + v[1])
       
  5895 				+ (v[2] - v[4]) * (v[5] + v[3])
       
  5896 				+ (v[4] - v[6]) * (v[7] + v[5]);
       
  5897 	},
  5893 	},
  5898 
  5894 
  5899 	getBounds: function(v) {
  5895 	getBounds: function(v) {
  5900 		var min = v.slice(0, 2),
  5896 		var min = v.slice(0, 2),
  5901 			max = min.slice(),
  5897 			max = min.slice(),
  5917 		}
  5913 		}
  5918 		var a = 3 * (v1 - v2) - v0 + v3,
  5914 		var a = 3 * (v1 - v2) - v0 + v3,
  5919 			b = 2 * (v0 + v2) - 4 * v1,
  5915 			b = 2 * (v0 + v2) - 4 * v1,
  5920 			c = v1 - v0,
  5916 			c = v1 - v0,
  5921 			count = Numerical.solveQuadratic(a, b, c, roots),
  5917 			count = Numerical.solveQuadratic(a, b, c, roots),
  5922 			tMin = 0.000001,
  5918 			tMin = 4e-7,
  5923 			tMax = 1 - tMin;
  5919 			tMax = 1 - tMin;
  5924 		add(v3, 0);
  5920 		add(v3, 0);
  5925 		for (var i = 0; i < count; i++) {
  5921 		for (var i = 0; i < count; i++) {
  5926 			var t = roots[i],
  5922 			var t = roots[i],
  5927 				u = 1 - t;
  5923 				u = 1 - t;
  5939 		this[name] = function() {
  5935 		this[name] = function() {
  5940 			if (!this._bounds)
  5936 			if (!this._bounds)
  5941 				this._bounds = {};
  5937 				this._bounds = {};
  5942 			var bounds = this._bounds[name];
  5938 			var bounds = this._bounds[name];
  5943 			if (!bounds) {
  5939 			if (!bounds) {
  5944 				bounds = this._bounds[name] = Path[name]([this._segment1,
  5940 				var path = this._path;
  5945 						this._segment2], false, this._path.getStyle());
  5941 				bounds = this._bounds[name] = Path[name](
       
  5942 						[this._segment1, this._segment2], false,
       
  5943 						path && path.getStyle());
  5946 			}
  5944 			}
  5947 			return bounds.clone();
  5945 			return bounds.clone();
  5948 		};
  5946 		};
  5949 	},
  5947 	},
  5950 {
  5948 {
  5951 
  5949 
       
  5950 }), Base.each({
       
  5951 	isStraight: function(l, h1, h2) {
       
  5952 		if (h1.isZero() && h2.isZero()) {
       
  5953 			return true;
       
  5954 		} else if (l.isZero()) {
       
  5955 			return false;
       
  5956 		} else if (h1.isCollinear(l) && h2.isCollinear(l)) {
       
  5957 			var div = l.dot(l),
       
  5958 				p1 = l.dot(h1) / div,
       
  5959 				p2 = l.dot(h2) / div;
       
  5960 			return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
       
  5961 		}
       
  5962 		return false;
       
  5963 	},
       
  5964 
       
  5965 	isLinear: function(l, h1, h2) {
       
  5966 		var third = l.divide(3);
       
  5967 		return h1.equals(third) && h2.negate().equals(third);
       
  5968 	}
       
  5969 }, function(test, name) {
       
  5970 	this[name] = function() {
       
  5971 		var seg1 = this._segment1,
       
  5972 			seg2 = this._segment2;
       
  5973 		return test(seg2._point.subtract(seg1._point),
       
  5974 				seg1._handleOut, seg2._handleIn);
       
  5975 	};
       
  5976 
       
  5977 	this.statics[name] = function(v) {
       
  5978 		var p1x = v[0], p1y = v[1],
       
  5979 			p2x = v[6], p2y = v[7];
       
  5980 		return test(new Point(p2x - p1x, p2y - p1y),
       
  5981 				new Point(v[2] - p1x, v[3] - p1y),
       
  5982 				new Point(v[4] - p2x, v[5] - p2y));
       
  5983 	};
       
  5984 }, {
       
  5985 	statics: {},
       
  5986 
       
  5987 	hasHandles: function() {
       
  5988 		return !this._segment1._handleOut.isZero()
       
  5989 				|| !this._segment2._handleIn.isZero();
       
  5990 	},
       
  5991 
       
  5992 	isCollinear: function(curve) {
       
  5993 		return curve && this.isStraight() && curve.isStraight()
       
  5994 				&& this.getLine().isCollinear(curve.getLine());
       
  5995 	},
       
  5996 
       
  5997 	isHorizontal: function() {
       
  5998 		return this.isStraight() && Math.abs(this.getTangentAt(0.5, true).y)
       
  5999 				< 1e-7;
       
  6000 	},
       
  6001 
       
  6002 	isVertical: function() {
       
  6003 		return this.isStraight() && Math.abs(this.getTangentAt(0.5, true).x)
       
  6004 				< 1e-7;
       
  6005 	}
  5952 }), {
  6006 }), {
  5953 	beans: false,
  6007 	beans: false,
  5954 
  6008 
  5955 	getParameterAt: function(offset, start) {
  6009 	getParameterAt: function(offset, start) {
  5956 		return Curve.getParameterAt(this.getValues(), offset, start);
  6010 		return Curve.getParameterAt(this.getValues(), offset, start);
  5957 	},
  6011 	},
  5958 
  6012 
  5959 	getParameterOf: function() {
  6013 	getParameterOf: function() {
  5960 		var point = Point.read(arguments);
  6014 		return Curve.getParameterOf(this.getValues(), Point.read(arguments));
  5961 		return Curve.getParameterOf(this.getValues(), point.x, point.y);
       
  5962 	},
  6015 	},
  5963 
  6016 
  5964 	getLocationAt: function(offset, isParameter) {
  6017 	getLocationAt: function(offset, isParameter) {
  5965 		var t = isParameter ? offset : this.getParameterAt(offset);
  6018 		var t = isParameter ? offset : this.getParameterAt(offset);
  5966 		return t != null && t >= 0 && t <= 1
  6019 		return t != null && t >= 0 && t <= 1
  5979 	},
  6032 	},
  5980 
  6033 
  5981 	getNearestLocation: function() {
  6034 	getNearestLocation: function() {
  5982 		var point = Point.read(arguments),
  6035 		var point = Point.read(arguments),
  5983 			values = this.getValues(),
  6036 			values = this.getValues(),
  5984 			count = 100,
  6037 			t = Curve.getNearestParameter(values, point),
  5985 			minDist = Infinity,
  6038 			pt = Curve.getPoint(values, t);
  5986 			minT = 0;
  6039 		return new CurveLocation(this, t, pt, null, point.getDistance(pt));
  5987 
       
  5988 		function refine(t) {
       
  5989 			if (t >= 0 && t <= 1) {
       
  5990 				var dist = point.getDistance(Curve.getPoint(values, t), true);
       
  5991 				if (dist < minDist) {
       
  5992 					minDist = dist;
       
  5993 					minT = t;
       
  5994 					return true;
       
  5995 				}
       
  5996 			}
       
  5997 		}
       
  5998 
       
  5999 		for (var i = 0; i <= count; i++)
       
  6000 			refine(i / count);
       
  6001 
       
  6002 		var step = 1 / (count * 2);
       
  6003 		while (step > 0.000001) {
       
  6004 			if (!refine(minT - step) && !refine(minT + step))
       
  6005 				step /= 2;
       
  6006 		}
       
  6007 		var pt = Curve.getPoint(values, minT);
       
  6008 		return new CurveLocation(this, minT, pt, null, null, null,
       
  6009 				point.getDistance(pt));
       
  6010 	},
  6040 	},
  6011 
  6041 
  6012 	getNearestPoint: function() {
  6042 	getNearestPoint: function() {
  6013 		return this.getNearestLocation.apply(this, arguments).getPoint();
  6043 		return this.getNearestLocation.apply(this, arguments).getPoint();
  6014 	}
  6044 	}
  6062 			return null;
  6092 			return null;
  6063 		var p1x = v[0], p1y = v[1],
  6093 		var p1x = v[0], p1y = v[1],
  6064 			c1x = v[2], c1y = v[3],
  6094 			c1x = v[2], c1y = v[3],
  6065 			c2x = v[4], c2y = v[5],
  6095 			c2x = v[4], c2y = v[5],
  6066 			p2x = v[6], p2y = v[7],
  6096 			p2x = v[6], p2y = v[7],
  6067 			tolerance = 0.000001,
  6097 			tMin = 4e-7,
       
  6098 			tMax = 1 - tMin,
  6068 			x, y;
  6099 			x, y;
  6069 
  6100 
  6070 		if (type === 0 && (t < tolerance || t > 1 - tolerance)) {
  6101 		if (type === 0 && (t < tMin || t > tMax)) {
  6071 			var isZero = t < tolerance;
  6102 			var isZero = t < tMin;
  6072 			x = isZero ? p1x : p2x;
  6103 			x = isZero ? p1x : p2x;
  6073 			y = isZero ? p1y : p2y;
  6104 			y = isZero ? p1y : p2y;
  6074 		} else {
  6105 		} else {
  6075 			var cx = 3 * (c1x - p1x),
  6106 			var cx = 3 * (c1x - p1x),
  6076 				bx = 3 * (c2x - c1x) - cx,
  6107 				bx = 3 * (c2x - c1x) - cx,
  6081 				ay = p2y - p1y - cy - by;
  6112 				ay = p2y - p1y - cy - by;
  6082 			if (type === 0) {
  6113 			if (type === 0) {
  6083 				x = ((ax * t + bx) * t + cx) * t + p1x;
  6114 				x = ((ax * t + bx) * t + cx) * t + p1x;
  6084 				y = ((ay * t + by) * t + cy) * t + p1y;
  6115 				y = ((ay * t + by) * t + cy) * t + p1y;
  6085 			} else {
  6116 			} else {
  6086 				if (t < tolerance) {
  6117 				if (t < tMin) {
  6087 					x = cx;
  6118 					x = cx;
  6088 					y = cy;
  6119 					y = cy;
  6089 				} else if (t > 1 - tolerance) {
  6120 				} else if (t > tMax) {
  6090 					x = 3 * (p2x - c2x);
  6121 					x = 3 * (p2x - c2x);
  6091 					y = 3 * (p2y - c2y);
  6122 					y = 3 * (p2y - c2y);
  6092 				} else {
  6123 				} else {
  6093 					x = (3 * ax * t + 2 * bx) * t + cx;
  6124 					x = (3 * ax * t + 2 * bx) * t + cx;
  6094 					y = (3 * ay * t + 2 * by) * t + cy;
  6125 					y = (3 * ay * t + 2 * by) * t + cy;
  6095 				}
  6126 				}
  6096 				if (normalized) {
  6127 				if (normalized) {
  6097 					if (x === 0 && y === 0
  6128 					if (x === 0 && y === 0 && (t < tMin || t > tMax)) {
  6098 							&& (t < tolerance || t > 1 - tolerance)) {
       
  6099 						x = c2x - c1x;
  6129 						x = c2x - c1x;
  6100 						y = c2y - c1y;
  6130 						y = c2y - c1y;
  6101 					}
  6131 					}
  6102 					var len = Math.sqrt(x * x + y * y);
  6132 					var len = Math.sqrt(x * x + y * y);
  6103 					x /= len;
  6133 					if (len) {
  6104 					y /= len;
  6134 						x /= len;
       
  6135 						y /= len;
       
  6136 					}
  6105 				}
  6137 				}
  6106 				if (type === 3) {
  6138 				if (type === 3) {
  6107 					var x2 = 6 * ax * t + 2 * bx,
  6139 					var x2 = 6 * ax * t + 2 * bx,
  6108 						y2 = 6 * ay * t + 2 * by,
  6140 						y2 = 6 * ay * t + 2 * by,
  6109 						d = Math.pow(x * x + y * y, 3 / 2);
  6141 						d = Math.pow(x * x + y * y, 3 / 2);
  6113 			}
  6145 			}
  6114 		}
  6146 		}
  6115 		return type === 2 ? new Point(y, -x) : new Point(x, y);
  6147 		return type === 2 ? new Point(y, -x) : new Point(x, y);
  6116 	}
  6148 	}
  6117 
  6149 
  6118 	return {
  6150 	return { statics: {
  6119 		statics: true,
       
  6120 
  6151 
  6121 		getLength: function(v, a, b) {
  6152 		getLength: function(v, a, b) {
  6122 			if (a === undefined)
  6153 			if (a === undefined)
  6123 				a = 0;
  6154 				a = 0;
  6124 			if (b === undefined)
  6155 			if (b === undefined)
  6125 				b = 1;
  6156 				b = 1;
  6126 			var isZero = Numerical.isZero;
  6157 			if (a === 0 && b === 1 && Curve.isStraight(v)) {
  6127 			if (a === 0 && b === 1
       
  6128 					&& isZero(v[0] - v[2]) && isZero(v[1] - v[3])
       
  6129 					&& isZero(v[6] - v[4]) && isZero(v[7] - v[5])) {
       
  6130 				var dx = v[6] - v[0],
  6158 				var dx = v[6] - v[0],
  6131 					dy = v[7] - v[1];
  6159 					dy = v[7] - v[1];
  6132 				return Math.sqrt(dx * dx + dy * dy);
  6160 				return Math.sqrt(dx * dx + dy * dy);
  6133 			}
  6161 			}
  6134 			var ds = getLengthIntegrand(v);
  6162 			var ds = getLengthIntegrand(v);
  6138 		getParameterAt: function(v, offset, start) {
  6166 		getParameterAt: function(v, offset, start) {
  6139 			if (start === undefined)
  6167 			if (start === undefined)
  6140 				start = offset < 0 ? 1 : 0
  6168 				start = offset < 0 ? 1 : 0
  6141 			if (offset === 0)
  6169 			if (offset === 0)
  6142 				return start;
  6170 				return start;
  6143 			var tolerance = 0.000001,
  6171 			var abs = Math.abs,
  6144 				abs = Math.abs,
       
  6145 				forward = offset > 0,
  6172 				forward = offset > 0,
  6146 				a = forward ? start : 0,
  6173 				a = forward ? start : 0,
  6147 				b = forward ? 1 : start,
  6174 				b = forward ? 1 : start,
  6148 				ds = getLengthIntegrand(v),
  6175 				ds = getLengthIntegrand(v),
  6149 				rangeLength = Numerical.integrate(ds, a, b,
  6176 				rangeLength = Numerical.integrate(ds, a, b,
  6150 						getIterations(a, b));
  6177 						getIterations(a, b));
  6151 			if (abs(offset - rangeLength) < tolerance) {
  6178 			if (abs(offset - rangeLength) < 1e-12) {
  6152 				return forward ? b : a;
  6179 				return forward ? b : a;
  6153 			} else if (abs(offset) > rangeLength) {
  6180 			} else if (abs(offset) > rangeLength) {
  6154 				return null;
  6181 				return null;
  6155 			}
  6182 			}
  6156 			var guess = offset / rangeLength,
  6183 			var guess = offset / rangeLength,
  6159 				length += Numerical.integrate(ds, start, t,
  6186 				length += Numerical.integrate(ds, start, t,
  6160 						getIterations(start, t));
  6187 						getIterations(start, t));
  6161 				start = t;
  6188 				start = t;
  6162 				return length - offset;
  6189 				return length - offset;
  6163 			}
  6190 			}
  6164 			return Numerical.findRoot(f, ds, start + guess, a, b, 16,
  6191 			return Numerical.findRoot(f, ds, start + guess, a, b, 32,
  6165 					tolerance);
  6192 					1e-12);
  6166 		},
  6193 		},
  6167 
  6194 
  6168 		getPoint: function(v, t) {
  6195 		getPoint: function(v, t) {
  6169 			return evaluate(v, t, 0, false);
  6196 			return evaluate(v, t, 0, false);
  6170 		},
  6197 		},
  6186 		},
  6213 		},
  6187 
  6214 
  6188 		getCurvature: function(v, t) {
  6215 		getCurvature: function(v, t) {
  6189 			return evaluate(v, t, 3, false).x;
  6216 			return evaluate(v, t, 3, false).x;
  6190 		}
  6217 		}
  6191 	};
  6218 	}};
  6192 }, new function() {
  6219 },
  6193 	function addLocation(locations, include, curve1, t1, point1, curve2, t2,
  6220 new function() {
  6194 			point2) {
  6221 
  6195 		var loc = new CurveLocation(curve1, t1, point1, curve2, t2, point2);
  6222 	function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
  6196 		if (!include || include(loc))
  6223 			overlap) {
  6197 			locations.push(loc);
  6224 		var startConnected = param.startConnected,
  6198 	}
  6225 			endConnected = param.endConnected,
  6199 
  6226 			tMin = 4e-7,
  6200 	function addCurveIntersections(v1, v2, curve1, curve2, locations, include,
  6227 			tMax = 1 - tMin;
       
  6228 		if (t1 == null)
       
  6229 			t1 = Curve.getParameterOf(v1, p1);
       
  6230 		if (t1 !== null && t1 >= (startConnected ? tMin : 0) &&
       
  6231 			t1 <= (endConnected ? tMax : 1)) {
       
  6232 			if (t2 == null)
       
  6233 				t2 = Curve.getParameterOf(v2, p2);
       
  6234 			if (t2 !== null && t2 >= (endConnected ? tMin : 0) &&
       
  6235 				t2 <= (startConnected ? tMax : 1)) {
       
  6236 				var renormalize = param.renormalize;
       
  6237 				if (renormalize) {
       
  6238 					var res = renormalize(t1, t2);
       
  6239 					t1 = res[0];
       
  6240 					t2 = res[1];
       
  6241 				}
       
  6242 				var loc1 = new CurveLocation(c1, t1,
       
  6243 						p1 || Curve.getPoint(v1, t1), overlap),
       
  6244 					loc2 = new CurveLocation(c2, t2,
       
  6245 						p2 || Curve.getPoint(v2, t2), overlap),
       
  6246 					flip = loc1.getPath() === loc2.getPath()
       
  6247 						&& loc1.getIndex() > loc2.getIndex(),
       
  6248 					loc = flip ? loc2 : loc1,
       
  6249 					include = param.include;
       
  6250 				loc1._intersection = loc2;
       
  6251 				loc2._intersection = loc1;
       
  6252 				if (!include || include(loc)) {
       
  6253 					CurveLocation.insert(locations, loc, true);
       
  6254 				}
       
  6255 			}
       
  6256 		}
       
  6257 	}
       
  6258 
       
  6259 	function addCurveIntersections(v1, v2, c1, c2, locations, param,
  6201 			tMin, tMax, uMin, uMax, oldTDiff, reverse, recursion) {
  6260 			tMin, tMax, uMin, uMax, oldTDiff, reverse, recursion) {
  6202 		if (recursion > 32)
  6261 		if (++recursion >= 24)
  6203 			return;
  6262 			return;
  6204 		var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
  6263 		var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
  6205 			tolerance = 0.000001,
       
  6206 			getSignedDistance = Line.getSignedDistance,
  6264 			getSignedDistance = Line.getSignedDistance,
  6207 			d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]) || 0,
  6265 			d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),
  6208 			d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]) || 0,
  6266 			d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),
  6209 			factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
  6267 			factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
  6210 			dMin = factor * Math.min(0, d1, d2),
  6268 			dMin = factor * Math.min(0, d1, d2),
  6211 			dMax = factor * Math.max(0, d1, d2),
  6269 			dMax = factor * Math.max(0, d1, d2),
  6212 			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
  6270 			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
  6213 			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
  6271 			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
  6214 			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
  6272 			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
  6215 			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
  6273 			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
  6216 			tMinNew, tMaxNew, tDiff;
  6274 			hull = getConvexHull(dp0, dp1, dp2, dp3),
  6217 		if (q0x === q3x && uMax - uMin < tolerance && recursion > 3) {
  6275 			top = hull[0],
  6218 			tMaxNew = tMinNew = (tMax + tMin) / 2;
  6276 			bottom = hull[1],
  6219 			tDiff = 0;
  6277 			tMinClip,
  6220 		} else {
  6278 			tMaxClip;
  6221 			var hull = getConvexHull(dp0, dp1, dp2, dp3),
  6279 		if ((tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null ||
  6222 				top = hull[0],
  6280 			(tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),
  6223 				bottom = hull[1],
  6281 				dMin, dMax)) == null)
  6224 				tMinClip, tMaxClip;
  6282 			return;
  6225 			tMinClip = clipConvexHull(top, bottom, dMin, dMax);
  6283 		v1 = Curve.getPart(v1, tMinClip, tMaxClip);
  6226 			top.reverse();
  6284 		var tDiff = tMaxClip - tMinClip,
  6227 			bottom.reverse();
  6285 			tMinNew = tMin + (tMax - tMin) * tMinClip,
  6228 			tMaxClip = clipConvexHull(top, bottom, dMin, dMax);
  6286 			tMaxNew = tMin + (tMax - tMin) * tMaxClip;
  6229 			if (tMinClip == null || tMaxClip == null)
       
  6230 				return;
       
  6231 			v1 = Curve.getPart(v1, tMinClip, tMaxClip);
       
  6232 			tDiff = tMaxClip - tMinClip;
       
  6233 			tMinNew = tMax * tMinClip + tMin * (1 - tMinClip);
       
  6234 			tMaxNew = tMax * tMaxClip + tMin * (1 - tMaxClip);
       
  6235 		}
       
  6236 		if (oldTDiff > 0.5 && tDiff > 0.5) {
  6287 		if (oldTDiff > 0.5 && tDiff > 0.5) {
  6237 			if (tMaxNew - tMinNew > uMax - uMin) {
  6288 			if (tMaxNew - tMinNew > uMax - uMin) {
  6238 				var parts = Curve.subdivide(v1, 0.5),
  6289 				var parts = Curve.subdivide(v1, 0.5),
  6239 					t = tMinNew + (tMaxNew - tMinNew) / 2;
  6290 					t = tMinNew + (tMaxNew - tMinNew) / 2;
  6240 				addCurveIntersections(
  6291 				addCurveIntersections(
  6241 					v2, parts[0], curve2, curve1, locations, include,
  6292 					v2, parts[0], c2, c1, locations, param,
  6242 					uMin, uMax, tMinNew, t, tDiff, !reverse, ++recursion);
  6293 					uMin, uMax, tMinNew, t, tDiff, !reverse, recursion);
  6243 				addCurveIntersections(
  6294 				addCurveIntersections(
  6244 					v2, parts[1], curve2, curve1, locations, include,
  6295 					v2, parts[1], c2, c1, locations, param,
  6245 					uMin, uMax, t, tMaxNew, tDiff, !reverse, recursion);
  6296 					uMin, uMax, t, tMaxNew, tDiff, !reverse, recursion);
  6246 			} else {
  6297 			} else {
  6247 				var parts = Curve.subdivide(v2, 0.5),
  6298 				var parts = Curve.subdivide(v2, 0.5),
  6248 					t = uMin + (uMax - uMin) / 2;
  6299 					t = uMin + (uMax - uMin) / 2;
  6249 				addCurveIntersections(
  6300 				addCurveIntersections(
  6250 					parts[0], v1, curve2, curve1, locations, include,
  6301 					parts[0], v1, c2, c1, locations, param,
  6251 					uMin, t, tMinNew, tMaxNew, tDiff, !reverse, ++recursion);
  6302 					uMin, t, tMinNew, tMaxNew, tDiff, !reverse, recursion);
  6252 				addCurveIntersections(
  6303 				addCurveIntersections(
  6253 					parts[1], v1, curve2, curve1, locations, include,
  6304 					parts[1], v1, c2, c1, locations, param,
  6254 					t, uMax, tMinNew, tMaxNew, tDiff, !reverse, recursion);
  6305 					t, uMax, tMinNew, tMaxNew, tDiff, !reverse, recursion);
  6255 			}
  6306 			}
  6256 		} else if (Math.max(uMax - uMin, tMaxNew - tMinNew) < tolerance) {
  6307 		} else if (Math.max(uMax - uMin, tMaxNew - tMinNew)
       
  6308 				< 1e-7) {
  6257 			var t1 = tMinNew + (tMaxNew - tMinNew) / 2,
  6309 			var t1 = tMinNew + (tMaxNew - tMinNew) / 2,
  6258 				t2 = uMin + (uMax - uMin) / 2;
  6310 				t2 = uMin + (uMax - uMin) / 2;
  6259 			if (reverse) {
  6311 			v1 = c1.getValues();
  6260 				addLocation(locations, include,
  6312 			v2 = c2.getValues();
  6261 						curve2, t2, Curve.getPoint(v2, t2),
  6313 			addLocation(locations, param,
  6262 						curve1, t1, Curve.getPoint(v1, t1));
  6314 				reverse ? v2 : v1, reverse ? c2 : c1, reverse ? t2 : t1, null,
  6263 			} else {
  6315 				reverse ? v1 : v2, reverse ? c1 : c2, reverse ? t1 : t2, null);
  6264 				addLocation(locations, include,
  6316 		} else if (tDiff > 1e-12) {
  6265 						curve1, t1, Curve.getPoint(v1, t1),
  6317 			addCurveIntersections(v2, v1, c2, c1, locations, param,
  6266 						curve2, t2, Curve.getPoint(v2, t2));
  6318 					uMin, uMax, tMinNew, tMaxNew, tDiff, !reverse, recursion);
  6267 			}
       
  6268 		} else if (tDiff > 0) {
       
  6269 			addCurveIntersections(v2, v1, curve2, curve1, locations, include,
       
  6270 					uMin, uMax, tMinNew, tMaxNew, tDiff, !reverse, ++recursion);
       
  6271 		}
  6319 		}
  6272 	}
  6320 	}
  6273 
  6321 
  6274 	function getConvexHull(dq0, dq1, dq2, dq3) {
  6322 	function getConvexHull(dq0, dq1, dq2, dq3) {
  6275 		var p0 = [ 0, dq0 ],
  6323 		var p0 = [ 0, dq0 ],
  6276 			p1 = [ 1 / 3, dq1 ],
  6324 			p1 = [ 1 / 3, dq1 ],
  6277 			p2 = [ 2 / 3, dq2 ],
  6325 			p2 = [ 2 / 3, dq2 ],
  6278 			p3 = [ 1, dq3 ],
  6326 			p3 = [ 1, dq3 ],
  6279 			getSignedDistance = Line.getSignedDistance,
  6327 			dist1 = dq1 - (2 * dq0 + dq3) / 3,
  6280 			dist1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
  6328 			dist2 = dq2 - (dq0 + 2 * dq3) / 3,
  6281 			dist2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2),
       
  6282 			flip = false,
       
  6283 			hull;
  6329 			hull;
  6284 		if (dist1 * dist2 < 0) {
  6330 		if (dist1 * dist2 < 0) {
  6285 			hull = [[p0, p1, p3], [p0, p2, p3]];
  6331 			hull = [[p0, p1, p3], [p0, p2, p3]];
  6286 			flip = dist1 < 0;
       
  6287 		} else {
  6332 		} else {
  6288 			var pmax, cross = 0,
  6333 			var distRatio = dist1 / dist2;
  6289 				distZero = dist1 === 0 || dist2 === 0;
  6334 			hull = [
  6290 			if (Math.abs(dist1) > Math.abs(dist2)) {
  6335 				distRatio >= 2 ? [p0, p1, p3]
  6291 				pmax = p1;
  6336 				: distRatio <= .5 ? [p0, p2, p3]
  6292 				cross = (dq3 - dq2 - (dq3 - dq0) / 3)
  6337 				: [p0, p1, p2, p3],
  6293 						* (2 * (dq3 - dq2) - dq3 + dq1) / 3;
  6338 				[p0, p3]
  6294 			} else {
  6339 			];
  6295 				pmax = p2;
  6340 		}
  6296 				cross = (dq1 - dq0 + (dq0 - dq3) / 3)
  6341 		return (dist1 || dist2) < 0 ? hull.reverse() : hull;
  6297 						* (-2 * (dq0 - dq1) + dq0 - dq2) / 3;
       
  6298 			}
       
  6299 			hull = cross < 0 || distZero
       
  6300 					? [[p0, pmax, p3], [p0, p3]]
       
  6301 					: [[p0, p1, p2, p3], [p0, p3]];
       
  6302 			flip = dist1 ? dist1 < 0 : dist2 < 0;
       
  6303 		}
       
  6304 		return flip ? hull.reverse() : hull;
       
  6305 	}
  6342 	}
  6306 
  6343 
  6307 	function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
  6344 	function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
  6308 		if (hullTop[0][1] < dMin) {
  6345 		if (hullTop[0][1] < dMin) {
  6309 			return clipConvexHullPart(hullTop, true, dMin);
  6346 			return clipConvexHullPart(hullTop, true, dMin);
  6318 		var px = part[0][0],
  6355 		var px = part[0][0],
  6319 			py = part[0][1];
  6356 			py = part[0][1];
  6320 		for (var i = 1, l = part.length; i < l; i++) {
  6357 		for (var i = 1, l = part.length; i < l; i++) {
  6321 			var qx = part[i][0],
  6358 			var qx = part[i][0],
  6322 				qy = part[i][1];
  6359 				qy = part[i][1];
  6323 			if (top ? qy >= threshold : qy <= threshold)
  6360 			if (top ? qy >= threshold : qy <= threshold) {
  6324 				return px + (threshold - py) * (qx - px) / (qy - py);
  6361 				return qy === threshold ? qx
       
  6362 						: px + (threshold - py) * (qx - px) / (qy - py);
       
  6363 			}
  6325 			px = qx;
  6364 			px = qx;
  6326 			py = qy;
  6365 			py = qy;
  6327 		}
  6366 		}
  6328 		return null;
  6367 		return null;
  6329 	}
  6368 	}
  6330 
  6369 
  6331 	function addCurveLineIntersections(v1, v2, curve1, curve2, locations,
  6370 	function addCurveLineIntersections(v1, v2, c1, c2, locations, param) {
  6332 			include) {
  6371 		var flip = Curve.isStraight(v1),
  6333 		var flip = Curve.isLinear(v1),
       
  6334 			vc = flip ? v2 : v1,
  6372 			vc = flip ? v2 : v1,
  6335 			vl = flip ? v1 : v2,
  6373 			vl = flip ? v1 : v2,
  6336 			lx1 = vl[0], ly1 = vl[1],
  6374 			lx1 = vl[0], ly1 = vl[1],
  6337 			lx2 = vl[6], ly2 = vl[7],
  6375 			lx2 = vl[6], ly2 = vl[7],
  6338 			ldx = lx2 - lx1,
  6376 			ldx = lx2 - lx1,
  6339 			ldy = ly2 - ly1,
  6377 			ldy = ly2 - ly1,
  6340 			angle = Math.atan2(-ldy, ldx),
  6378 			angle = Math.atan2(-ldy, ldx),
  6341 			sin = Math.sin(angle),
  6379 			sin = Math.sin(angle),
  6342 			cos = Math.cos(angle),
  6380 			cos = Math.cos(angle),
  6343 			rlx2 = ldx * cos - ldy * sin,
       
  6344 			rvl = [0, 0, 0, 0, rlx2, 0, rlx2, 0],
       
  6345 			rvc = [];
  6381 			rvc = [];
  6346 		for(var i = 0; i < 8; i += 2) {
  6382 		for(var i = 0; i < 8; i += 2) {
  6347 			var x = vc[i] - lx1,
  6383 			var x = vc[i] - lx1,
  6348 				y = vc[i + 1] - ly1;
  6384 				y = vc[i + 1] - ly1;
  6349 			rvc.push(
  6385 			rvc.push(
  6350 				x * cos - y * sin,
  6386 				x * cos - y * sin,
  6351 				y * cos + x * sin);
  6387 				x * sin + y * cos);
  6352 		}
  6388 		}
  6353 		var roots = [],
  6389 		var roots = [],
  6354 			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
  6390 			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
  6355 		for (var i = 0; i < count; i++) {
  6391 		for (var i = 0; i < count; i++) {
  6356 			var tc = roots[i],
  6392 			var tc = roots[i],
  6357 				x = Curve.getPoint(rvc, tc).x;
  6393 				pc = Curve.getPoint(vc, tc),
  6358 			if (x >= 0 && x <= rlx2) {
  6394 				tl = Curve.getParameterOf(vl, pc);
  6359 				var tl = Curve.getParameterOf(rvl, x, 0),
  6395 			if (tl !== null) {
       
  6396 				var pl = Curve.getPoint(vl, tl),
  6360 					t1 = flip ? tl : tc,
  6397 					t1 = flip ? tl : tc,
  6361 					t2 = flip ? tc : tl;
  6398 					t2 = flip ? tc : tl;
  6362 				addLocation(locations, include,
  6399 				if (!param.endConnected || t2 > Numerical.CURVETIME_EPSILON) {
  6363 						curve1, t1, Curve.getPoint(v1, t1),
  6400 					addLocation(locations, param,
  6364 						curve2, t2, Curve.getPoint(v2, t2));
  6401 							v1, c1, t1, flip ? pl : pc,
  6365 			}
  6402 							v2, c2, t2, flip ? pc : pl);
  6366 		}
  6403 				}
  6367 	}
  6404 			}
  6368 
  6405 		}
  6369 	function addLineIntersection(v1, v2, curve1, curve2, locations, include) {
  6406 	}
  6370 		var point = Line.intersect(
  6407 
       
  6408 	function addLineIntersection(v1, v2, c1, c2, locations, param) {
       
  6409 		var pt = Line.intersect(
  6371 				v1[0], v1[1], v1[6], v1[7],
  6410 				v1[0], v1[1], v1[6], v1[7],
  6372 				v2[0], v2[1], v2[6], v2[7]);
  6411 				v2[0], v2[1], v2[6], v2[7]);
  6373 		if (point) {
  6412 		if (pt) {
  6374 			var x = point.x,
  6413 			addLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);
  6375 				y = point.y;
       
  6376 			addLocation(locations, include,
       
  6377 					curve1, Curve.getParameterOf(v1, x, y), point,
       
  6378 					curve2, Curve.getParameterOf(v2, x, y), point);
       
  6379 		}
  6414 		}
  6380 	}
  6415 	}
  6381 
  6416 
  6382 	return { statics: {
  6417 	return { statics: {
  6383 		getIntersections: function(v1, v2, c1, c2, locations, include) {
  6418 		_getIntersections: function(v1, v2, c1, c2, locations, param) {
  6384 			var linear1 = Curve.isLinear(v1),
  6419 			if (!v2) {
  6385 				linear2 = Curve.isLinear(v2),
  6420 				return Curve._getSelfIntersection(v1, c1, locations, param);
  6386 				c1p1 = c1.getPoint1(),
  6421 			}
  6387 				c1p2 = c1.getPoint2(),
  6422 			var c1p1x = v1[0], c1p1y = v1[1],
  6388 				c2p1 = c2.getPoint1(),
  6423 				c1p2x = v1[6], c1p2y = v1[7],
  6389 				c2p2 = c2.getPoint2(),
  6424 				c2p1x = v2[0], c2p1y = v2[1],
  6390 				tolerance = 0.000001;
  6425 				c2p2x = v2[6], c2p2y = v2[7],
  6391 			if (c1p1.isClose(c2p1, tolerance))
  6426 				c1s1x = (3 * v1[2] + c1p1x) / 4,
  6392 				addLocation(locations, include, c1, 0, c1p1, c2, 0, c1p1);
  6427 				c1s1y = (3 * v1[3] + c1p1y) / 4,
  6393 			if (c1p1.isClose(c2p2, tolerance))
  6428 				c1s2x = (3 * v1[4] + c1p2x) / 4,
  6394 				addLocation(locations, include, c1, 0, c1p1, c2, 1, c1p1);
  6429 				c1s2y = (3 * v1[5] + c1p2y) / 4,
  6395 			(linear1 && linear2
  6430 				c2s1x = (3 * v2[2] + c2p1x) / 4,
       
  6431 				c2s1y = (3 * v2[3] + c2p1y) / 4,
       
  6432 				c2s2x = (3 * v2[4] + c2p2x) / 4,
       
  6433 				c2s2y = (3 * v2[5] + c2p2y) / 4,
       
  6434 				min = Math.min,
       
  6435 				max = Math.max;
       
  6436 			if (!(	max(c1p1x, c1s1x, c1s2x, c1p2x) >=
       
  6437 					min(c2p1x, c2s1x, c2s2x, c2p2x) &&
       
  6438 					min(c1p1x, c1s1x, c1s2x, c1p2x) <=
       
  6439 					max(c2p1x, c2s1x, c2s2x, c2p2x) &&
       
  6440 					max(c1p1y, c1s1y, c1s2y, c1p2y) >=
       
  6441 					min(c2p1y, c2s1y, c2s2y, c2p2y) &&
       
  6442 					min(c1p1y, c1s1y, c1s2y, c1p2y) <=
       
  6443 					max(c2p1y, c2s1y, c2s2y, c2p2y)))
       
  6444 				return locations;
       
  6445 			if (!param.startConnected && !param.endConnected) {
       
  6446 				var overlaps = Curve.getOverlaps(v1, v2);
       
  6447 				if (overlaps) {
       
  6448 					for (var i = 0; i < 2; i++) {
       
  6449 						var overlap = overlaps[i];
       
  6450 						addLocation(locations, param,
       
  6451 							v1, c1, overlap[0], null,
       
  6452 							v2, c2, overlap[1], null, true);
       
  6453 					}
       
  6454 					return locations;
       
  6455 				}
       
  6456 			}
       
  6457 
       
  6458 			var straight1 = Curve.isStraight(v1),
       
  6459 				straight2 = Curve.isStraight(v2),
       
  6460 				straight = straight1 && straight2,
       
  6461 				epsilon = 1e-12,
       
  6462 				before = locations.length;
       
  6463 			(straight
  6396 				? addLineIntersection
  6464 				? addLineIntersection
  6397 				: linear1 || linear2
  6465 				: straight1 || straight2
  6398 					? addCurveLineIntersections
  6466 					? addCurveLineIntersections
  6399 					: addCurveIntersections)(
  6467 					: addCurveIntersections)(
  6400 						v1, v2, c1, c2, locations, include,
  6468 						v1, v2, c1, c2, locations, param,
  6401 						0, 1, 0, 1, 0, false, 0);
  6469 						0, 1, 0, 1, 0, false, 0);
  6402 			if (c1p2.isClose(c2p1, tolerance))
  6470 			if (straight && locations.length > before)
  6403 				addLocation(locations, include, c1, 1, c1p2, c2, 0, c1p2);
  6471 				return locations;
  6404 			if (c1p2.isClose(c2p2, tolerance))
  6472 			var c1p1 = new Point(c1p1x, c1p1y),
  6405 				addLocation(locations, include, c1, 1, c1p2, c2, 1, c1p2);
  6473 				c1p2 = new Point(c1p2x, c1p2y),
       
  6474 				c2p1 = new Point(c2p1x, c2p1y),
       
  6475 				c2p2 = new Point(c2p2x, c2p2y);
       
  6476 			if (c1p1.isClose(c2p1, epsilon))
       
  6477 				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);
       
  6478 			if (!param.startConnected && c1p1.isClose(c2p2, epsilon))
       
  6479 				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);
       
  6480 			if (!param.endConnected && c1p2.isClose(c2p1, epsilon))
       
  6481 				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);
       
  6482 			if (c1p2.isClose(c2p2, epsilon))
       
  6483 				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);
  6406 			return locations;
  6484 			return locations;
  6407 		},
  6485 		},
  6408 
  6486 
  6409 		filterIntersections: function(locations, _expand) {
  6487 		_getSelfIntersection: function(v1, c1, locations, param) {
  6410 			var last = locations.length - 1,
  6488 			var p1x = v1[0], p1y = v1[1],
  6411 				tMax = 1 - 0.000001;
  6489 				h1x = v1[2], h1y = v1[3],
  6412 			for (var i = last; i >= 0; i--) {
  6490 				h2x = v1[4], h2y = v1[5],
  6413 				var loc = locations[i],
  6491 				p2x = v1[6], p2y = v1[7];
  6414 					next = loc._curve.getNext(),
  6492 			var line = new Line(p1x, p1y, p2x, p2y, false),
  6415 					next2 = loc._curve2.getNext();
  6493 				side1 = line.getSide(new Point(h1x, h1y), true),
  6416 				if (next && loc._parameter >= tMax) {
  6494 				side2 = line.getSide(new Point(h2x, h2y), true);
  6417 					loc._parameter = 0;
  6495 			if (side1 === side2) {
  6418 					loc._curve = next;
  6496 				var edgeSum = (p1x - h2x) * (h1y - p2y)
       
  6497 							+ (h1x - p2x) * (h2y - p1y);
       
  6498 				if (edgeSum * side1 > 0)
       
  6499 					return locations;
       
  6500 			}
       
  6501 			var ax = p2x - 3 * h2x + 3 * h1x - p1x,
       
  6502 				bx = h2x - 2 * h1x + p1x,
       
  6503 				cx = h1x - p1x,
       
  6504 				ay = p2y - 3 * h2y + 3 * h1y - p1y,
       
  6505 				by = h2y - 2 * h1y + p1y,
       
  6506 				cy = h1y - p1y,
       
  6507 				ac = ay * cx - ax * cy,
       
  6508 				ab = ay * bx - ax * by,
       
  6509 				bc = by * cx - bx * cy;
       
  6510 			if (ac * ac - 4 * ab * bc < 0) {
       
  6511 				var roots = [],
       
  6512 					tSplit,
       
  6513 					count = Numerical.solveCubic(
       
  6514 							ax * ax	 + ay * ay,
       
  6515 							3 * (ax * bx + ay * by),
       
  6516 							2 * (bx * bx + by * by) + ax * cx + ay * cy,
       
  6517 							bx * cx + by * cy,
       
  6518 							roots, 0, 1);
       
  6519 				if (count > 0) {
       
  6520 					for (var i = 0, maxCurvature = 0; i < count; i++) {
       
  6521 						var curvature = Math.abs(
       
  6522 								c1.getCurvatureAt(roots[i], true));
       
  6523 						if (curvature > maxCurvature) {
       
  6524 							maxCurvature = curvature;
       
  6525 							tSplit = roots[i];
       
  6526 						}
       
  6527 					}
       
  6528 					var parts = Curve.subdivide(v1, tSplit);
       
  6529 					param.endConnected = true;
       
  6530 					param.renormalize = function(t1, t2) {
       
  6531 						return [t1 * tSplit, t2 * (1 - tSplit) + tSplit];
       
  6532 					};
       
  6533 					Curve._getIntersections(parts[0], parts[1], c1, c1,
       
  6534 							locations, param);
  6419 				}
  6535 				}
  6420 				if (next2 && loc._parameter2 >= tMax) {
  6536 			}
  6421 					loc._parameter2 = 0;
  6537 			return locations;
  6422 					loc._curve2 = next2;
  6538 		},
       
  6539 
       
  6540 		getOverlaps: function(v1, v2) {
       
  6541 			var abs = Math.abs,
       
  6542 				timeEpsilon = 4e-7,
       
  6543 				geomEpsilon = 2e-7,
       
  6544 				straight1 = Curve.isStraight(v1),
       
  6545 				straight2 = Curve.isStraight(v2),
       
  6546 				straight =	straight1 && straight2;
       
  6547 
       
  6548 			function getLineLengthSquared(v) {
       
  6549 				var x = v[6] - v[0],
       
  6550 					y = v[7] - v[1];
       
  6551 				return x * x + y * y;
       
  6552 			}
       
  6553 
       
  6554 			if (straight) {
       
  6555 				var flip = getLineLengthSquared(v1) < getLineLengthSquared(v2),
       
  6556 					l1 = flip ? v2 : v1,
       
  6557 					l2 = flip ? v1 : v2,
       
  6558 					line = new Line(l1[0], l1[1], l1[6], l1[7]);
       
  6559 				if (line.getDistance(new Point(l2[0], l2[1])) > geomEpsilon ||
       
  6560 					line.getDistance(new Point(l2[6], l2[7])) > geomEpsilon)
       
  6561 					return null;
       
  6562 			} else if (straight1 ^ straight2) {
       
  6563 				return null;
       
  6564 			}
       
  6565 
       
  6566 			var v = [v1, v2],
       
  6567 				pairs = [];
       
  6568 			for (var i = 0, t1 = 0;
       
  6569 					i < 2 && pairs.length < 2;
       
  6570 					i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
       
  6571 				var t2 = Curve.getParameterOf(v[i ^ 1], new Point(
       
  6572 						v[i][t1 === 0 ? 0 : 6],
       
  6573 						v[i][t1 === 0 ? 1 : 7]));
       
  6574 				if (t2 != null) {
       
  6575 					var pair = i === 0 ? [t1, t2] : [t2, t1];
       
  6576 					if (pairs.length === 0 ||
       
  6577 						abs(pair[0] - pairs[0][0]) > timeEpsilon &&
       
  6578 						abs(pair[1] - pairs[0][1]) > timeEpsilon)
       
  6579 						pairs.push(pair);
  6423 				}
  6580 				}
  6424 			}
  6581 				if (i === 1 && pairs.length === 0)
  6425 
  6582 					break;
  6426 			function compare(loc1, loc2) {
  6583 			}
  6427 				var path1 = loc1.getPath(),
  6584 			if (pairs.length !== 2) {
  6428 					path2 = loc2.getPath();
  6585 				pairs = null;
  6429 				return path1 === path2
  6586 			} else if (!straight) {
  6430 						? (loc1.getIndex() + loc1.getParameter())
  6587 				var o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),
  6431 								- (loc2.getIndex() + loc2.getParameter())
  6588 					o2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);
  6432 						: path1._id - path2._id;
  6589 				if (abs(o2[2] - o1[2]) > geomEpsilon ||
  6433 			}
  6590 					abs(o2[3] - o1[3]) > geomEpsilon ||
  6434 
  6591 					abs(o2[4] - o1[4]) > geomEpsilon ||
  6435 			if (last > 0) {
  6592 					abs(o2[5] - o1[5]) > geomEpsilon)
  6436 				locations.sort(compare);
  6593 					pairs = null;
  6437 				for (var i = last; i > 0; i--) {
  6594 			}
  6438 					if (locations[i].equals(locations[i - 1])) {
  6595 			return pairs;
  6439 						locations.splice(i, 1);
       
  6440 						last--;
       
  6441 					}
       
  6442 				}
       
  6443 			}
       
  6444 			if (_expand) {
       
  6445 				for (var i = last; i >= 0; i--)
       
  6446 					locations.push(locations[i].getIntersection());
       
  6447 				locations.sort(compare);
       
  6448 			}
       
  6449 			return locations;
       
  6450 		}
  6596 		}
  6451 	}};
  6597 	}};
  6452 });
  6598 });
  6453 
  6599 
  6454 var CurveLocation = Base.extend({
  6600 var CurveLocation = Base.extend({
  6455 	_class: 'CurveLocation',
  6601 	_class: 'CurveLocation',
  6456 	beans: true,
  6602 	beans: true,
  6457 
  6603 
  6458 	initialize: function CurveLocation(curve, parameter, point, _curve2,
  6604 	initialize: function CurveLocation(curve, parameter, point,
  6459 			_parameter2, _point2, _distance) {
  6605 			_overlap, _distance) {
       
  6606 		if (parameter > 0.9999996) {
       
  6607 			var next = curve.getNext();
       
  6608 			if (next) {
       
  6609 				parameter = 0;
       
  6610 				curve = next;
       
  6611 			}
       
  6612 		}
  6460 		this._id = UID.get(CurveLocation);
  6613 		this._id = UID.get(CurveLocation);
       
  6614 		this._setCurve(curve);
       
  6615 		this._parameter = parameter;
       
  6616 		this._point = point || curve.getPointAt(parameter, true);
       
  6617 		this._overlap = _overlap;
       
  6618 		this._distance = _distance;
       
  6619 		this._intersection = this._next = this._prev = null;
       
  6620 	},
       
  6621 
       
  6622 	_setCurve: function(curve) {
  6461 		var path = curve._path;
  6623 		var path = curve._path;
  6462 		this._version = path ? path._version : 0;
  6624 		this._version = path ? path._version : 0;
  6463 		this._curve = curve;
  6625 		this._curve = curve;
  6464 		this._parameter = parameter;
  6626 		this._segment = null;
  6465 		this._point = point || curve.getPointAt(parameter, true);
       
  6466 		this._curve2 = _curve2;
       
  6467 		this._parameter2 = _parameter2;
       
  6468 		this._point2 = _point2;
       
  6469 		this._distance = _distance;
       
  6470 		this._segment1 = curve._segment1;
  6627 		this._segment1 = curve._segment1;
  6471 		this._segment2 = curve._segment2;
  6628 		this._segment2 = curve._segment2;
  6472 	},
  6629 	},
  6473 
  6630 
  6474 	getSegment: function(_preferFirst) {
  6631 	_setSegment: function(segment) {
  6475 		if (!this._segment) {
  6632 		this._setCurve(segment.getCurve());
  6476 			var curve = this.getCurve(),
  6633 		this._segment = segment;
  6477 				parameter = this.getParameter();
  6634 		this._parameter = segment === this._segment1 ? 0 : 1;
  6478 			if (parameter === 1) {
  6635 		this._point = segment._point.clone();
  6479 				this._segment = curve._segment2;
  6636 	},
  6480 			} else if (parameter === 0 || _preferFirst) {
  6637 
  6481 				this._segment = curve._segment1;
  6638 	getSegment: function() {
  6482 			} else if (parameter == null) {
  6639 		var curve = this.getCurve(),
  6483 				return null;
  6640 			segment = this._segment;
  6484 			} else {
  6641 		if (!segment) {
  6485 				this._segment = curve.getPartLength(0, parameter)
  6642 			var parameter = this.getParameter();
       
  6643 			if (parameter === 0) {
       
  6644 				segment = curve._segment1;
       
  6645 			} else if (parameter === 1) {
       
  6646 				segment = curve._segment2;
       
  6647 			} else if (parameter != null) {
       
  6648 				segment = curve.getPartLength(0, parameter)
  6486 					< curve.getPartLength(parameter, 1)
  6649 					< curve.getPartLength(parameter, 1)
  6487 						? curve._segment1
  6650 						? curve._segment1
  6488 						: curve._segment2;
  6651 						: curve._segment2;
  6489 			}
  6652 			}
  6490 		}
  6653 			this._segment = segment;
  6491 		return this._segment;
  6654 		}
       
  6655 		return segment;
  6492 	},
  6656 	},
  6493 
  6657 
  6494 	getCurve: function() {
  6658 	getCurve: function() {
  6495 		var curve = this._curve,
  6659 		var curve = this._curve,
  6496 			path = curve && curve._path;
  6660 			path = curve && curve._path,
       
  6661 			that = this;
  6497 		if (path && path._version !== this._version) {
  6662 		if (path && path._version !== this._version) {
  6498 			curve = null;
  6663 			curve = this._parameter = this._curve = this._offset = null;
  6499 			this._parameter = null;
  6664 		}
  6500 		}
  6665 
  6501 		if (!curve) {
  6666 		function trySegment(segment) {
  6502 			curve = this._segment1.getCurve();
  6667 			var curve = segment && segment.getCurve();
  6503 			if (curve.getParameterOf(this._point) == null)
  6668 			if (curve && (that._parameter = curve.getParameterOf(that._point))
  6504 				curve = this._segment2.getPrevious().getCurve();
  6669 					!= null) {
  6505 			this._curve = curve;
  6670 				that._setCurve(curve);
  6506 			path = curve._path;
  6671 				that._segment = segment;
  6507 			this._version = path ? path._version : 0;
  6672 				return curve;
  6508 		}
  6673 			}
  6509 		return curve;
  6674 		}
       
  6675 
       
  6676 		return curve
       
  6677 			|| trySegment(this._segment)
       
  6678 			|| trySegment(this._segment1)
       
  6679 			|| trySegment(this._segment2.getPrevious());
  6510 	},
  6680 	},
  6511 
  6681 
  6512 	getPath: function() {
  6682 	getPath: function() {
  6513 		var curve = this.getCurve();
  6683 		var curve = this.getCurve();
  6514 		return curve && curve._path;
  6684 		return curve && curve._path;
  6530 	getPoint: function() {
  6700 	getPoint: function() {
  6531 		return this._point;
  6701 		return this._point;
  6532 	},
  6702 	},
  6533 
  6703 
  6534 	getOffset: function() {
  6704 	getOffset: function() {
  6535 		var path = this.getPath();
  6705 		var offset = this._offset;
  6536 		return path ? path._getOffset(this) : this.getCurveOffset();
  6706 		if (offset == null) {
       
  6707 			offset = 0;
       
  6708 			var path = this.getPath(),
       
  6709 				index = this.getIndex();
       
  6710 			if (path && index != null) {
       
  6711 				var curves = path.getCurves();
       
  6712 				for (var i = 0; i < index; i++)
       
  6713 					offset += curves[i].getLength();
       
  6714 			}
       
  6715 			this._offset = offset += this.getCurveOffset();
       
  6716 		}
       
  6717 		return offset;
  6537 	},
  6718 	},
  6538 
  6719 
  6539 	getCurveOffset: function() {
  6720 	getCurveOffset: function() {
  6540 		var curve = this.getCurve(),
  6721 		var curve = this.getCurve(),
  6541 			parameter = this.getParameter();
  6722 			parameter = this.getParameter();
  6542 		return parameter != null && curve && curve.getPartLength(0, parameter);
  6723 		return parameter != null && curve && curve.getPartLength(0, parameter);
  6543 	},
  6724 	},
  6544 
  6725 
  6545 	getIntersection: function() {
  6726 	getIntersection: function() {
  6546 		var intersection = this._intersection;
  6727 		return this._intersection;
  6547 		if (!intersection && this._curve2) {
       
  6548 			this._intersection = intersection = new CurveLocation(this._curve2,
       
  6549 					this._parameter2, this._point2 || this._point, this);
       
  6550 			intersection._intersection = this;
       
  6551 		}
       
  6552 		return intersection;
       
  6553 	},
  6728 	},
  6554 
  6729 
  6555 	getDistance: function() {
  6730 	getDistance: function() {
  6556 		return this._distance;
  6731 		return this._distance;
  6557 	},
  6732 	},
  6558 
  6733 
  6559 	divide: function() {
  6734 	divide: function() {
  6560 		var curve = this.getCurve();
  6735 		var curve = this.getCurve(),
  6561 		return curve && curve.divide(this.getParameter(), true);
  6736 			res = null;
       
  6737 		if (curve) {
       
  6738 			res = curve.divide(this.getParameter(), true);
       
  6739 			if (res)
       
  6740 				this._setSegment(res._segment1);
       
  6741 		}
       
  6742 		return res;
  6562 	},
  6743 	},
  6563 
  6744 
  6564 	split: function() {
  6745 	split: function() {
  6565 		var curve = this.getCurve();
  6746 		var curve = this.getCurve();
  6566 		return curve && curve.split(this.getParameter(), true);
  6747 		return curve ? curve.split(this.getParameter(), true) : null;
  6567 	},
  6748 	},
  6568 
  6749 
  6569 	equals: function(loc) {
  6750 	equals: function(loc, _ignoreOther) {
  6570 		var abs = Math.abs,
  6751 		var res = this === loc,
  6571 			tolerance = 0.000001;
  6752 			epsilon = 2e-7;
  6572 		return this === loc
  6753 		if (!res && loc instanceof CurveLocation
  6573 				|| loc instanceof CurveLocation
  6754 				&& this.getPath() === loc.getPath()
  6574 					&& this.getCurve() === loc.getCurve()
  6755 				&& this.getPoint().isClose(loc.getPoint(), epsilon)) {
  6575 					&& abs(this.getParameter() - loc.getParameter()) < tolerance
  6756 			var c1 = this.getCurve(),
  6576 					&& this._curve2 === loc._curve2
  6757 				c2 = loc.getCurve(),
  6577 					&& abs(this._parameter2 - loc._parameter2) < tolerance
  6758 				abs = Math.abs,
  6578 				|| false;
  6759 				diff = abs(
       
  6760 					((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
       
  6761 							+ this.getParameter()) -
       
  6762 					((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
       
  6763 							+ loc.getParameter()));
       
  6764 			res = (diff < 4e-7
       
  6765 				|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon
       
  6766 					|| abs(this.getPath().getLength() - diff) < epsilon))
       
  6767 				&& (_ignoreOther
       
  6768 					|| (!this._intersection && !loc._intersection
       
  6769 						|| this._intersection && this._intersection.equals(
       
  6770 								loc._intersection, true)));
       
  6771 		}
       
  6772 		return res;
  6579 	},
  6773 	},
  6580 
  6774 
  6581 	toString: function() {
  6775 	toString: function() {
  6582 		var parts = [],
  6776 		var parts = [],
  6583 			point = this.getPoint(),
  6777 			point = this.getPoint(),
  6591 		if (parameter != null)
  6785 		if (parameter != null)
  6592 			parts.push('parameter: ' + f.number(parameter));
  6786 			parts.push('parameter: ' + f.number(parameter));
  6593 		if (this._distance != null)
  6787 		if (this._distance != null)
  6594 			parts.push('distance: ' + f.number(this._distance));
  6788 			parts.push('distance: ' + f.number(this._distance));
  6595 		return '{ ' + parts.join(', ') + ' }';
  6789 		return '{ ' + parts.join(', ') + ' }';
       
  6790 	},
       
  6791 
       
  6792 	isTouching: function() {
       
  6793 		var inter = this._intersection;
       
  6794 		if (inter && this.getTangent().isCollinear(inter.getTangent())) {
       
  6795 			var curve1 = this.getCurve(),
       
  6796 				curve2 = inter.getCurve();
       
  6797 			return !(curve1.isStraight() && curve2.isStraight()
       
  6798 					&& curve1.getLine().intersect(curve2.getLine()));
       
  6799 		}
       
  6800 		return false;
       
  6801 	},
       
  6802 
       
  6803 	isCrossing: function() {
       
  6804 		var inter = this._intersection;
       
  6805 		if (!inter)
       
  6806 			return false;
       
  6807 		var t1 = this.getParameter(),
       
  6808 			t2 = inter.getParameter(),
       
  6809 			tMin = 4e-7,
       
  6810 			tMax = 1 - tMin;
       
  6811 		if (t1 >= tMin && t1 <= tMax || t2 >= tMin && t2 <= tMax)
       
  6812 			return !this.isTouching();
       
  6813 		var c2 = this.getCurve(),
       
  6814 			c1 = c2.getPrevious(),
       
  6815 			c4 = inter.getCurve(),
       
  6816 			c3 = c4.getPrevious(),
       
  6817 			PI = Math.PI;
       
  6818 		if (!c1 || !c3)
       
  6819 			return false;
       
  6820 
       
  6821 		function isInRange(angle, min, max) {
       
  6822 			return min < max
       
  6823 				? angle > min && angle < max
       
  6824 				: angle > min && angle <= PI || angle >= -PI && angle < max;
       
  6825 		}
       
  6826 
       
  6827 		var a1 = c1.getTangentAt(tMax, true).negate().getAngleInRadians(),
       
  6828 			a2 = c2.getTangentAt(tMin, true).getAngleInRadians(),
       
  6829 			a3 = c3.getTangentAt(tMax, true).negate().getAngleInRadians(),
       
  6830 			a4 = c4.getTangentAt(tMin, true).getAngleInRadians();
       
  6831 
       
  6832 		return (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2))
       
  6833 			&& (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1));
       
  6834 	},
       
  6835 
       
  6836 	isOverlap: function() {
       
  6837 		return !!this._overlap;
  6596 	}
  6838 	}
  6597 }, Base.each(Curve.evaluateMethods, function(name) {
  6839 }, Base.each(Curve.evaluateMethods, function(name) {
  6598 	if (name !== 'getPoint') {
  6840 	var get = name + 'At';
  6599 		var get = name + 'At';
  6841 	this[name] = function() {
  6600 		this[name] = function() {
  6842 		var parameter = this.getParameter(),
  6601 			var parameter = this.getParameter(),
  6843 			curve = this.getCurve();
  6602 				curve = this.getCurve();
  6844 		return parameter != null && curve && curve[get](parameter, true);
  6603 			return parameter != null && curve && curve[get](parameter, true);
  6845 	};
  6604 		};
  6846 }, {
  6605 	}
  6847 	preserve: true
  6606 }, {}));
  6848 }),
       
  6849 new function() {
       
  6850 
       
  6851 	function insert(locations, loc, merge) {
       
  6852 		var length = locations.length,
       
  6853 			l = 0,
       
  6854 			r = length - 1;
       
  6855 
       
  6856 		function search(index, dir) {
       
  6857 			for (var i = index + dir; i >= -1 && i <= length; i += dir) {
       
  6858 				var loc2 = locations[((i % length) + length) % length];
       
  6859 				if (!loc.getPoint().isClose(loc2.getPoint(),
       
  6860 						2e-7))
       
  6861 					break;
       
  6862 				if (loc.equals(loc2))
       
  6863 					return loc2;
       
  6864 			}
       
  6865 			return null;
       
  6866 		}
       
  6867 
       
  6868 		while (l <= r) {
       
  6869 			var m = (l + r) >>> 1,
       
  6870 				loc2 = locations[m],
       
  6871 				found;
       
  6872 			if (merge && (found = loc.equals(loc2) ? loc2
       
  6873 					: (search(m, -1) || search(m, 1)))) {
       
  6874 				if (loc._overlap) {
       
  6875 					found._overlap = found._intersection._overlap = true;
       
  6876 				}
       
  6877 				return found;
       
  6878 			}
       
  6879 		var path1 = loc.getPath(),
       
  6880 			path2 = loc2.getPath(),
       
  6881 			diff = path1 === path2
       
  6882 				? (loc.getIndex() + loc.getParameter())
       
  6883 				- (loc2.getIndex() + loc2.getParameter())
       
  6884 				: path1._id - path2._id;
       
  6885 			if (diff < 0) {
       
  6886 				r = m - 1;
       
  6887 			} else {
       
  6888 				l = m + 1;
       
  6889 			}
       
  6890 		}
       
  6891 		locations.splice(l, 0, loc);
       
  6892 		return loc;
       
  6893 	}
       
  6894 
       
  6895 	return { statics: {
       
  6896 		insert: insert,
       
  6897 
       
  6898 		expand: function(locations) {
       
  6899 			var expanded = locations.slice();
       
  6900 			for (var i = 0, l = locations.length; i < l; i++) {
       
  6901 				insert(expanded, locations[i]._intersection, false);
       
  6902 			}
       
  6903 			return expanded;
       
  6904 		}
       
  6905 	}};
       
  6906 });
  6607 
  6907 
  6608 var PathItem = Item.extend({
  6908 var PathItem = Item.extend({
  6609 	_class: 'PathItem',
  6909 	_class: 'PathItem',
  6610 
  6910 
  6611 	initialize: function PathItem() {
  6911 	initialize: function PathItem() {
  6612 	},
  6912 	},
  6613 
  6913 
  6614 	getIntersections: function(path, _matrix, _expand) {
  6914 	getIntersections: function(path, include, _matrix, _returnFirst) {
  6615 		if (this === path)
  6915 		var self = this === path || !path,
  6616 			path = null;
       
  6617 		var locations = [],
       
  6618 			curves1 = this.getCurves(),
       
  6619 			curves2 = path ? path.getCurves() : curves1,
       
  6620 			matrix1 = this._matrix.orNullIfIdentity(),
  6916 			matrix1 = this._matrix.orNullIfIdentity(),
  6621 			matrix2 = path ? (_matrix || path._matrix).orNullIfIdentity()
  6917 			matrix2 = self ? matrix1
  6622 				: matrix1,
  6918 				: (_matrix || path._matrix).orNullIfIdentity();
       
  6919 		if (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
       
  6920 			return [];
       
  6921 		var curves1 = this.getCurves(),
       
  6922 			curves2 = self ? curves1 : path.getCurves(),
  6623 			length1 = curves1.length,
  6923 			length1 = curves1.length,
  6624 			length2 = path ? curves2.length : length1,
  6924 			length2 = self ? length1 : curves2.length,
  6625 			values2 = [],
  6925 			values2 = [],
  6626 			tMin = 0.000001,
  6926 			arrays = [],
  6627 			tMax = 1 - tMin;
  6927 			locations,
  6628 		if (path && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
  6928 			path;
  6629 			return [];
       
  6630 		for (var i = 0; i < length2; i++)
  6929 		for (var i = 0; i < length2; i++)
  6631 			values2[i] = curves2[i].getValues(matrix2);
  6930 			values2[i] = curves2[i].getValues(matrix2);
  6632 		for (var i = 0; i < length1; i++) {
  6931 		for (var i = 0; i < length1; i++) {
  6633 			var curve1 = curves1[i],
  6932 			var curve1 = curves1[i],
  6634 				values1 = path ? curve1.getValues(matrix1) : values2[i];
  6933 				values1 = self ? values2[i] : curve1.getValues(matrix1),
  6635 			if (!path) {
  6934 				path1 = curve1.getPath();
  6636 				var seg1 = curve1.getSegment1(),
  6935 			if (path1 !== path) {
  6637 					seg2 = curve1.getSegment2(),
  6936 				path = path1;
  6638 					h1 = seg1._handleOut,
  6937 				locations = [];
  6639 					h2 = seg2._handleIn;
  6938 				arrays.push(locations);
  6640 				if (new Line(seg1._point.subtract(h1), h1.multiply(2), true)
  6939 			}
  6641 						.intersect(new Line(seg2._point.subtract(h2),
  6940 			if (self) {
  6642 						h2.multiply(2), true), false)) {
  6941 				Curve._getSelfIntersection(values1, curve1, locations, {
  6643 					var parts = Curve.subdivide(values1);
  6942 					include: include,
  6644 					Curve.getIntersections(
  6943 					startConnected: length1 === 1 &&
  6645 						parts[0], parts[1], curve1, curve1, locations,
  6944 							curve1.getPoint1().equals(curve1.getPoint2())
  6646 						function(loc) {
  6945 				});
  6647 							if (loc._parameter <= tMax) {
  6946 			}
  6648 								loc._parameter /= 2;
  6947 			for (var j = self ? i + 1 : 0; j < length2; j++) {
  6649 								loc._parameter2 = 0.5 + loc._parameter2 / 2;
  6948 				if (_returnFirst && locations.length)
  6650 								return true;
  6949 					return locations;
  6651 							}
  6950 				var curve2 = curves2[j];
  6652 						}
  6951 				Curve._getIntersections(
  6653 					);
  6952 					values1, values2[j], curve1, curve2, locations,
  6654 				}
  6953 					{
  6655 			}
  6954 						include: include,
  6656 			for (var j = path ? 0 : i + 1; j < length2; j++) {
  6955 						startConnected: self && curve1.getPrevious() === curve2,
  6657 				Curve.getIntersections(
  6956 						endConnected: self && curve1.getNext() === curve2
  6658 					values1, values2[j], curve1, curves2[j], locations,
  6957 					}
  6659 					!path && (j === i + 1 || j === length2 - 1 && i === 0)
       
  6660 						&& function(loc) {
       
  6661 							var t = loc._parameter;
       
  6662 							return t >= tMin && t <= tMax;
       
  6663 						}
       
  6664 				);
  6958 				);
  6665 			}
  6959 			}
  6666 		}
  6960 		}
  6667 		return Curve.filterIntersections(locations, _expand);
  6961 		locations = [];
       
  6962 		for (var i = 0, l = arrays.length; i < l; i++) {
       
  6963 			locations.push.apply(locations, arrays[i]);
       
  6964 		}
       
  6965 		return locations;
       
  6966 	},
       
  6967 
       
  6968 	getCrossings: function(path) {
       
  6969 		return this.getIntersections(path, function(inter) {
       
  6970 			return inter.isCrossing();
       
  6971 		});
  6668 	},
  6972 	},
  6669 
  6973 
  6670 	_asPathItem: function() {
  6974 	_asPathItem: function() {
  6671 		return this;
  6975 		return this;
  6672 	},
  6976 	},
  6838 		_changed.base.call(this, flags);
  7142 		_changed.base.call(this, flags);
  6839 		if (flags & 8) {
  7143 		if (flags & 8) {
  6840 			var parent = this._parent;
  7144 			var parent = this._parent;
  6841 			if (parent)
  7145 			if (parent)
  6842 				parent._currentPath = undefined;
  7146 				parent._currentPath = undefined;
  6843 			this._length = this._clockwise = undefined;
  7147 			this._length = this._area = this._clockwise = this._monoCurves =
       
  7148 					undefined;
  6844 			if (flags & 16) {
  7149 			if (flags & 16) {
  6845 				this._version++;
  7150 				this._version++;
  6846 			} else if (this._curves) {
  7151 			} else if (this._curves) {
  6847 			   for (var i = 0, l = this._curves.length; i < l; i++)
  7152 			   for (var i = 0, l = this._curves.length; i < l; i++)
  6848 					this._curves[i]._changed();
  7153 					this._curves[i]._changed();
  6849 			}
  7154 			}
  6850 			this._monoCurves = undefined;
       
  6851 		} else if (flags & 32) {
  7155 		} else if (flags & 32) {
  6852 			this._bounds = undefined;
  7156 			this._bounds = undefined;
  6853 		}
  7157 		}
  6854 	},
  7158 	},
  6855 
  7159 
  6975 
  7279 
  6976 	isEmpty: function() {
  7280 	isEmpty: function() {
  6977 		return this._segments.length === 0;
  7281 		return this._segments.length === 0;
  6978 	},
  7282 	},
  6979 
  7283 
  6980 	isLinear: function() {
       
  6981 		var segments = this._segments;
       
  6982 		for (var i = 0, l = segments.length; i < l; i++) {
       
  6983 			if (!segments[i].isLinear())
       
  6984 				return false;
       
  6985 		}
       
  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;
       
  6996 	},
       
  6997 
       
  6998 	_transformContent: function(matrix) {
  7284 	_transformContent: function(matrix) {
  6999 		var coords = new Array(6);
  7285 		var coords = new Array(6);
  7000 		for (var i = 0, l = this._segments.length; i < l; i++)
  7286 		for (var i = 0, l = this._segments.length; i < l; i++)
  7001 			this._segments[i]._transformCoordinates(matrix, coords, true);
  7287 			this._segments[i]._transformCoordinates(matrix, coords, true);
  7002 		return true;
  7288 		return true;
  7022 		} else {
  7308 		} else {
  7023 			segments.splice.apply(segments, [index, 0].concat(segs));
  7309 			segments.splice.apply(segments, [index, 0].concat(segs));
  7024 			for (var i = index + amount, l = segments.length; i < l; i++)
  7310 			for (var i = index + amount, l = segments.length; i < l; i++)
  7025 				segments[i]._index = i;
  7311 				segments[i]._index = i;
  7026 		}
  7312 		}
  7027 		if (curves || segs._curves) {
  7313 		if (curves) {
  7028 			if (!curves)
  7314 			var total = this._countCurves(),
  7029 				curves = this._curves = [];
  7315 				from = index + amount - 1 === total ? index - 1 : index,
  7030 			var from = index > 0 ? index - 1 : index,
       
  7031 				start = from,
  7316 				start = from,
  7032 				to = Math.min(from + amount, this._countCurves());
  7317 				to = Math.min(from + amount, total);
  7033 			if (segs._curves) {
  7318 			if (segs._curves) {
  7034 				curves.splice.apply(curves, [from, 0].concat(segs._curves));
  7319 				curves.splice.apply(curves, [from, 0].concat(segs._curves));
  7035 				start += segs._curves.length;
  7320 				start += segs._curves.length;
  7036 			}
  7321 			}
  7037 			for (var i = start; i < to; i++)
  7322 			for (var i = start; i < to; i++)
  7132 		return removed;
  7417 		return removed;
  7133 	},
  7418 	},
  7134 
  7419 
  7135 	clear: '#removeSegments',
  7420 	clear: '#removeSegments',
  7136 
  7421 
       
  7422 	hasHandles: function() {
       
  7423 		var segments = this._segments;
       
  7424 		for (var i = 0, l = segments.length; i < l; i++) {
       
  7425 			if (segments[i].hasHandles())
       
  7426 				return true;
       
  7427 		}
       
  7428 		return false;
       
  7429 	},
       
  7430 
       
  7431 	clearHandles: function() {
       
  7432 		var segments = this._segments;
       
  7433 		for (var i = 0, l = segments.length; i < l; i++)
       
  7434 			segments[i].clearHandles();
       
  7435 	},
       
  7436 
  7137 	getLength: function() {
  7437 	getLength: function() {
  7138 		if (this._length == null) {
  7438 		if (this._length == null) {
  7139 			var curves = this.getCurves();
  7439 			var curves = this.getCurves(),
  7140 			this._length = 0;
  7440 				length = 0;
  7141 			for (var i = 0, l = curves.length; i < l; i++)
  7441 			for (var i = 0, l = curves.length; i < l; i++)
  7142 				this._length += curves[i].getLength();
  7442 				length += curves[i].getLength();
       
  7443 			this._length = length;
  7143 		}
  7444 		}
  7144 		return this._length;
  7445 		return this._length;
  7145 	},
  7446 	},
  7146 
  7447 
  7147 	getArea: function() {
  7448 	getArea: function() {
  7148 		var curves = this.getCurves();
  7449 		if (this._area == null) {
  7149 		var area = 0;
  7450 			var segments = this._segments,
  7150 		for (var i = 0, l = curves.length; i < l; i++)
  7451 				count = segments.length,
  7151 			area += curves[i].getArea();
  7452 				last = count - 1,
  7152 		return area;
  7453 				area = 0;
       
  7454 			for (var i = 0, l = this._closed ? count : last; i < l; i++) {
       
  7455 				area += Curve.getArea(Curve.getValues(
       
  7456 						segments[i], segments[i < last ? i + 1 : 0]));
       
  7457 			}
       
  7458 			this._area = area;
       
  7459 		}
       
  7460 		return this._area;
       
  7461 	},
       
  7462 
       
  7463 	isClockwise: function() {
       
  7464 		if (this._clockwise !== undefined)
       
  7465 			return this._clockwise;
       
  7466 		return this.getArea() >= 0;
       
  7467 	},
       
  7468 
       
  7469 	setClockwise: function(clockwise) {
       
  7470 		if (this.isClockwise() != (clockwise = !!clockwise))
       
  7471 			this.reverse();
       
  7472 		this._clockwise = clockwise;
  7153 	},
  7473 	},
  7154 
  7474 
  7155 	isFullySelected: function() {
  7475 	isFullySelected: function() {
  7156 		var length = this._segments.length;
  7476 		var length = this._segments.length;
  7157 		return this._selected && length > 0 && this._selectedSegmentState
  7477 		return this._selected && length > 0 && this._selectedSegmentState
  7201 
  7521 
  7202 	reduce: function() {
  7522 	reduce: function() {
  7203 		var curves = this.getCurves();
  7523 		var curves = this.getCurves();
  7204 		for (var i = curves.length - 1; i >= 0; i--) {
  7524 		for (var i = curves.length - 1; i >= 0; i--) {
  7205 			var curve = curves[i];
  7525 			var curve = curves[i];
  7206 			if (curve.isLinear() && curve.getLength() === 0)
  7526 			if (!curve.hasHandles() && (curve.getLength() === 0
       
  7527 					|| curve.isCollinear(curve.getNext())))
  7207 				curve.remove();
  7528 				curve.remove();
  7208 		}
  7529 		}
  7209 		return this;
  7530 		return this;
  7210 	},
  7531 	},
  7211 
  7532 
  7226 			if (!arg)
  7547 			if (!arg)
  7227 				return null
  7548 				return null
  7228 			index = arg.index;
  7549 			index = arg.index;
  7229 			parameter = arg.parameter;
  7550 			parameter = arg.parameter;
  7230 		}
  7551 		}
  7231 		var tolerance = 0.000001;
  7552 		var tMin = 4e-7,
  7232 		if (parameter >= 1 - tolerance) {
  7553 			tMax = 1 - tMin;
       
  7554 		if (parameter >= tMax) {
  7233 			index++;
  7555 			index++;
  7234 			parameter--;
  7556 			parameter--;
  7235 		}
  7557 		}
  7236 		var curves = this.getCurves();
  7558 		var curves = this.getCurves();
  7237 		if (index >= 0 && index < curves.length) {
  7559 		if (index >= 0 && index < curves.length) {
  7238 			if (parameter > tolerance) {
  7560 			if (parameter >= tMin) {
  7239 				curves[index++].divide(parameter, true);
  7561 				curves[index++].divide(parameter, true);
  7240 			}
  7562 			}
  7241 			var segs = this.removeSegments(index, this._segments.length, true),
  7563 			var segs = this.removeSegments(index, this._segments.length, true),
  7242 				path;
  7564 				path;
  7243 			if (this._closed) {
  7565 			if (this._closed) {
  7244 				this.setClosed(false);
  7566 				this.setClosed(false);
  7245 				path = this;
  7567 				path = this;
  7246 			} else {
  7568 			} else {
  7247 				path = this._clone(new Path().insertAbove(this, true));
  7569 				path = new Path(Item.NO_INSERT);
       
  7570 				path.insertAbove(this, true);
       
  7571 				this._clone(path);
  7248 			}
  7572 			}
  7249 			path._add(segs, 0);
  7573 			path._add(segs, 0);
  7250 			this.addSegment(segs[0]);
  7574 			this.addSegment(segs[0]);
  7251 			return path;
  7575 			return path;
  7252 		}
  7576 		}
  7253 		return null;
  7577 		return null;
  7254 	},
       
  7255 
       
  7256 	isClockwise: function() {
       
  7257 		if (this._clockwise !== undefined)
       
  7258 			return this._clockwise;
       
  7259 		return Path.isClockwise(this._segments);
       
  7260 	},
       
  7261 
       
  7262 	setClockwise: function(clockwise) {
       
  7263 		if (this.isClockwise() != (clockwise = !!clockwise))
       
  7264 			this.reverse();
       
  7265 		this._clockwise = clockwise;
       
  7266 	},
  7578 	},
  7267 
  7579 
  7268 	reverse: function() {
  7580 	reverse: function() {
  7269 		this._segments.reverse();
  7581 		this._segments.reverse();
  7270 		for (var i = 0, l = this._segments.length; i < l; i++) {
  7582 		for (var i = 0, l = this._segments.length; i < l; i++) {
  7303 					this._add(segments.slice(0, segments.length - 1), 0);
  7615 					this._add(segments.slice(0, segments.length - 1), 0);
  7304 				} else {
  7616 				} else {
  7305 					this._add(segments.slice());
  7617 					this._add(segments.slice());
  7306 				}
  7618 				}
  7307 			}
  7619 			}
  7308 			if (path.closed)
  7620 			if (path._closed)
  7309 				this._add([segments[0]]);
  7621 				this._add([segments[0]]);
  7310 			path.remove();
  7622 			path.remove();
  7311 		}
  7623 		}
  7312 		var first = this.getFirstSegment(),
  7624 		var first = this.getFirstSegment(),
  7313 			last = this.getLastSegment();
  7625 			last = this.getLastSegment();
  7328 			size,
  7640 			size,
  7329 			radius,
  7641 			radius,
  7330 			topCenter;
  7642 			topCenter;
  7331 
  7643 
  7332 		function isCollinear(i, j) {
  7644 		function isCollinear(i, j) {
  7333 			return segments[i].isCollinear(segments[j]);
  7645 			var seg1 = segments[i],
       
  7646 				seg2 = seg1.getNext(),
       
  7647 				seg3 = segments[j],
       
  7648 				seg4 = seg3.getNext();
       
  7649 			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
       
  7650 					&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
       
  7651 					&& seg2._point.subtract(seg1._point).isCollinear(
       
  7652 						seg4._point.subtract(seg3._point));
  7334 		}
  7653 		}
  7335 
  7654 
  7336 		function isOrthogonal(i) {
  7655 		function isOrthogonal(i) {
  7337 			return segments[i].isOrthogonal();
  7656 			var seg2 = segments[i],
       
  7657 				seg1 = seg2.getPrevious(),
       
  7658 				seg3 = seg2.getNext();
       
  7659 			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
       
  7660 					&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
       
  7661 					&& seg2._point.subtract(seg1._point).isOrthogonal(
       
  7662 						seg3._point.subtract(seg2._point));
  7338 		}
  7663 		}
  7339 
  7664 
  7340 		function isArc(i) {
  7665 		function isArc(i) {
  7341 			return segments[i].isOrthogonalArc();
  7666 			var seg1 = segments[i],
       
  7667 				seg2 = seg1.getNext(),
       
  7668 				handle1 = seg1._handleOut,
       
  7669 				handle2 = seg2._handleIn,
       
  7670 				kappa = 0.5522847498307936;
       
  7671 			if (handle1.isOrthogonal(handle2)) {
       
  7672 				var pt1 = seg1._point,
       
  7673 					pt2 = seg2._point,
       
  7674 					corner = new Line(pt1, handle1, true).intersect(
       
  7675 							new Line(pt2, handle2, true), true);
       
  7676 				return corner && Numerical.isZero(handle1.getLength() /
       
  7677 						corner.subtract(pt1).getLength() - kappa)
       
  7678 					&& Numerical.isZero(handle2.getLength() /
       
  7679 						corner.subtract(pt2).getLength() - kappa);
       
  7680 			}
       
  7681 			return false;
  7342 		}
  7682 		}
  7343 
  7683 
  7344 		function getDistance(i, j) {
  7684 		function getDistance(i, j) {
  7345 			return segments[i]._point.getDistance(segments[j]._point);
  7685 			return segments[i]._point.getDistance(segments[j]._point);
  7346 		}
  7686 		}
  7513 		};
  7853 		};
  7514 	},
  7854 	},
  7515 {
  7855 {
  7516 	beans: false,
  7856 	beans: false,
  7517 
  7857 
  7518 	_getOffset: function(location) {
       
  7519 		var index = location && location.getIndex();
       
  7520 		if (index != null) {
       
  7521 			var curves = this.getCurves(),
       
  7522 				offset = 0;
       
  7523 			for (var i = 0; i < index; i++)
       
  7524 				offset += curves[i].getLength();
       
  7525 			var curve = curves[index],
       
  7526 				parameter = location.getParameter();
       
  7527 			if (parameter > 0)
       
  7528 				offset += curve.getPartLength(0, parameter);
       
  7529 			return offset;
       
  7530 		}
       
  7531 		return null;
       
  7532 	},
       
  7533 
       
  7534 	getLocationOf: function() {
  7858 	getLocationOf: function() {
  7535 		var point = Point.read(arguments),
  7859 		var point = Point.read(arguments),
  7536 			curves = this.getCurves();
  7860 			curves = this.getCurves();
  7537 		for (var i = 0, l = curves.length; i < l; i++) {
  7861 		for (var i = 0, l = curves.length; i < l; i++) {
  7538 			var loc = curves[i].getLocationOf(point);
  7862 			var loc = curves[i].getLocationOf(point);
  7561 			length += curve.getLength();
  7885 			length += curve.getLength();
  7562 			if (length > offset) {
  7886 			if (length > offset) {
  7563 				return curve.getLocationAt(offset - start);
  7887 				return curve.getLocationAt(offset - start);
  7564 			}
  7888 			}
  7565 		}
  7889 		}
  7566 		if (offset <= this.getLength())
  7890 		if (curves.length > 0 && offset <= this.getLength())
  7567 			return new CurveLocation(curves[curves.length - 1], 1);
  7891 			return new CurveLocation(curves[curves.length - 1], 1);
  7568 		return null;
  7892 		return null;
  7569 	},
  7893 	},
  7570 
  7894 
  7571 	getNearestLocation: function() {
  7895 	getNearestLocation: function() {
  7584 	},
  7908 	},
  7585 
  7909 
  7586 	getNearestPoint: function() {
  7910 	getNearestPoint: function() {
  7587 		return this.getNearestLocation.apply(this, arguments).getPoint();
  7911 		return this.getNearestLocation.apply(this, arguments).getPoint();
  7588 	}
  7912 	}
  7589 }), new function() {
  7913 }),
       
  7914 new function() {
  7590 
  7915 
  7591 	function drawHandles(ctx, segments, matrix, size) {
  7916 	function drawHandles(ctx, segments, matrix, size) {
  7592 		var half = size / 2;
  7917 		var half = size / 2;
  7593 
  7918 
  7594 		function drawHandle(index) {
  7919 		function drawHandle(index) {
  7748 			drawSegments(ctx, this, matrix);
  8073 			drawSegments(ctx, this, matrix);
  7749 			ctx.stroke();
  8074 			ctx.stroke();
  7750 			drawHandles(ctx, this._segments, matrix, paper.settings.handleSize);
  8075 			drawHandles(ctx, this._segments, matrix, paper.settings.handleSize);
  7751 		}
  8076 		}
  7752 	};
  8077 	};
  7753 }, new function() {
  8078 },
  7754 
  8079 new function() {
  7755 	function getFirstControlPoints(rhs) {
  8080 	function getFirstControlPoints(rhs) {
  7756 		var n = rhs.length,
  8081 		var n = rhs.length,
  7757 			x = [],
  8082 			x = [],
  7758 			tmp = [],
  8083 			tmp = [],
  7759 			b = 2;
  8084 			b = 2;
  7841 				var segment = this._segments[0];
  8166 				var segment = this._segments[0];
  7842 				segment.setHandleIn(handleIn.subtract(segment._point));
  8167 				segment.setHandleIn(handleIn.subtract(segment._point));
  7843 			}
  8168 			}
  7844 		}
  8169 		}
  7845 	};
  8170 	};
  7846 }, new function() {
  8171 },
       
  8172 new function() {
  7847 	function getCurrentSegment(that) {
  8173 	function getCurrentSegment(that) {
  7848 		var segments = that._segments;
  8174 		var segments = that._segments;
  7849 		if (segments.length === 0)
  8175 		if (segments.length === 0)
  7850 			throw new Error('Use a moveTo() command first');
  8176 			throw new Error('Use a moveTo() command first');
  7851 		return segments[segments.length - 1];
  8177 		return segments[segments.length - 1];
  7927 					middle = from.add(to).divide(2),
  8253 					middle = from.add(to).divide(2),
  7928 					pt = from.subtract(middle).rotate(-rotation),
  8254 					pt = from.subtract(middle).rotate(-rotation),
  7929 					x = pt.x,
  8255 					x = pt.x,
  7930 					y = pt.y,
  8256 					y = pt.y,
  7931 					abs = Math.abs,
  8257 					abs = Math.abs,
  7932 					epsilon = 1e-12,
       
  7933 					rx = abs(radius.width),
  8258 					rx = abs(radius.width),
  7934 					ry = abs(radius.height),
  8259 					ry = abs(radius.height),
  7935 					rxSq = rx * rx,
  8260 					rxSq = rx * rx,
  7936 					rySq = ry * ry,
  8261 					rySq = ry * ry,
  7937 					xSq =  x * x,
  8262 					xSq =  x * x,
  7943 					rxSq = rx * rx;
  8268 					rxSq = rx * rx;
  7944 					rySq = ry * ry;
  8269 					rySq = ry * ry;
  7945 				}
  8270 				}
  7946 				factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
  8271 				factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
  7947 						(rxSq * ySq + rySq * xSq);
  8272 						(rxSq * ySq + rySq * xSq);
  7948 				if (abs(factor) < epsilon)
  8273 				if (abs(factor) < 1e-12)
  7949 					factor = 0;
  8274 					factor = 0;
  7950 				if (factor < 0)
  8275 				if (factor < 0)
  7951 					throw new Error(
  8276 					throw new Error(
  7952 							'Cannot create an arc with the given arguments');
  8277 							'Cannot create an arc with the given arguments');
  7953 				center = new Point(rx * y / ry, -ry * x / rx)
  8278 				center = new Point(rx * y / ry, -ry * x / rx)
  8073 		return Path[getter](this._segments, this._closed, this.getStyle(),
  8398 		return Path[getter](this._segments, this._closed, this.getStyle(),
  8074 				matrix);
  8399 				matrix);
  8075 	},
  8400 	},
  8076 
  8401 
  8077 statics: {
  8402 statics: {
  8078 	isClockwise: function(segments) {
       
  8079 		var sum = 0;
       
  8080 		for (var i = 0, l = segments.length; i < l; i++)
       
  8081 			sum += Curve.getEdgeSum(Curve.getValues(
       
  8082 					segments[i], segments[i + 1 < l ? i + 1 : 0]));
       
  8083 		return sum > 0;
       
  8084 	},
       
  8085 
       
  8086 	getBounds: function(segments, closed, style, matrix, strokePadding) {
  8403 	getBounds: function(segments, closed, style, matrix, strokePadding) {
  8087 		var first = segments[0];
  8404 		var first = segments[0];
  8088 		if (!first)
  8405 		if (!first)
  8089 			return new Rectangle();
  8406 			return new Rectangle();
  8090 		var coords = new Array(6),
  8407 		var coords = new Array(6),
  8425 			}
  8742 			}
  8426 		}
  8743 		}
  8427 	},
  8744 	},
  8428 
  8745 
  8429 	insertChildren: function insertChildren(index, items, _preserve) {
  8746 	insertChildren: function insertChildren(index, items, _preserve) {
       
  8747 		for (var i = items.length - 1; i >= 0; i--) {
       
  8748 			var item = items[i];
       
  8749 			if (item instanceof CompoundPath) {
       
  8750 				items.splice.apply(items, [i, 1].concat(item.removeChildren()));
       
  8751 				item.remove();
       
  8752 			}
       
  8753 		}
  8430 		items = insertChildren.base.call(this, index, items, _preserve, Path);
  8754 		items = insertChildren.base.call(this, index, items, _preserve, Path);
  8431 		for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
  8755 		for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
  8432 			var item = items[i];
  8756 			var item = items[i];
  8433 			if (item._clockwise === undefined)
  8757 			if (item._clockwise === undefined)
  8434 				item.setClockwise(item._index === 0);
  8758 				item.setClockwise(item._index === 0);
  8446 		for (var i = 0, l = this._children.length; i < l; i++)
  8770 		for (var i = 0, l = this._children.length; i < l; i++)
  8447 			this._children[i].smooth();
  8771 			this._children[i].smooth();
  8448 	},
  8772 	},
  8449 
  8773 
  8450 	reduce: function reduce() {
  8774 	reduce: function reduce() {
  8451 		if (this._children.length === 0) {
  8775 		var children = this._children;
       
  8776 		for (var i = children.length - 1; i >= 0; i--) {
       
  8777 			var path = children[i].reduce();
       
  8778 			if (path.isEmpty())
       
  8779 				children.splice(i, 1);
       
  8780 		}
       
  8781 		if (children.length === 0) {
  8452 			var path = new Path(Item.NO_INSERT);
  8782 			var path = new Path(Item.NO_INSERT);
  8453 			path.insertAbove(this);
  8783 			path.insertAbove(this);
  8454 			path.setStyle(this._style);
  8784 			path.setStyle(this._style);
  8455 			this.remove();
  8785 			this.remove();
  8456 			return path;
  8786 			return path;
  8457 		} else {
  8787 		}
  8458 			return reduce.base.call(this);
  8788 		return reduce.base.call(this);
  8459 		}
       
  8460 	},
  8789 	},
  8461 
  8790 
  8462 	isClockwise: function() {
  8791 	isClockwise: function() {
  8463 		var child = this.getFirstChild();
  8792 		var child = this.getFirstChild();
  8464 		return child && child.isClockwise();
  8793 		return child && child.isClockwise();
  8512 			paths = [];
  8841 			paths = [];
  8513 		for (var i = 0, l = children.length; i < l; i++) {
  8842 		for (var i = 0, l = children.length; i < l; i++) {
  8514 			var child = children[i],
  8843 			var child = children[i],
  8515 				mx = child._matrix;
  8844 				mx = child._matrix;
  8516 			paths.push(child.getPathData(_matrix && !mx.isIdentity()
  8845 			paths.push(child.getPathData(_matrix && !mx.isIdentity()
  8517 					? _matrix.chain(mx) : mx, _precision));
  8846 					? _matrix.chain(mx) : _matrix, _precision));
  8518 		}
  8847 		}
  8519 		return paths.join(' ');
  8848 		return paths.join(' ');
  8520 	}
  8849 	}
  8521 }, {
  8850 }, {
  8522 	_getChildHitTestOptions: function(options) {
  8851 	_getChildHitTestOptions: function(options) {
  8560 			if (!selectedItems[child._id])
  8889 			if (!selectedItems[child._id])
  8561 				child._drawSelected(ctx, mx.isIdentity() ? matrix
  8890 				child._drawSelected(ctx, mx.isIdentity() ? matrix
  8562 						: matrix.chain(mx));
  8891 						: matrix.chain(mx));
  8563 		}
  8892 		}
  8564 	}
  8893 	}
  8565 }, new function() {
  8894 },
       
  8895 new function() {
  8566 	function getCurrentPath(that, check) {
  8896 	function getCurrentPath(that, check) {
  8567 		var children = that._children;
  8897 		var children = that._children;
  8568 		if (check && children.length === 0)
  8898 		if (check && children.length === 0)
  8569 			throw new Error('Use a moveTo() command first');
  8899 			throw new Error('Use a moveTo() command first');
  8570 		return children[children.length - 1];
  8900 		return children[children.length - 1];
  8571 	}
  8901 	}
  8572 
  8902 
  8573 	var fields = {
  8903 	var fields = {
  8574 		moveTo: function() {
  8904 		moveTo: function() {
  8575 			var current = getCurrentPath(this),
  8905 			var current = getCurrentPath(this),
  8576 				path = current && current.isEmpty() ? current : new Path();
  8906 				path = current && current.isEmpty() ? current
       
  8907 						: new Path(Item.NO_INSERT);
  8577 			if (path !== current)
  8908 			if (path !== current)
  8578 				this.addChild(path);
  8909 				this.addChild(path);
  8579 			path.moveTo.apply(path, arguments);
  8910 			path.moveTo.apply(path, arguments);
  8580 		},
  8911 		},
  8581 
  8912 
  8621 		exclude: function(w) {
  8952 		exclude: function(w) {
  8622 			return w === 1;
  8953 			return w === 1;
  8623 		}
  8954 		}
  8624 	};
  8955 	};
  8625 
  8956 
       
  8957 	function preparePath(path, resolve) {
       
  8958 		var res = path.clone(false).reduce().transform(null, true, true);
       
  8959 		return resolve ? res.resolveCrossings().reorient() : res;
       
  8960 	}
       
  8961 
       
  8962 	function finishBoolean(ctor, paths, path1, path2, reduce) {
       
  8963 		var result = new ctor(Item.NO_INSERT);
       
  8964 		result.addChildren(paths, true);
       
  8965 		if (reduce)
       
  8966 			result = result.reduce();
       
  8967 		result.insertAbove(path2 && path1.isSibling(path2)
       
  8968 				&& path1.getIndex() < path2.getIndex()
       
  8969 					? path2 : path1);
       
  8970 		result.setStyle(path1._style);
       
  8971 		return result;
       
  8972 	}
       
  8973 
  8626 	function computeBoolean(path1, path2, operation) {
  8974 	function computeBoolean(path1, path2, operation) {
  8627 		var operator = operators[operation];
  8975 		if (!path1._children && !path1._closed)
  8628 		function preparePath(path) {
  8976 			return computeOpenBoolean(path1, path2, operation);
  8629 			return path.clone(false).reduce().reorient().transform(null, true,
  8977 		var _path1 = preparePath(path1, true),
  8630 					true);
  8978 			_path2 = path2 && path1 !== path2 && preparePath(path2, true);
  8631 		}
       
  8632 
       
  8633 		var _path1 = preparePath(path1),
       
  8634 			_path2 = path2 && path1 !== path2 && preparePath(path2);
       
  8635 		if (_path2 && /^(subtract|exclude)$/.test(operation)
  8979 		if (_path2 && /^(subtract|exclude)$/.test(operation)
  8636 				^ (_path2.isClockwise() !== _path1.isClockwise()))
  8980 				^ (_path2.isClockwise() !== _path1.isClockwise()))
  8637 			_path2.reverse();
  8981 			_path2.reverse();
  8638 		splitPath(_path1.getIntersections(_path2, null, true));
  8982 		var intersections = CurveLocation.expand(
  8639 
  8983 			_path1.getIntersections(_path2, function(inter) {
  8640 		var chain = [],
  8984 				return _path2 && inter.isOverlap() || inter.isCrossing();
  8641 			segments = [],
  8985 			})
  8642 			monoCurves = [],
  8986 		);
  8643 			tolerance = 0.000001;
  8987 		divideLocations(intersections);
       
  8988 
       
  8989 		var segments = [],
       
  8990 			monoCurves = [];
  8644 
  8991 
  8645 		function collect(paths) {
  8992 		function collect(paths) {
  8646 			for (var i = 0, l = paths.length; i < l; i++) {
  8993 			for (var i = 0, l = paths.length; i < l; i++) {
  8647 				var path = paths[i];
  8994 				var path = paths[i];
  8648 				segments.push.apply(segments, path._segments);
  8995 				segments.push.apply(segments, path._segments);
  8651 		}
  8998 		}
  8652 
  8999 
  8653 		collect(_path1._children || [_path1]);
  9000 		collect(_path1._children || [_path1]);
  8654 		if (_path2)
  9001 		if (_path2)
  8655 			collect(_path2._children || [_path2]);
  9002 			collect(_path2._children || [_path2]);
  8656 		segments.sort(function(a, b) {
  9003 		for (var i = 0, l = intersections.length; i < l; i++) {
  8657 			var _a = a._intersection,
  9004 			propagateWinding(intersections[i]._segment, _path1, _path2,
  8658 				_b = b._intersection;
  9005 					monoCurves, operation);
  8659 			return !_a && !_b || _a && _b ? 0 : _a ? -1 : 1;
  9006 		}
  8660 		});
       
  8661 		for (var i = 0, l = segments.length; i < l; i++) {
  9007 		for (var i = 0, l = segments.length; i < l; i++) {
  8662 			var segment = segments[i];
  9008 			var segment = segments[i];
  8663 			if (segment._winding != null)
  9009 			if (segment._winding == null) {
  8664 				continue;
  9010 				propagateWinding(segment, _path1, _path2, monoCurves,
  8665 			chain.length = 0;
  9011 						operation);
  8666 			var startSeg = segment,
  9012 			}
  8667 				totalLength = 0,
  9013 		}
  8668 				windingSum = 0;
  9014 		return finishBoolean(CompoundPath, tracePaths(segments, operation),
  8669 			do {
  9015 				path1, path2, true);
  8670 				var length = segment.getCurve().getLength();
  9016 	}
  8671 				chain.push({ segment: segment, length: length });
  9017 
  8672 				totalLength += length;
  9018 	function computeOpenBoolean(path1, path2, operation) {
  8673 				segment = segment.getNext();
  9019 		if (!path2 || !path2._children && !path2._closed
  8674 			} while (segment && !segment._intersection && segment !== startSeg);
  9020 				|| !/^(subtract|intersect)$/.test(operation))
  8675 			for (var j = 0; j < 3; j++) {
  9021 			return null;
  8676 				var length = totalLength * (j + 1) / 4;
  9022 		var _path1 = preparePath(path1, false),
  8677 				for (var k = 0, m = chain.length; k < m; k++) {
  9023 			_path2 = preparePath(path2, false),
  8678 					var node = chain[k],
  9024 			intersections = _path1.getIntersections(_path2, function(inter) {
  8679 						curveLength = node.length;
  9025 				return inter.isOverlap() || inter.isCrossing();
  8680 					if (length <= curveLength) {
  9026 			}),
  8681 						if (length < tolerance
  9027 			sub = operation === 'subtract',
  8682 								|| curveLength - length < tolerance)
  9028 			paths = [];
  8683 							length = curveLength / 2;
  9029 
  8684 						var curve = node.segment.getCurve(),
  9030 		function addPath(path) {
  8685 							pt = curve.getPointAt(length),
  9031 			if (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {
  8686 							hor = curve.isLinear() && Math.abs(curve
  9032 				paths.unshift(path);
  8687 									.getTangentAt(0.5, true).y) < tolerance,
  9033 				return true;
  8688 							path = curve._path;
  9034 			}
  8689 						if (path._parent instanceof CompoundPath)
  9035 		}
  8690 							path = path._parent;
  9036 
  8691 						windingSum += operation === 'subtract' && _path2
  9037 		for (var i = intersections.length - 1; i >= 0; i--) {
  8692 							&& (path === _path1 && _path2._getWinding(pt, hor)
  9038 			var path = intersections[i].split();
  8693 							|| path === _path2 && !_path1._getWinding(pt, hor))
  9039 			if (path) {
  8694 							? 0
  9040 				if (addPath(path))
  8695 							: getWinding(pt, monoCurves, hor);
  9041 					path.getFirstSegment().setHandleIn(0, 0);
  8696 						break;
  9042 				_path1.getLastSegment().setHandleOut(0, 0);
  8697 					}
  9043 			}
  8698 					length -= curveLength;
  9044 		}
       
  9045 		addPath(_path1);
       
  9046 		return finishBoolean(Group, paths, path1, path2);
       
  9047 	}
       
  9048 
       
  9049 	function linkIntersections(from, to) {
       
  9050 		var prev = from;
       
  9051 		while (prev) {
       
  9052 			if (prev === to)
       
  9053 				return;
       
  9054 			prev = prev._prev;
       
  9055 		}
       
  9056 		while (from._next && from._next !== to)
       
  9057 			from = from._next;
       
  9058 		if (!from._next) {
       
  9059 			while (to._prev)
       
  9060 				to = to._prev;
       
  9061 			from._next = to;
       
  9062 			to._prev = from;
       
  9063 		}
       
  9064 	}
       
  9065 
       
  9066 	function divideLocations(locations) {
       
  9067 		var tMin = 4e-7,
       
  9068 			tMax = 1 - tMin,
       
  9069 			noHandles = false,
       
  9070 			clearSegments = [],
       
  9071 			prevCurve,
       
  9072 			prevT;
       
  9073 
       
  9074 		for (var i = locations.length - 1; i >= 0; i--) {
       
  9075 			var loc = locations[i],
       
  9076 				curve = loc._curve,
       
  9077 				t = loc._parameter,
       
  9078 				origT = t;
       
  9079 			if (curve !== prevCurve) {
       
  9080 				noHandles = !curve.hasHandles();
       
  9081 			} else if (prevT > 0) {
       
  9082 				t /= prevT;
       
  9083 			}
       
  9084 			var segment;
       
  9085 			if (t < tMin) {
       
  9086 				segment = curve._segment1;
       
  9087 			} else if (t > tMax) {
       
  9088 				segment = curve._segment2;
       
  9089 			} else {
       
  9090 				segment = curve.divide(t, true, true)._segment1;
       
  9091 				if (noHandles)
       
  9092 					clearSegments.push(segment);
       
  9093 			}
       
  9094 			loc._setSegment(segment);
       
  9095 			var inter = segment._intersection,
       
  9096 				dest = loc._intersection;
       
  9097 			if (inter) {
       
  9098 				linkIntersections(inter, dest);
       
  9099 				var other = inter;
       
  9100 				while (other) {
       
  9101 					linkIntersections(other._intersection, inter);
       
  9102 					other = other._next;
  8699 				}
  9103 				}
  8700 			}
       
  8701 			var winding = Math.round(windingSum / 3);
       
  8702 			for (var j = chain.length - 1; j >= 0; j--)
       
  8703 				chain[j].segment._winding = winding;
       
  8704 		}
       
  8705 		var result = new CompoundPath(Item.NO_INSERT);
       
  8706 		result.insertAbove(path1);
       
  8707 		result.addChildren(tracePaths(segments, operator), true);
       
  8708 		result = result.reduce();
       
  8709 		result.setStyle(path1._style);
       
  8710 		return result;
       
  8711 	}
       
  8712 
       
  8713 	function splitPath(intersections) {
       
  8714 		var tMin = 0.000001,
       
  8715 			tMax = 1 - tMin,
       
  8716 			linearHandles;
       
  8717 
       
  8718 		function resetLinear() {
       
  8719 			for (var i = 0, l = linearHandles.length; i < l; i++)
       
  8720 				linearHandles[i].set(0, 0);
       
  8721 		}
       
  8722 
       
  8723 		for (var i = intersections.length - 1, curve, prev; i >= 0; i--) {
       
  8724 			var loc = intersections[i],
       
  8725 				t = loc._parameter;
       
  8726 			if (prev && prev._curve === loc._curve && prev._parameter > 0) {
       
  8727 				t /= prev._parameter;
       
  8728 			} else {
  9104 			} else {
  8729 				curve = loc._curve;
  9105 				segment._intersection = dest;
  8730 				if (linearHandles)
  9106 			}
  8731 					resetLinear();
  9107 			prevCurve = curve;
  8732 				linearHandles = curve.isLinear() ? [
  9108 			prevT = origT;
  8733 						curve._segment1._handleOut,
  9109 		}
  8734 						curve._segment2._handleIn
  9110 		for (var i = 0, l = clearSegments.length; i < l; i++) {
  8735 					] : null;
  9111 			clearSegments[i].clearHandles();
  8736 			}
  9112 		}
  8737 			var newCurve,
       
  8738 				segment;
       
  8739 			if (newCurve = curve.divide(t, true, true)) {
       
  8740 				segment = newCurve._segment1;
       
  8741 				curve = newCurve.getPrevious();
       
  8742 				if (linearHandles)
       
  8743 					linearHandles.push(segment._handleOut, segment._handleIn);
       
  8744 			} else {
       
  8745 				segment = t < tMin
       
  8746 					? curve._segment1
       
  8747 					: t > tMax
       
  8748 						? curve._segment2
       
  8749 						: curve.getPartLength(0, t) < curve.getPartLength(t, 1)
       
  8750 							? curve._segment1
       
  8751 							: curve._segment2;
       
  8752 			}
       
  8753 			segment._intersection = loc.getIntersection();
       
  8754 			loc._segment = segment;
       
  8755 			prev = loc;
       
  8756 		}
       
  8757 		if (linearHandles)
       
  8758 			resetLinear();
       
  8759 	}
  9113 	}
  8760 
  9114 
  8761 	function getWinding(point, curves, horizontal, testContains) {
  9115 	function getWinding(point, curves, horizontal, testContains) {
  8762 		var tolerance = 0.000001,
  9116 		var epsilon = 2e-7,
  8763 			tMin = tolerance,
  9117 			tMin = 4e-7,
  8764 			tMax = 1 - tMin,
  9118 			tMax = 1 - tMin,
  8765 			px = point.x,
  9119 			px = point.x,
  8766 			py = point.y,
  9120 			py = point.y,
  8767 			windLeft = 0,
  9121 			windLeft = 0,
  8768 			windRight = 0,
  9122 			windRight = 0,
  8769 			roots = [],
  9123 			roots = [],
  8770 			abs = Math.abs;
  9124 			abs = Math.abs;
  8771 		if (horizontal) {
  9125 		if (horizontal) {
  8772 			var yTop = -Infinity,
  9126 			var yTop = -Infinity,
  8773 				yBottom = Infinity,
  9127 				yBottom = Infinity,
  8774 				yBefore = py - tolerance,
  9128 				yBefore = py - epsilon,
  8775 				yAfter = py + tolerance;
  9129 				yAfter = py + epsilon;
  8776 			for (var i = 0, l = curves.length; i < l; i++) {
  9130 			for (var i = 0, l = curves.length; i < l; i++) {
  8777 				var values = curves[i].values;
  9131 				var values = curves[i].values;
  8778 				if (Curve.solveCubic(values, 0, px, roots, 0, 1) > 0) {
  9132 				if (Curve.solveCubic(values, 0, px, roots, 0, 1) > 0) {
  8779 					for (var j = roots.length - 1; j >= 0; j--) {
  9133 					for (var j = roots.length - 1; j >= 0; j--) {
  8780 						var y = Curve.getPoint(values, roots[j]).y;
  9134 						var y = Curve.getPoint(values, roots[j]).y;
  8787 				}
  9141 				}
  8788 			}
  9142 			}
  8789 			yTop = (yTop + py) / 2;
  9143 			yTop = (yTop + py) / 2;
  8790 			yBottom = (yBottom + py) / 2;
  9144 			yBottom = (yBottom + py) / 2;
  8791 			if (yTop > -Infinity)
  9145 			if (yTop > -Infinity)
  8792 				windLeft = getWinding(new Point(px, yTop), curves);
  9146 				windLeft = getWinding(new Point(px, yTop), curves, false,
       
  9147 						testContains);
  8793 			if (yBottom < Infinity)
  9148 			if (yBottom < Infinity)
  8794 				windRight = getWinding(new Point(px, yBottom), curves);
  9149 				windRight = getWinding(new Point(px, yBottom), curves, false,
       
  9150 						testContains);
  8795 		} else {
  9151 		} else {
  8796 			var xBefore = px - tolerance,
  9152 			var xBefore = px - epsilon,
  8797 				xAfter = px + tolerance;
  9153 				xAfter = px + epsilon;
  8798 			var startCounted = false,
  9154 			var startCounted = false,
  8799 				prevCurve,
  9155 				prevCurve,
  8800 				prevT;
  9156 				prevT;
  8801 			for (var i = 0, l = curves.length; i < l; i++) {
  9157 			for (var i = 0, l = curves.length; i < l; i++) {
  8802 				var curve = curves[i],
  9158 				var curve = curves[i],
  8812 						|| t < tMin && prevT > tMax
  9168 						|| t < tMin && prevT > tMax
  8813 							&& curve.previous === prevCurve)) {
  9169 							&& curve.previous === prevCurve)) {
  8814 						var x = Curve.getPoint(values, t).x,
  9170 						var x = Curve.getPoint(values, t).x,
  8815 							slope = Curve.getTangent(values, t).y,
  9171 							slope = Curve.getTangent(values, t).y,
  8816 							counted = false;
  9172 							counted = false;
  8817 						if (Numerical.isZero(slope) && !Curve.isLinear(values)
  9173 						if (Numerical.isZero(slope) && !Curve.isStraight(values)
  8818 								|| t < tMin && slope * Curve.getTangent(
  9174 								|| t < tMin && slope * Curve.getTangent(
  8819 									curve.previous.values, 1).y < 0
  9175 									curve.previous.values, 1).y < 0
  8820 								|| t > tMax && slope * Curve.getTangent(
  9176 								|| t > tMax && slope * Curve.getTangent(
  8821 									curve.next.values, 0).y < 0) {
  9177 									curve.next.values, 0).y < 0) {
  8822 							if (testContains && x >= xBefore && x <= xAfter) {
  9178 							if (testContains && x >= xBefore && x <= xAfter) {
  8840 			}
  9196 			}
  8841 		}
  9197 		}
  8842 		return Math.max(abs(windLeft), abs(windRight));
  9198 		return Math.max(abs(windLeft), abs(windRight));
  8843 	}
  9199 	}
  8844 
  9200 
  8845 	function tracePaths(segments, operator, selfOp) {
  9201 	function propagateWinding(segment, path1, path2, monoCurves, operation) {
       
  9202 		var epsilon = 2e-7,
       
  9203 			chain = [],
       
  9204 			start = segment,
       
  9205 			totalLength = 0,
       
  9206 			windingSum = 0;
       
  9207 		do {
       
  9208 			var curve = segment.getCurve(),
       
  9209 				length = curve.getLength();
       
  9210 			chain.push({ segment: segment, curve: curve, length: length });
       
  9211 			totalLength += length;
       
  9212 			segment = segment.getNext();
       
  9213 		} while (segment && !segment._intersection && segment !== start);
       
  9214 		for (var i = 0; i < 3; i++) {
       
  9215 			var length = totalLength * (i + 1) / 4;
       
  9216 			for (var k = 0, m = chain.length; k < m; k++) {
       
  9217 				var node = chain[k],
       
  9218 					curveLength = node.length;
       
  9219 				if (length <= curveLength) {
       
  9220 					if (length < epsilon || curveLength - length < epsilon)
       
  9221 						length = curveLength / 2;
       
  9222 					var curve = node.curve,
       
  9223 						path = curve._path,
       
  9224 						parent = path._parent,
       
  9225 						pt = curve.getPointAt(length),
       
  9226 						hor = curve.isHorizontal();
       
  9227 					if (parent instanceof CompoundPath)
       
  9228 						path = parent;
       
  9229 					windingSum += operation === 'subtract' && path2
       
  9230 						&& (path === path1 && path2._getWinding(pt, hor)
       
  9231 						|| path === path2 && !path1._getWinding(pt, hor))
       
  9232 						? 0
       
  9233 						: getWinding(pt, monoCurves, hor);
       
  9234 					break;
       
  9235 				}
       
  9236 				length -= curveLength;
       
  9237 			}
       
  9238 		}
       
  9239 		var winding = Math.round(windingSum / 3);
       
  9240 		for (var j = chain.length - 1; j >= 0; j--)
       
  9241 			chain[j].segment._winding = winding;
       
  9242 	}
       
  9243 
       
  9244 	function tracePaths(segments, operation) {
  8846 		var paths = [],
  9245 		var paths = [],
  8847 			tMin = 0.000001,
  9246 			start,
  8848 			tMax = 1 - tMin;
  9247 			otherStart,
  8849 		for (var i = 0, seg, startSeg, l = segments.length; i < l; i++) {
  9248 			operator = operators[operation],
  8850 			seg = startSeg = segments[i];
  9249 			overlapWinding = {
  8851 			if (seg._visited || !operator(seg._winding))
  9250 				unite: { 1: 2 },
       
  9251 				intersect: { 2: 1 }
       
  9252 			}[operation];
       
  9253 
       
  9254 		function isValid(seg, adjusted) {
       
  9255 			if (seg._visited)
       
  9256 				return false;
       
  9257 			if (!operator)
       
  9258 				return true;
       
  9259 			var winding = seg._winding,
       
  9260 				inter = seg._intersection;
       
  9261 			if (inter && adjusted && overlapWinding && inter.isOverlap())
       
  9262 				winding = overlapWinding[winding] || winding;
       
  9263 			return operator(winding);
       
  9264 		}
       
  9265 
       
  9266 		function isStart(seg) {
       
  9267 			return seg === start || seg === otherStart;
       
  9268 		}
       
  9269 
       
  9270 		function findBestIntersection(inter, strict) {
       
  9271 			if (!inter._next)
       
  9272 				return inter;
       
  9273 			while (inter) {
       
  9274 				var seg = inter._segment,
       
  9275 					nextSeg = seg.getNext(),
       
  9276 					nextInter = nextSeg._intersection;
       
  9277 				if (isStart(nextSeg)
       
  9278 					|| !seg._visited && !nextSeg._visited
       
  9279 					&& (!operator
       
  9280 						|| (!strict || isValid(seg))
       
  9281 						&& (!(strict && nextInter && nextInter.isOverlap())
       
  9282 							&& isValid(nextSeg)
       
  9283 							|| !strict && nextInter
       
  9284 							&& isValid(nextInter._segment))
       
  9285 					))
       
  9286 					return inter;
       
  9287 				inter = inter._next;
       
  9288 			}
       
  9289 			return null;
       
  9290 		}
       
  9291 
       
  9292 		function findStartSegment(inter, next) {
       
  9293 			while (inter) {
       
  9294 				var seg = inter._segment;
       
  9295 				if (isStart(seg))
       
  9296 					return seg;
       
  9297 				inter = inter[next ? '_next' : '_prev'];
       
  9298 			}
       
  9299 		}
       
  9300 
       
  9301 		for (var i = 0, l = segments.length; i < l; i++) {
       
  9302 			var seg = segments[i],
       
  9303 				path = null,
       
  9304 				finished = false;
       
  9305 			if (!isValid(seg, true))
  8852 				continue;
  9306 				continue;
  8853 			var path = new Path(Item.NO_INSERT),
  9307 			start = otherStart = null;
  8854 				inter = seg._intersection,
  9308 			while (!finished) {
  8855 				startInterSeg = inter && inter._segment,
  9309 				var inter = seg._intersection,
  8856 				added = false,
  9310 					handleIn = path && seg._handleIn;
  8857 				dir = 1;
  9311 				inter = inter && (findBestIntersection(inter, true)
  8858 			do {
  9312 						|| findBestIntersection(inter, false)) || inter;
  8859 				var handleIn = dir > 0 ? seg._handleIn : seg._handleOut,
  9313 				var other = inter && inter._segment;
  8860 					handleOut = dir > 0 ? seg._handleOut : seg._handleIn,
  9314 				if (other && isValid(other))
  8861 					interSeg;
  9315 					seg = other;
  8862 				if (added && (!operator(seg._winding) || selfOp)
  9316 				if (seg._visited) {
  8863 						&& (inter = seg._intersection)
  9317 					finished = isStart(seg);
  8864 						&& (interSeg = inter._segment)
  9318 					if (!finished && inter) {
  8865 						&& interSeg !== startSeg) {
  9319 						var found = findStartSegment(inter, true)
  8866 					if (selfOp) {
  9320 							|| findStartSegment(inter, false);
  8867 						seg._visited = interSeg._visited;
  9321 						if (found) {
  8868 						seg = interSeg;
  9322 							seg = found;
  8869 						dir = 1;
  9323 							finished = true;
  8870 					} else {
       
  8871 						var c1 = seg.getCurve();
       
  8872 						if (dir > 0)
       
  8873 							c1 = c1.getPrevious();
       
  8874 						var t1 = c1.getTangentAt(dir < 1 ? tMin : tMax, true),
       
  8875 							c4 = interSeg.getCurve(),
       
  8876 							c3 = c4.getPrevious(),
       
  8877 							t3 = c3.getTangentAt(tMax, true),
       
  8878 							t4 = c4.getTangentAt(tMin, true),
       
  8879 							w3 = t1.cross(t3),
       
  8880 							w4 = t1.cross(t4);
       
  8881 						if (w3 * w4 !== 0) {
       
  8882 							var curve = w3 < w4 ? c3 : c4,
       
  8883 								nextCurve = operator(curve._segment1._winding)
       
  8884 									? curve
       
  8885 									: w3 < w4 ? c4 : c3,
       
  8886 								nextSeg = nextCurve._segment1;
       
  8887 							dir = nextCurve === c3 ? -1 : 1;
       
  8888 							if (nextSeg._visited && seg._path !== nextSeg._path
       
  8889 										|| !operator(nextSeg._winding)) {
       
  8890 								dir = 1;
       
  8891 							} else {
       
  8892 								seg._visited = interSeg._visited;
       
  8893 								seg = interSeg;
       
  8894 								if (nextSeg._visited)
       
  8895 									dir = 1;
       
  8896 							}
       
  8897 						} else {
       
  8898 							dir = 1;
       
  8899 						}
  9324 						}
  8900 					}
  9325 					}
  8901 					handleOut = dir > 0 ? seg._handleOut : seg._handleIn;
  9326 					break;
  8902 				}
  9327 				}
  8903 				path.add(new Segment(seg._point, added && handleIn, handleOut));
  9328 				if (!path) {
  8904 				added = true;
  9329 					path = new Path(Item.NO_INSERT);
       
  9330 					start = seg;
       
  9331 					otherStart = other;
       
  9332 				}
       
  9333 				path.add(new Segment(seg._point, handleIn, seg._handleOut));
  8905 				seg._visited = true;
  9334 				seg._visited = true;
  8906 				seg = dir > 0 ? seg.getNext() : seg. getPrevious();
  9335 				seg = seg.getNext();
  8907 			} while (seg && !seg._visited
  9336 				finished = isStart(seg);
  8908 					&& seg !== startSeg && seg !== startInterSeg
  9337 			}
  8909 					&& (seg._intersection || operator(seg._winding)));
  9338 			if (finished) {
  8910 			if (seg && (seg === startSeg || seg === startInterSeg)) {
  9339 				path.firstSegment.setHandleIn(seg._handleIn);
  8911 				path.firstSegment.setHandleIn((seg === startInterSeg
       
  8912 						? startInterSeg : seg)._handleIn);
       
  8913 				path.setClosed(true);
  9340 				path.setClosed(true);
  8914 			} else {
  9341 			} else if (path) {
  8915 				path.lastSegment._handleOut.set(0, 0);
  9342 				console.error('Boolean operation resulted in open path',
  8916 			}
  9343 						'segments =', path._segments.length,
  8917 			if (path._segments.length >
  9344 						'length =', path.getLength());
  8918 					(path._closed ? path.isLinear() ? 2 : 0 : 1))
  9345 				path = null;
       
  9346 			}
       
  9347 			if (path && (path._segments.length > 8
       
  9348 					|| !Numerical.isZero(path.getArea()))) {
  8919 				paths.push(path);
  9349 				paths.push(path);
       
  9350 				path = null;
       
  9351 			}
  8920 		}
  9352 		}
  8921 		return paths;
  9353 		return paths;
  8922 	}
  9354 	}
  8923 
  9355 
  8924 	return {
  9356 	return {
  8942 		exclude: function(path) {
  9374 		exclude: function(path) {
  8943 			return computeBoolean(this, path, 'exclude');
  9375 			return computeBoolean(this, path, 'exclude');
  8944 		},
  9376 		},
  8945 
  9377 
  8946 		divide: function(path) {
  9378 		divide: function(path) {
  8947 			return new Group([this.subtract(path), this.intersect(path)]);
  9379 			return finishBoolean(Group,
       
  9380 					[this.subtract(path), this.intersect(path)],
       
  9381 					this, path, true);
       
  9382 		},
       
  9383 
       
  9384 		resolveCrossings: function() {
       
  9385 			var crossings = this.getCrossings();
       
  9386 			if (!crossings.length)
       
  9387 				return this;
       
  9388 			divideLocations(CurveLocation.expand(crossings));
       
  9389 			var paths = this._children || [this],
       
  9390 				segments = [];
       
  9391 			for (var i = 0, l = paths.length; i < l; i++) {
       
  9392 				segments.push.apply(segments, paths[i]._segments);
       
  9393 			}
       
  9394 			return finishBoolean(CompoundPath, tracePaths(segments),
       
  9395 					this, null, false);
  8948 		}
  9396 		}
  8949 	};
  9397 	};
  8950 });
  9398 });
  8951 
  9399 
  8952 Path.inject({
  9400 Path.inject({
  8978 				return;
  9426 				return;
  8979 			var y0 = v[1],
  9427 			var y0 = v[1],
  8980 				y1 = v[3],
  9428 				y1 = v[3],
  8981 				y2 = v[5],
  9429 				y2 = v[5],
  8982 				y3 = v[7];
  9430 				y3 = v[7];
  8983 			if (Curve.isLinear(v)) {
  9431 			if (Curve.isStraight(v)) {
  8984 				insertCurve(v);
  9432 				insertCurve(v);
  8985 			} else {
  9433 			} else {
  8986 				var a = 3 * (y1 - y2) - y0 + y3,
  9434 				var a = 3 * (y1 - y2) - y0 + y3,
  8987 					b = 2 * (y0 + y2) - 4 * y1,
  9435 					b = 2 * (y0 + y2) - 4 * y1,
  8988 					c = y1 - y0,
  9436 					c = y1 - y0,
  8989 					tolerance = 0.000001,
  9437 					tMin = 4e-7,
  8990 					roots = [];
  9438 					tMax = 1 - tMin,
  8991 				var count = Numerical.solveQuadratic(a, b, c, roots, tolerance,
  9439 					roots = [],
  8992 						1 - tolerance);
  9440 					n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
  8993 				if (count === 0) {
  9441 				if (n === 0) {
  8994 					insertCurve(v);
  9442 					insertCurve(v);
  8995 				} else {
  9443 				} else {
  8996 					roots.sort();
  9444 					roots.sort();
  8997 					var t = roots[0],
  9445 					var t = roots[0],
  8998 						parts = Curve.subdivide(v, t);
  9446 						parts = Curve.subdivide(v, t);
  8999 					insertCurve(parts[0]);
  9447 					insertCurve(parts[0]);
  9000 					if (count > 1) {
  9448 					if (n > 1) {
  9001 						t = (roots[1] - t) / (1 - t);
  9449 						t = (roots[1] - t) / (1 - t);
  9002 						parts = Curve.subdivide(parts[1], t);
  9450 						parts = Curve.subdivide(parts[1], t);
  9003 						insertCurve(parts[0]);
  9451 						insertCurve(parts[0]);
  9004 					}
  9452 					}
  9005 					insertCurve(parts[1]);
  9453 					insertCurve(parts[1]);
  9110 		}
  9558 		}
  9111 
  9559 
  9112 		function computeParts(curve, index, minT, maxT) {
  9560 		function computeParts(curve, index, minT, maxT) {
  9113 			if ((maxT - minT) > minDifference
  9561 			if ((maxT - minT) > minDifference
  9114 					&& !Curve.isFlatEnough(curve, tolerance || 0.25)) {
  9562 					&& !Curve.isFlatEnough(curve, tolerance || 0.25)) {
  9115 				var split = Curve.subdivide(curve),
  9563 				var split = Curve.subdivide(curve, 0.5),
  9116 					halfT = (minT + maxT) / 2;
  9564 					halfT = (minT + maxT) / 2;
  9117 				computeParts(split[0], index, minT, halfT);
  9565 				computeParts(split[0], index, minT, halfT);
  9118 				computeParts(split[1], index, halfT, maxT);
  9566 				computeParts(split[1], index, halfT, maxT);
  9119 			} else {
  9567 			} else {
  9120 				var x = curve[6] - curve[0],
  9568 				var x = curve[6] - curve[0],
  9121 					y = curve[7] - curve[1],
  9569 					y = curve[7] - curve[1],
  9122 					dist = Math.sqrt(x * x + y * y);
  9570 					dist = Math.sqrt(x * x + y * y);
  9123 				if (dist > 0.000001) {
  9571 				if (dist > 1e-6) {
  9124 					length += dist;
  9572 					length += dist;
  9125 					parts.push({
  9573 					parts.push({
  9126 						offset: length,
  9574 						offset: length,
  9127 						value: maxT,
  9575 						value: maxT,
  9128 						index: index
  9576 						index: index
  9364 		var pt = this.evaluate(3, curve, u),
  9812 		var pt = this.evaluate(3, curve, u),
  9365 			pt1 = this.evaluate(2, curve1, u),
  9813 			pt1 = this.evaluate(2, curve1, u),
  9366 			pt2 = this.evaluate(1, curve2, u),
  9814 			pt2 = this.evaluate(1, curve2, u),
  9367 			diff = pt.subtract(point),
  9815 			diff = pt.subtract(point),
  9368 			df = pt1.dot(pt1) + diff.dot(pt2);
  9816 			df = pt1.dot(pt1) + diff.dot(pt2);
  9369 		if (Math.abs(df) < 0.000001)
  9817 		if (Math.abs(df) < 1e-6)
  9370 			return u;
  9818 			return u;
  9371 		return u - diff.dot(pt1) / df;
  9819 		return u - diff.dot(pt1) / df;
  9372 	},
  9820 	},
  9373 
  9821 
  9374 	evaluate: function(degree, curve, t) {
  9822 	evaluate: function(degree, curve, t) {
  9799 									|| 'radial' in arg
 10247 									|| 'radial' in arg
  9800 								? 'gradient'
 10248 								? 'gradient'
  9801 								: 'gray' in arg
 10249 								: 'gray' in arg
  9802 									? 'gray'
 10250 									? 'gray'
  9803 									: 'rgb';
 10251 									: 'rgb';
  9804 						var properties = types[type];
 10252 						var properties = types[type],
  9805 							parsers = componentParsers[type];
 10253 							parsers = componentParsers[type];
  9806 						this._components = components = [];
 10254 						this._components = components = [];
  9807 						for (var i = 0, l = properties.length; i < l; i++) {
 10255 						for (var i = 0, l = properties.length; i < l; i++) {
  9808 							var value = arg[properties[i]];
 10256 							var value = arg[properties[i]];
  9809 							if (value == null && i === 0 && type === 'gradient'
 10257 							if (value == null && i === 0 && type === 'gradient'
 10001 				var random = Math.random;
 10449 				var random = Math.random;
 10002 				return new Color(random(), random(), random());
 10450 				return new Color(random(), random(), random());
 10003 			}
 10451 			}
 10004 		}
 10452 		}
 10005 	});
 10453 	});
 10006 }, new function() {
 10454 },
       
 10455 new function() {
 10007 	var operators = {
 10456 	var operators = {
 10008 		add: function(a, b) {
 10457 		add: function(a, b) {
 10009 			return a + b;
 10458 			return a + b;
 10010 		},
 10459 		},
 10011 
 10460 
 10036 							: null);
 10485 							: null);
 10037 		};
 10486 		};
 10038 	}, {
 10487 	}, {
 10039 	});
 10488 	});
 10040 });
 10489 });
 10041 
       
 10042 Base.each(Color._types, function(properties, type) {
       
 10043 	var ctor = this[Base.capitalize(type) + 'Color'] = function(arg) {
       
 10044 			var argType = arg != null && typeof arg,
       
 10045 				components = argType === 'object' && arg.length != null
       
 10046 					? arg
       
 10047 					: argType === 'string'
       
 10048 						? null
       
 10049 						: arguments;
       
 10050 			return components
       
 10051 					? new Color(type, components)
       
 10052 					: new Color(arg);
       
 10053 		};
       
 10054 	if (type.length == 3) {
       
 10055 		var acronym = type.toUpperCase();
       
 10056 		Color[acronym] = this[acronym + 'Color'] = ctor;
       
 10057 	}
       
 10058 }, Base.exports);
       
 10059 
 10490 
 10060 var Gradient = Base.extend({
 10491 var Gradient = Base.extend({
 10061 	_class: 'Gradient',
 10492 	_class: 'Gradient',
 10062 
 10493 
 10063 	initialize: function Gradient(stops, radial) {
 10494 	initialize: function Gradient(stops, radial) {
 10679 		this._animate = false;
 11110 		this._animate = false;
 10680 		this._frameItems = {};
 11111 		this._frameItems = {};
 10681 		return true;
 11112 		return true;
 10682 	},
 11113 	},
 10683 
 11114 
 10684 	_events: {
 11115 	_events: Base.each(['onResize', 'onMouseDown', 'onMouseUp', 'onMouseMove'],
 10685 		onFrame: {
 11116 		function(name) {
 10686 			install: function() {
 11117 			this[name] = {
 10687 				this.play();
 11118 				install: function(type) {
 10688 			},
 11119 					this._installEvent(type);
 10689 
 11120 				},
 10690 			uninstall: function() {
 11121 
 10691 				this.pause();
 11122 				uninstall: function(type) {
 10692 			}
 11123 					this._uninstallEvent(type);
 10693 		},
 11124 				}
 10694 
 11125 			};
 10695 		onResize: {}
 11126 		}, {
 10696 	},
 11127 			onFrame: {
       
 11128 				install: function() {
       
 11129 					this.play();
       
 11130 				},
       
 11131 
       
 11132 				uninstall: function() {
       
 11133 					this.pause();
       
 11134 				}
       
 11135 			}
       
 11136 		}
       
 11137 	),
 10697 
 11138 
 10698 	_animate: false,
 11139 	_animate: false,
 10699 	_time: 0,
 11140 	_time: 0,
 10700 	_count: 0,
 11141 	_count: 0,
 10701 
 11142 
 10886 			if (typeof element === 'string')
 11327 			if (typeof element === 'string')
 10887 				element = document.getElementById(element);
 11328 				element = document.getElementById(element);
 10888 			return new CanvasView(project, element);
 11329 			return new CanvasView(project, element);
 10889 		}
 11330 		}
 10890 	}
 11331 	}
 10891 }, new function() {
 11332 },
       
 11333 new function() {
 10892 	var tool,
 11334 	var tool,
 10893 		prevFocus,
 11335 		prevFocus,
 10894 		tempFocus,
 11336 		tempFocus,
 10895 		dragging = false;
 11337 		dragging = false;
 10896 
 11338 
 11009 
 11451 
 11010 	DomEvent.add(window, {
 11452 	DomEvent.add(window, {
 11011 		load: updateFocus
 11453 		load: updateFocus
 11012 	});
 11454 	});
 11013 
 11455 
       
 11456 	var mouseFlags = {
       
 11457 		mousedown: {
       
 11458 			mousedown: 1,
       
 11459 			mousedrag: 1,
       
 11460 			click: 1,
       
 11461 			doubleclick: 1
       
 11462 		},
       
 11463 		mouseup: {
       
 11464 			mouseup: 1,
       
 11465 			mousedrag: 1,
       
 11466 			click: 1,
       
 11467 			doubleclick: 1
       
 11468 		},
       
 11469 		mousemove: {
       
 11470 			mousedrag: 1,
       
 11471 			mousemove: 1,
       
 11472 			mouseenter: 1,
       
 11473 			mouseleave: 1
       
 11474 		}
       
 11475 	};
       
 11476 
 11014 	return {
 11477 	return {
 11015 		_viewEvents: viewEvents,
 11478 		_viewEvents: viewEvents,
 11016 
 11479 
 11017 		_handleEvent: function() {},
 11480 		_handleEvent: function() {},
       
 11481 
       
 11482 		_installEvent: function(type) {
       
 11483 			var counters = this._eventCounters;
       
 11484 			if (counters) {
       
 11485 				for (var key in mouseFlags) {
       
 11486 					counters[key] = (counters[key] || 0)
       
 11487 							+ (mouseFlags[key][type] || 0);
       
 11488 				}
       
 11489 			}
       
 11490 		},
       
 11491 
       
 11492 		_uninstallEvent: function(type) {
       
 11493 			var counters = this._eventCounters;
       
 11494 			if (counters) {
       
 11495 				for (var key in mouseFlags)
       
 11496 					counters[key] -= mouseFlags[key][type] || 0;
       
 11497 			}
       
 11498 		},
 11018 
 11499 
 11019 		statics: {
 11500 		statics: {
 11020 			updateFocus: updateFocus
 11501 			updateFocus: updateFocus
 11021 		}
 11502 		}
 11022 	};
 11503 	};
 11103 		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
 11584 		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
 11104 		project.draw(ctx, this._matrix, this._pixelRatio);
 11585 		project.draw(ctx, this._matrix, this._pixelRatio);
 11105 		project._needsUpdate = false;
 11586 		project._needsUpdate = false;
 11106 		return true;
 11587 		return true;
 11107 	}
 11588 	}
 11108 }, new function() {
 11589 },
 11109 
 11590 new function() {
 11110 	var downPoint,
 11591 	var downPoint,
 11111 		lastPoint,
 11592 		lastPoint,
 11112 		overPoint,
 11593 		overPoint,
 11113 		downItem,
 11594 		downItem,
 11114 		lastItem,
 11595 		lastItem,
 11549 		return this._minDistance == this._maxDistance
 12030 		return this._minDistance == this._maxDistance
 11550 			? this._minDistance : null;
 12031 			? this._minDistance : null;
 11551 	},
 12032 	},
 11552 
 12033 
 11553 	setFixedDistance: function(distance) {
 12034 	setFixedDistance: function(distance) {
 11554 		this._minDistance = distance;
 12035 		this._minDistance = this._maxDistance = distance;
 11555 		this._maxDistance = distance;
       
 11556 	},
 12036 	},
 11557 
 12037 
 11558 	_updateEvent: function(type, point, minDistance, maxDistance, start,
 12038 	_updateEvent: function(type, point, minDistance, maxDistance, start,
 11559 			needsChange, matchMaxDistance) {
 12039 			needsChange, matchMaxDistance) {
 11560 		if (!start) {
 12040 		if (!start) {