From c5b4828ace9bf4955a0c1e429370f9ddbea4ea2e Mon Sep 17 00:00:00 2001
From: sapics <gv.nishino@gmail.com>
Date: Thu, 16 Jun 2016 13:46:02 +0900
Subject: [PATCH 01/58] Fix to cover the case when Numerical.solveQuadratic
 return -1 in path._getMonoCurves culculation

---
 src/path/PathItem.Boolean.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js
index 9d034acd..916c9587 100644
--- a/src/path/PathItem.Boolean.js
+++ b/src/path/PathItem.Boolean.js
@@ -979,7 +979,7 @@ Path.inject(/** @lends Path# */{
                     // Keep then range to 0 .. 1 (excluding) in the search for y
                     // extrema.
                     n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
-                if (n === 0) {
+                if (n < 1) {
                     insertCurve(v);
                 } else {
                     roots.sort();

From ff6484ba8caa9f1e8484da1ca9bf9ded2fc99c02 Mon Sep 17 00:00:00 2001
From: sapics <gv.nishino@gmail.com>
Date: Thu, 16 Jun 2016 14:37:07 +0900
Subject: [PATCH 02/58] Fix to cover the case when Numerical.solveQuadratic
 return -1 in Numerical.solveCubic

---
 src/util/Numerical.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index 44050fbb..b81718d8 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -356,7 +356,8 @@ var Numerical = new function() {
             }
             // The cubic has been deflated to a quadratic.
             var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max);
-            if (isFinite(x) && (count === 0 || x !== roots[count - 1])
+            if (isFinite(x) && count >= 0
+                    && (count === 0 || x !== roots[count - 1])
                     && (min == null || x > min - EPSILON && x < max + EPSILON))
                 roots[count++] = min == null ? x : clamp(x, min, max);
             return count;

From c217e963b8fda9a6af257c3cceb4e851e4c065ad Mon Sep 17 00:00:00 2001
From: Jan <development@iconexperience.com>
Date: Thu, 16 Jun 2016 12:46:12 +0200
Subject: [PATCH 03/58] Rough bounds checking for _addBounds()

Performance of `_addBounds()` can be improved significantly by performing a rough bounds checking first. This is a cheap way to check if the curve can extend the current min or max values at all. Only if the check is passed, further Only if the current bounds can be extended by the curve's bounds, further calculation needs to be done.
Also, if the values of a curve are sorted, the extrema are simply the start and end point.
---
 src/path/Curve.js | 84 +++++++++++++++++++++++++++--------------------
 1 file changed, 48 insertions(+), 36 deletions(-)

diff --git a/src/path/Curve.js b/src/path/Curve.js
index ae7286f3..26264e70 100644
--- a/src/path/Curve.js
+++ b/src/path/Curve.js
@@ -785,42 +785,54 @@ statics: /** @lends Curve */{
      */
     _addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
         padding /= 2; // strokePadding is in width, not radius
-        // Code ported and further optimised from:
-        // http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
-        function add(value, padding) {
-            var left = value - padding,
-                right = value + padding;
-            if (left < min[coord])
-                min[coord] = left;
-            if (right > max[coord])
-                max[coord] = right;
-        }
-        // Calculate derivative of our bezier polynomial, divided by 3.
-        // Doing so allows for simpler calculations of a, b, c and leads to the
-        // same quadratic roots.
-        var a = 3 * (v1 - v2) - v0 + v3,
-            b = 2 * (v0 + v2) - 4 * v1,
-            c = v1 - v0,
-            count = Numerical.solveQuadratic(a, b, c, roots),
-            // Add some tolerance for good roots, as t = 0, 1 are added
-            // separately anyhow, and we don't want joins to be added with radii
-            // in getStrokeBounds()
-            tMin = /*#=*/Numerical.CURVETIME_EPSILON,
-            tMax = 1 - tMin;
-        // Only add strokeWidth to bounds for points which lie within 0 < t < 1
-        // The corner cases for cap and join are handled in getStrokeBounds()
-        add(v3, 0);
-        for (var i = 0; i < count; i++) {
-            var t = roots[i],
-                u = 1 - t;
-            // Test for good roots and only add to bounds if good.
-            if (tMin < t && t < tMax)
-                // Calculate bezier polynomial at t.
-                add(u * u * u * v0
-                    + 3 * u * u * t * v1
-                    + 3 * u * t * t * v2
-                    + t * t * t * v3,
-                    padding);
+        var minPad = min[coord] - padding,
+            maxPad = max[coord] + padding;
+        // The curve can only extend the current bounds if at least one value
+        // is outside the min-max range.
+        if (v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad
+                || v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
+            // Code ported and further optimised from:
+            // http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
+            function add(value, padding) {
+                var left = value - padding,
+                    right = value + padding;
+                if (left < min[coord])
+                    min[coord] = left;
+                if (right > max[coord])
+                    max[coord] = right;
+            }
+            if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {
+                // If values are sorted, the curve's extrema are v0 and v3
+                add(v0, padding);
+                add(v3, padding);
+            } else {// Calculate derivative of our bezier polynomial, divided by 3.
+                // Doing so allows for simpler calculations of a, b, c and leads to the
+                // same quadratic roots.
+                var a = 3 * (v1 - v2) - v0 + v3,
+                    b = 2 * (v0 + v2) - 4 * v1,
+                    c = v1 - v0,
+                    count = Numerical.solveQuadratic(a, b, c, roots),
+                // Add some tolerance for good roots, as t = 0, 1 are added
+                // separately anyhow, and we don't want joins to be added with radii
+                // in getStrokeBounds()
+                    tMin = /*#=*/Numerical.CURVETIME_EPSILON,
+                    tMax = 1 - tMin;
+                // Only add strokeWidth to bounds for points which lie within 0 < t < 1
+                // The corner cases for cap and join are handled in getStrokeBounds()
+                add(v3, 0);
+                for (var i = 0; i < count; i++) {
+                    var t = roots[i],
+                        u = 1 - t;
+                    // Test for good roots and only add to bounds if good.
+                    if (tMin < t && t < tMax)
+                    // Calculate bezier polynomial at t.
+                        add(u * u * u * v0
+                            + 3 * u * u * t * v1
+                            + 3 * u * t * t * v2
+                            + t * t * t * v3,
+                            padding);
+                }
+            }
         }
     }
 }}, Base.each(

From 7009fc3ea020ba9745c7594d03346ebfdd61864e Mon Sep 17 00:00:00 2001
From: Jan <development@iconexperience.com>
Date: Thu, 16 Jun 2016 13:13:16 +0200
Subject: [PATCH 04/58] Add check of value range in solveCubic

Performance of `Curve.solveCubic()` can be improved by first checking if the specified value is within the curve's value range. If it is outside the range, the expensive call to `Numerical.solveCubic()` is not necessary.
---
 src/path/Curve.js | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/path/Curve.js b/src/path/Curve.js
index ae7286f3..3a1fd518 100644
--- a/src/path/Curve.js
+++ b/src/path/Curve.js
@@ -628,8 +628,13 @@ statics: /** @lends Curve */{
         var p1 = v[coord],
             c1 = v[coord + 2],
             c2 = v[coord + 4],
-            p2 = v[coord + 6],
-            c = 3 * (c1 - p1),
+            p2 = v[coord + 6];
+        if (p1 < val && p2 < val && c1 < val && c2 < val
+                || p1 > val && p2 > val && c1 > val && c2 > val) {
+            // If val is outside the curve values, no solution is possible.
+            return 0;
+        }
+        var c = 3 * (c1 - p1),
             b = 3 * (c2 - c1) - c,
             a = p2 - p1 - c - b;
         return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);

From 74b22266f7dfd1302adef0754117c055179e33a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Thu, 16 Jun 2016 14:16:48 +0200
Subject: [PATCH 05/58] Clean up code from #1082 & #1083

---
 src/path/Curve.js | 69 +++++++++++++++++++++++++----------------------
 1 file changed, 37 insertions(+), 32 deletions(-)

diff --git a/src/path/Curve.js b/src/path/Curve.js
index 2e42d5e2..16497f56 100644
--- a/src/path/Curve.js
+++ b/src/path/Curve.js
@@ -628,16 +628,17 @@ statics: /** @lends Curve */{
         var p1 = v[coord],
             c1 = v[coord + 2],
             c2 = v[coord + 4],
-            p2 = v[coord + 6];
-        if (p1 < val && p2 < val && c1 < val && c2 < val
-                || p1 > val && p2 > val && c1 > val && c2 > val) {
-            // If val is outside the curve values, no solution is possible.
-            return 0;
+            p2 = v[coord + 6],
+            res = 0;
+        // If val is outside the curve values, no solution is possible.
+        if (  !(p1 < val && p2 < val && c1 < val && c2 < val ||
+                p1 > val && p2 > val && c1 > val && c2 > val)) {
+            var c = 3 * (c1 - p1),
+                b = 3 * (c2 - c1) - c,
+                a = p2 - p1 - c - b;
+            res = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
         }
-        var c = 3 * (c1 - p1),
-            b = 3 * (c2 - c1) - c,
-            a = p2 - p1 - c - b;
-        return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
+        return res;
     },
 
     getTimeOf: function(v, point) {
@@ -789,41 +790,45 @@ statics: /** @lends Curve */{
      * NOTE: padding is only used for Path.getBounds().
      */
     _addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
+        // Code ported and further optimised from:
+        // http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
+        function add(value, padding) {
+            var left = value - padding,
+                right = value + padding;
+            if (left < min[coord])
+                min[coord] = left;
+            if (right > max[coord])
+                max[coord] = right;
+        }
+
         padding /= 2; // strokePadding is in width, not radius
         var minPad = min[coord] - padding,
             maxPad = max[coord] + padding;
-        // The curve can only extend the current bounds if at least one value
-        // is outside the min-max range.
-        if (v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad
-                || v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
-            // Code ported and further optimised from:
-            // http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
-            function add(value, padding) {
-                var left = value - padding,
-                    right = value + padding;
-                if (left < min[coord])
-                    min[coord] = left;
-                if (right > max[coord])
-                    max[coord] = right;
-            }
+        // Perform a rough bounds checking first: The curve can only extend the
+        // current bounds if at least one value is outside the min-max range.
+        if (    v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||
+                v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
             if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {
-                // If values are sorted, the curve's extrema are v0 and v3
+                // If the values of a curve are sorted, the extrema are simply
+                // the start and end point.
                 add(v0, padding);
                 add(v3, padding);
-            } else {// Calculate derivative of our bezier polynomial, divided by 3.
-                // Doing so allows for simpler calculations of a, b, c and leads to the
-                // same quadratic roots.
+            } else {
+                // Calculate derivative of our bezier polynomial, divided by 3.
+                // Doing so allows for simpler calculations of a, b, c and leads
+                // to the same quadratic roots.
                 var a = 3 * (v1 - v2) - v0 + v3,
                     b = 2 * (v0 + v2) - 4 * v1,
                     c = v1 - v0,
                     count = Numerical.solveQuadratic(a, b, c, roots),
-                // Add some tolerance for good roots, as t = 0, 1 are added
-                // separately anyhow, and we don't want joins to be added with radii
-                // in getStrokeBounds()
+                    // Add some tolerance for good roots, as t = 0, 1 are added
+                    // separately anyhow, and we don't want joins to be added
+                    // with radii in getStrokeBounds()
                     tMin = /*#=*/Numerical.CURVETIME_EPSILON,
                     tMax = 1 - tMin;
-                // Only add strokeWidth to bounds for points which lie within 0 < t < 1
-                // The corner cases for cap and join are handled in getStrokeBounds()
+                // Only add strokeWidth to bounds for points which lie within 0
+                // < t < 1 The corner cases for cap and join are handled in
+                // getStrokeBounds()
                 add(v3, 0);
                 for (var i = 0; i < count; i++) {
                     var t = roots[i],

From a03631f620da50f59cacdcb20d2569177f965d30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Fri, 17 Jun 2016 00:42:40 +0200
Subject: [PATCH 06/58] Remove MouseEvent#target hitTest() getter magic again.

Relates to #995
---
 src/event/MouseEvent.js | 18 ++-------------
 src/view/View.js        | 49 +++++++++++------------------------------
 2 files changed, 15 insertions(+), 52 deletions(-)

diff --git a/src/event/MouseEvent.js b/src/event/MouseEvent.js
index 2e047898..667f1b5a 100644
--- a/src/event/MouseEvent.js
+++ b/src/event/MouseEvent.js
@@ -30,7 +30,7 @@ var MouseEvent = Event.extend(/** @lends MouseEvent# */{
         this.type = type;
         this.event = event;
         this.point = point;
-        this._target = target;
+        this.target = target;
         this.delta = delta;
     },
 
@@ -51,20 +51,6 @@ var MouseEvent = Event.extend(/** @lends MouseEvent# */{
      * @type Point
      */
 
-    // DOCS: document MouseEvent#target
-    /**
-     * @name MouseEvent#target
-     * @type Item
-     */
-    getTarget: function() {
-        // #_target may be a hitTest() function, in which case we need to
-        // execute and override it the first time #target is requested.
-        var target = this._target;
-        if (typeof target === 'function')
-            target = this._target = target();
-        return target;
-    },
-
     // DOCS: document MouseEvent#delta
     /**
      * @name MouseEvent#delta
@@ -77,7 +63,7 @@ var MouseEvent = Event.extend(/** @lends MouseEvent# */{
     toString: function() {
         return "{ type: '" + this.type
                 + "', point: " + this.point
-                + ', target: ' + this.getTarget()
+                + ', target: ' + this.target
                 + (this.delta ? ', delta: ' + this.delta : '')
                 + ', modifiers: ' + this.getModifiers()
                 + ' }';
diff --git a/src/view/View.js b/src/view/View.js
index 59c4becd..0cc79fbe 100644
--- a/src/view/View.js
+++ b/src/view/View.js
@@ -1196,8 +1196,7 @@ new function() { // Injection scope for event handling on the browser
     }
 
     // Returns true if event was stopped, false otherwise.
-    function emitMouseEvents(view, hitItem, hitTest, type, event, point,
-            prevPoint) {
+    function emitMouseEvents(view, hitItem, type, event, point, prevPoint) {
         // Before handling events, process removeOn() calls for cleanup.
         // NOTE: As soon as there is one event handler receiving mousedrag
         // events, non of the removeOnMove() items will be removed while the
@@ -1219,9 +1218,7 @@ new function() { // Injection scope for event handling on the browser
                 && emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
                     point, prevPoint, dragItem)
             // Lastly handle the mouse events on the view, if we're still here.
-            // Choose from the potential targets in the right sequence, with the
-            // hitTest() function as the fall-back getter for MouseEvent#target.
-            || emitMouseEvent(view, dragItem || hitItem || hitTest, type, event,
+            || emitMouseEvent(view, dragItem || hitItem || view, type, event,
                     point, prevPoint));
     }
 
@@ -1299,7 +1296,12 @@ new function() { // Injection scope for event handling on the browser
             // Run the hit-test on items first, but only if we're required to do
             // so for this given mouse event, see hitItems, #_countItemEvent():
             var inView = this.getBounds().contains(point),
-                hitItem,
+                hit = inView && view._project.hitTest(point, {
+                    tolerance: 0,
+                    fill: true,
+                    stroke: true
+                });
+                hitItem = hit && hit.item || null,
                 // Keep track if view event should be handled, so we can use it
                 // to decide if tool._handleMouseEvent() shall be called after.
                 handle = false,
@@ -1308,28 +1310,6 @@ new function() { // Injection scope for event handling on the browser
             // mouse event types.
             mouse[type.substr(5)] = true;
 
-            // Provide a hit-test function that makes sure to only perform the
-            // hit-test once, and only when it's actually required. This method
-            // is passed to emitMouseEvents() and as target to emitMouseEvent(),
-            // as the fall-back getter for MouseEvent#target.
-            function hitTest() {
-                //
-                if (hitItem === undefined) {
-                    var hit = inView && view._project.hitTest(point, {
-                        tolerance: 0,
-                        fill: true,
-                        stroke: true
-                    });
-                    hitItem = hit && hit.item || null;
-                }
-                // Return the target with view as the fall-back, as expected by
-                // MouseEvent#target.
-                return hitItem || view;
-            }
-
-            // Execute hitTest right away if we have events relying on hitItem.
-            if (hitItems)
-                hitTest();
             // Handle mouseenter / leave between items and views first.
             if (hitItems && hitItem !== overItem) {
                 if (overItem) {
@@ -1355,9 +1335,8 @@ new function() { // Injection scope for event handling on the browser
             if ((inView || mouse.drag) && !point.equals(lastPoint)) {
                 // Handle mousemove even if this is not actually a mousemove
                 // event but the mouse has moved since the last event.
-                emitMouseEvents(this, hitItem, hitTest,
-                        nativeMove ? type : 'mousemove', event,
-                        point, lastPoint);
+                emitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',
+                        event, point, lastPoint);
                 handle = true;
             }
             wasInView = inView;
@@ -1365,8 +1344,7 @@ new function() { // Injection scope for event handling on the browser
             // We emit mousedown only when in the view, and mouseup regardless,
             // as long as the mousedown event was inside.
             if (mouse.down && inView || mouse.up && downPoint) {
-                emitMouseEvents(this, hitItem, hitTest, type, event,
-                        point, downPoint);
+                emitMouseEvents(this, hitItem, type, event, point, downPoint);
                 if (mouse.down) {
                     // See if we're clicking again on the same item, within the
                     // double-click time. Firefox uses 300ms as the max time
@@ -1383,9 +1361,8 @@ new function() { // Injection scope for event handling on the browser
                     // not the view.
                     if (!prevented && hitItem === downItem) {
                         clickTime = Date.now();
-                        emitMouseEvents(this, hitItem, hitTest,
-                                dblClick ? 'doubleclick' : 'click', event,
-                                point, downPoint);
+                        emitMouseEvents(this, hitItem, dblClick ? 'doubleclick'
+                                : 'click', event, point, downPoint);
                         dblClick = false;
                     }
                     downItem = dragItem = null;

From f97143d37dac18a23a875d5ddf3050682fd7d261 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Fri, 17 Jun 2016 00:50:06 +0200
Subject: [PATCH 07/58] Fix jshint issue introduced by
 a03631f620da50f59cacdcb20d2569177f965d30

---
 src/view/View.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/view/View.js b/src/view/View.js
index 0cc79fbe..b5b991be 100644
--- a/src/view/View.js
+++ b/src/view/View.js
@@ -1300,7 +1300,7 @@ new function() { // Injection scope for event handling on the browser
                     tolerance: 0,
                     fill: true,
                     stroke: true
-                });
+                }),
                 hitItem = hit && hit.item || null,
                 // Keep track if view event should be handled, so we can use it
                 // to decide if tool._handleMouseEvent() shall be called after.

From f133475405bd13d47de48e2afe8fd7f03614cf69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 18 Jun 2016 23:06:17 +0200
Subject: [PATCH 08/58] Implement MouseEvent#currentTarget and document
 MouseEvent#target.

Relates to #995
---
 src/core/Emitter.js     |  8 +++++++-
 src/event/MouseEvent.js | 19 +++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/src/core/Emitter.js b/src/core/Emitter.js
index a83275ba..1b75b965 100644
--- a/src/core/Emitter.js
+++ b/src/core/Emitter.js
@@ -80,10 +80,14 @@ var Emitter = {
         var handlers = this._callbacks && this._callbacks[type];
         if (!handlers)
             return false;
-        var args = [].slice.call(arguments, 1);
+        var args = [].slice.call(arguments, 1),
+            setTarget = event && 'target' in event &&
+                !('currentTarget' in event);
         // Create a clone of the handlers list so changes caused by on / off
         // won't throw us off track here:
         handlers = handlers.slice();
+        if (setTarget)
+            event.currentTarget = this;
         for (var i = 0, l = handlers.length; i < l; i++) {
             if (handlers[i].apply(this, args) === false) {
                 // If the handler returns false, prevent the default behavior
@@ -94,6 +98,8 @@ var Emitter = {
                 break;
            }
         }
+        if (setTarget)
+            delete event.currentTarget;
         return true;
     },
 
diff --git a/src/event/MouseEvent.js b/src/event/MouseEvent.js
index 667f1b5a..0a3ca604 100644
--- a/src/event/MouseEvent.js
+++ b/src/event/MouseEvent.js
@@ -51,6 +51,25 @@ var MouseEvent = Event.extend(/** @lends MouseEvent# */{
      * @type Point
      */
 
+    /**
+     * The item that dispatched the event. It is different from
+     * {@link #currentTarget} when the event handler is called during
+     * the bubbling phase of the event.
+     *
+     * @name MouseEvent#target
+     * @type Item
+     */
+
+    /**
+     * The current target for the event, as the event traverses the scene graph.
+     * It always refers to the element the event handler has been attached to as
+     * opposed to {@link #target} which identifies the element on
+     * which the event occurred.
+     *
+     * @name MouseEvent#currentTarget
+     * @type Item
+     */
+
     // DOCS: document MouseEvent#delta
     /**
      * @name MouseEvent#delta

From cc55991b668f4231de22d2005dbdbdaab2ee99cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 18 Jun 2016 23:14:48 +0200
Subject: [PATCH 09/58] Fix new issue with Emitter unit tests.

---
 src/core/Emitter.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/core/Emitter.js b/src/core/Emitter.js
index 1b75b965..164e41c1 100644
--- a/src/core/Emitter.js
+++ b/src/core/Emitter.js
@@ -81,8 +81,8 @@ var Emitter = {
         if (!handlers)
             return false;
         var args = [].slice.call(arguments, 1),
-            setTarget = event && 'target' in event &&
-                !('currentTarget' in event);
+            setTarget = event && typeof event === 'object' && 'target' in event
+                && !('currentTarget' in event);
         // Create a clone of the handlers list so changes caused by on / off
         // won't throw us off track here:
         handlers = handlers.slice();

From 739788b67e5ccd07078227bed173763d4bf2419c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 19 Jun 2016 10:55:04 +0200
Subject: [PATCH 10/58] Clean up Event#currentTarget handlig.

---
 src/core/Emitter.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/core/Emitter.js b/src/core/Emitter.js
index 164e41c1..69ffbfc9 100644
--- a/src/core/Emitter.js
+++ b/src/core/Emitter.js
@@ -81,8 +81,9 @@ var Emitter = {
         if (!handlers)
             return false;
         var args = [].slice.call(arguments, 1),
-            setTarget = event && typeof event === 'object' && 'target' in event
-                && !('currentTarget' in event);
+            // Set the current target to `this` if the event object defines
+            // #target but not #currentTarget.
+            setTarget = event && event.target && !event.currentTarget;
         // Create a clone of the handlers list so changes caused by on / off
         // won't throw us off track here:
         handlers = handlers.slice();

From ab24f92373245754621bb156e340a79b894853b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 19 Jun 2016 11:02:54 +0200
Subject: [PATCH 11/58] Bring back accidentally removed hit-test optimization
 in event handling.

See comment.
---
 src/view/View.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/view/View.js b/src/view/View.js
index b5b991be..0cb9446b 100644
--- a/src/view/View.js
+++ b/src/view/View.js
@@ -1296,7 +1296,7 @@ new function() { // Injection scope for event handling on the browser
             // Run the hit-test on items first, but only if we're required to do
             // so for this given mouse event, see hitItems, #_countItemEvent():
             var inView = this.getBounds().contains(point),
-                hit = inView && view._project.hitTest(point, {
+                hit = hitItems && inView && view._project.hitTest(point, {
                     tolerance: 0,
                     fill: true,
                     stroke: true

From bb683c9291592144f1a51745341f1294d14cd553 Mon Sep 17 00:00:00 2001
From: sapics <gv.nishino@gmail.com>
Date: Mon, 20 Jun 2016 09:52:09 +0900
Subject: [PATCH 12/58] Remove same value solution in solveCubic

---
 src/util/Numerical.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index b81718d8..42457699 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -356,8 +356,8 @@ var Numerical = new function() {
             }
             // The cubic has been deflated to a quadratic.
             var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max);
-            if (isFinite(x) && count >= 0
-                    && (count === 0 || x !== roots[count - 1])
+            if (isFinite(x) && (count === 0
+                    || count > 0 && x !== roots[0] && x !== roots[1])
                     && (min == null || x > min - EPSILON && x < max + EPSILON))
                 roots[count++] = min == null ? x : clamp(x, min, max);
             return count;

From a9cc938967cff33ac3b04e84175cf326869c5a68 Mon Sep 17 00:00:00 2001
From: sapics <gv.nishino@gmail.com>
Date: Mon, 20 Jun 2016 13:53:39 +0900
Subject: [PATCH 13/58] Fix normalization in solveQuadratic

---
 src/util/Numerical.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index 42457699..4aa5f006 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -238,6 +238,7 @@ var Numerical = new function() {
                         abs(Math.floor(Math.log(gmC) * Math.LOG10E)));
                     a *= mult;
                     b *= mult;
+                    B *= mult;
                     c *= mult;
                     // Recalculate the discriminant
                     D = b * b - a * c;

From 78f65c9fabf38f896f024b200dfdd2dc41c99d08 Mon Sep 17 00:00:00 2001
From: sapics <gv.nishino@gmail.com>
Date: Mon, 20 Jun 2016 15:41:36 +0900
Subject: [PATCH 14/58] Improve solveQuadratic and solveCubic by hkrish c-code

---
 src/util/Numerical.js | 74 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 55 insertions(+), 19 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index 4aa5f006..50aec173 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -67,6 +67,25 @@ var Numerical = new function() {
         return value < min ? min : value > max ? max : value;
     }
 
+    function splitDouble(X) {
+        var bigX = X * 134217729, // X*(2^27 + 1)
+            Y = X - bigX,
+            Xh = Y + bigX; // Don't optimize Y away!
+        return [Xh, X - Xh];
+    }
+
+    function higherPrecisionDiscriminant(a, b, c) {
+        var ad = splitDouble(a),
+            bd = splitDouble(b),
+            cd = splitDouble(c),
+            p = b * b,
+            dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
+            q = a * c,
+            dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
+                    + ad[1] * cd[1];
+        return (p - q) + (dp - dq);
+    }
+
     return /** @lends Numerical */{
         TOLERANCE: 1e-6,
         /**
@@ -202,6 +221,8 @@ var Numerical = new function() {
          *  Kahan W. - "To Solve a Real Cubic Equation"
          *  http://www.cs.berkeley.edu/~wkahan/Math128/Cubic.pdf
          *  Blinn J. - "How to solve a Quadratic Equation"
+         *  Harikrishnan G.
+         *  https://gist.github.com/hkrish/9e0de1f121971ee0fbab281f5c986de9
          *
          * @param {Number} a the quadratic term
          * @param {Number} b the linear term
@@ -220,28 +241,30 @@ var Numerical = new function() {
                 eMax = max + EPSILON,
                 x1, x2 = Infinity,
                 B = b,
-                D;
+                D, E, pi = 3;
             // a, b, c are expected to be the coefficients of the equation:
             // Ax² - 2Bx + C == 0, so we take b = -B/2:
             b /= -2;
             D = b * b - a * c; // Discriminant
+            E = b * b + a * c;
+            if (pi * abs(D) < E) {
+                D = higherPrecisionDiscriminant(a, b, c);
+            }
             // If the discriminant is very small, we can try to pre-condition
             // the coefficients, so that we may get better accuracy
             if (D !== 0 && abs(D) < MACHINE_EPSILON) {
                 // If the geometric mean of the coefficients is small enough
-                var gmC = pow(abs(a * b * c), 1 / 3);
-                if (gmC < 1e-8) {
-                    // We multiply with a factor to normalize the coefficients.
-                    // The factor is just the nearest exponent of 10, big enough
-                    // to raise all the coefficients to nearly [-1, +1] range.
-                    var mult = gmC === 0 ? 0 : pow(10,
-                        abs(Math.floor(Math.log(gmC) * Math.LOG10E)));
-                    a *= mult;
-                    b *= mult;
-                    B *= mult;
-                    c *= mult;
-                    // Recalculate the discriminant
-                    D = b * b - a * c;
+                var sc = (abs(a) + abs(b) + abs(c)) || MACHINE_EPSILON;
+                sc = pow(2, -Math.floor(Math.log(sc) / Math.log(2) + 0.5));
+                a *= sc;
+                b *= sc;
+                c *= sc;
+                // Recalculate the discriminant
+                D = b * b - a * c;
+                E = b * b + a * c;
+                B = - 2.0 * b;
+                if (pi * abs(D) < E) {
+                    D = higherPrecisionDiscriminant(a, b, c);
                 }
             }
             if (abs(a) < EPSILON) {
@@ -284,6 +307,8 @@ var Numerical = new function() {
          * References:
          *  Kahan W. - "To Solve a Real Cubic Equation"
          *   http://www.cs.berkeley.edu/~wkahan/Math128/Cubic.pdf
+         *  Harikrishnan G.
+         *  https://gist.github.com/hkrish/9e0de1f121971ee0fbab281f5c986de9
          *
          * W. Kahan's paper contains inferences on accuracy of cubic
          * zero-finding methods. Also testing methods for robustness.
@@ -301,16 +326,27 @@ var Numerical = new function() {
          * @author Harikrishnan Gopalakrishnan <hari.exeption@gmail.com>
          */
         solveCubic: function(a, b, c, d, roots, min, max) {
-            var count = 0,
-                x, b1, c2;
+            var count = 0, x, b1, c2,
+                s = Math.max(abs(a), abs(b), abs(c), abs(d));
+            // Normalise coefficients a la Jenkins & Traub's RPOLY
+            if ((s < 1e-7 && s > 0) || s > 1e7) {
+                // Scale the coefficients by a multiple of the exponent of
+                // coefficients so that all the bits in the mantissa are
+                // preserved.
+                var p = pow(2, - Math.floor(Math.log(s) / Math.log(2)));
+                a *= p;
+                b *= p;
+                c *= p;
+                d *= p;
+            }
             // If a or d is zero, we only need to solve a quadratic, so we set
             // the coefficients appropriately.
-            if (abs(a) < EPSILON) {
+            if (a === 0) {
                 a = b;
                 b1 = c;
                 c2 = d;
                 x = Infinity;
-            } else if (abs(d) < EPSILON) {
+            } else if (d === 0) {
                 b1 = b;
                 c2 = c;
                 x = 0;
@@ -333,7 +369,7 @@ var Numerical = new function() {
                 s = t < 0 ? -1 : 1;
                 t = -qd / a;
                 // See Kahan's notes on why 1.324718*... works.
-                r = t > 0 ? 1.3247179572 * Math.max(r, sqrt(t)) : r;
+                r = t > 0 ? 1.324717957244746 * Math.max(r, sqrt(t)) : r;
                 x0 = x - s * r;
                 if (x0 !== x) {
                     do {

From 645e2c2af3d0cc4c446c5537aebd9b8031482973 Mon Sep 17 00:00:00 2001
From: sapics <gv.nishino@gmail.com>
Date: Mon, 20 Jun 2016 17:27:08 +0900
Subject: [PATCH 15/58] Revert EPSILON error in solveCubic

---
 src/util/Numerical.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index 50aec173..bb3c4df0 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -341,12 +341,12 @@ var Numerical = new function() {
             }
             // If a or d is zero, we only need to solve a quadratic, so we set
             // the coefficients appropriately.
-            if (a === 0) {
+            if (abs(a) < EPSILON) {
                 a = b;
                 b1 = c;
                 c2 = d;
                 x = Infinity;
-            } else if (d === 0) {
+            } else if (abs(d) < EPSILON) {
                 b1 = b;
                 c2 = c;
                 x = 0;

From 4fd120fab8e664a8d6748d10cb895d4a39a968da Mon Sep 17 00:00:00 2001
From: sapics <gv.nishino@gmail.com>
Date: Tue, 21 Jun 2016 08:47:42 +0900
Subject: [PATCH 16/58] Minor optimization in Numerical.js

---
 src/util/Numerical.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index bb3c4df0..9c339b89 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -255,7 +255,7 @@ var Numerical = new function() {
             if (D !== 0 && abs(D) < MACHINE_EPSILON) {
                 // If the geometric mean of the coefficients is small enough
                 var sc = (abs(a) + abs(b) + abs(c)) || MACHINE_EPSILON;
-                sc = pow(2, -Math.floor(Math.log(sc) / Math.log(2) + 0.5));
+                sc = pow(2, -Math.floor(Math.log(sc) * Math.LOG2E + 0.5));
                 a *= sc;
                 b *= sc;
                 c *= sc;
@@ -333,7 +333,7 @@ var Numerical = new function() {
                 // Scale the coefficients by a multiple of the exponent of
                 // coefficients so that all the bits in the mantissa are
                 // preserved.
-                var p = pow(2, - Math.floor(Math.log(s) / Math.log(2)));
+                var p = pow(2, -Math.floor(Math.log(s) * Math.LOG2E));
                 a *= p;
                 b *= p;
                 c *= p;

From f94b4f969bc52ead50e956cbaf656317291c3424 Mon Sep 17 00:00:00 2001
From: Jan <development@iconexperience.com>
Date: Wed, 22 Jun 2016 13:10:02 +0200
Subject: [PATCH 17/58] Accidential semicolon in var declaration

I think this is a mistake
---
 src/event/Key.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/event/Key.js b/src/event/Key.js
index 9b0d51cf..6b7b0d85 100644
--- a/src/event/Key.js
+++ b/src/event/Key.js
@@ -45,7 +45,7 @@ var Key = new function() {
         keyMap = {}, // Map for currently pressed keys
         charMap = {}, // key -> char mappings for pressed keys
         metaFixMap, // Keys that will not receive keyup events due to Mac bug
-        downKey; // The key from the keydown event, if it wasn't handled already
+        downKey, // The key from the keydown event, if it wasn't handled already
 
         // Use new Base() to convert into a Base object, for #toString()
         modifiers = new Base({

From cfa215051d7d686fadb10c746b6bc765db82dc03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 3 Jul 2016 12:17:37 +0200
Subject: [PATCH 18/58] Update to latest gulp-git-streamed and remove publish
 workaround code.

---
 gulp/tasks/publish.js | 4 +---
 package.json          | 2 +-
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/gulp/tasks/publish.js b/gulp/tasks/publish.js
index 8411ce0b..588520e7 100644
--- a/gulp/tasks/publish.js
+++ b/gulp/tasks/publish.js
@@ -37,9 +37,7 @@ gulp.task('publish:release', function() {
         .pipe(git.tag('v' + options.version, message))
         .pipe(git.checkout('master'))
         .pipe(git.merge('develop', { args: '-X theirs' }))
-        .pipe(git.push('origin', 'master' ))
-        .pipe(git.push('origin', 'develop' ))
-        .pipe(git.push(null, null, { args: '--tags' } ))
+        .pipe(git.push('origin', ['master', 'develop'], { args: '--tags' }))
         .pipe(shell('npm publish'))
         .pipe(git.checkout('develop'));
 });
diff --git a/package.json b/package.json
index 21faf4a7..3be0b94c 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
     "gulp-add-src": "^0.2.0",
     "gulp-bump": "^1.0.0",
     "gulp-cached": "^1.1.0",
-    "gulp-git-streamed": "^1.0.0",
+    "gulp-git-streamed": "^1.8.0",
     "gulp-jshint": "^2.0.0",
     "gulp-prepro": "^2.4.0",
     "gulp-qunits": "^2.0.1",

From 45ffc6fb8856155e405667d4995cf709bad135b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 3 Jul 2016 13:30:56 +0200
Subject: [PATCH 19/58] Improve Segment constructor to correctly handle
 undefined values.

Closes #1095
---
 src/path/Segment.js   |  2 +-
 test/tests/Segment.js | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/path/Segment.js b/src/path/Segment.js
index 70b8b923..d1cbb837 100644
--- a/src/path/Segment.js
+++ b/src/path/Segment.js
@@ -130,7 +130,7 @@ var Segment = Base.extend(/** @lends Segment# */{
             } else {
                 point = arg0;
             }
-        } else if (typeof arg0 === 'object') {
+        } else if (arg0 == null || typeof arg0 === 'object') {
             // It doesn't matter if all of these arguments exist.
             // new SegmentPoint() produces creates points with (0, 0) otherwise.
             point = arg0;
diff --git a/test/tests/Segment.js b/test/tests/Segment.js
index 24ce21e9..3a2107af 100644
--- a/test/tests/Segment.js
+++ b/test/tests/Segment.js
@@ -12,6 +12,11 @@
 
 QUnit.module('Segment');
 
+test('new Segment()', function() {
+    var segment = new Segment(null, null, null);
+    equals(segment.toString(), '{ point: { x: 0, y: 0 } }');
+});
+
 test('new Segment(point)', function() {
     var segment = new Segment(new Point(10, 10));
     equals(segment.toString(), '{ point: { x: 10, y: 10 } }');
@@ -22,6 +27,11 @@ test('new Segment(x, y)', function() {
     equals(segment.toString(), '{ point: { x: 10, y: 10 } }');
 });
 
+test('new Segment(undefined)', function() {
+    var segment = new Segment(undefined);
+    equals(segment.toString(), '{ point: { x: 0, y: 0 } }');
+});
+
 test('new Segment(object)', function() {
     var segment = new Segment({ point: { x: 10, y: 10 }, handleIn: { x: 5, y: 5 }, handleOut: { x: 15, y: 15 } });
     equals(segment.toString(), '{ point: { x: 10, y: 10 }, handleIn: { x: 5, y: 5 }, handleOut: { x: 15, y: 15 } }');
@@ -32,6 +42,16 @@ test('new Segment(point, handleIn, handleOut)', function() {
     equals(segment.toString(), '{ point: { x: 10, y: 10 }, handleIn: { x: 5, y: 5 }, handleOut: { x: 15, y: 15 } }');
 });
 
+test('new Segment(null, null, null)', function() {
+    var segment = new Segment(null, null, null);
+    equals(segment.toString(), '{ point: { x: 0, y: 0 } }');
+});
+
+test('new Segment(undefined, null, null)', function() {
+    var segment = new Segment(undefined, null, null);
+    equals(segment.toString(), '{ point: { x: 0, y: 0 } }');
+});
+
 test('new Segment(x, y, inX, inY, outX, outY)', function() {
     var segment = new Segment(10, 10, 5, 5, 15, 15);
     equals(segment.toString(), '{ point: { x: 10, y: 10 }, handleIn: { x: 5, y: 5 }, handleOut: { x: 15, y: 15 } }');

From df8969f1c45c41ad138ea046114fc4b8d500f1d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 3 Jul 2016 13:39:05 +0200
Subject: [PATCH 20/58] Switch to jsdom v9.4.0 with native DOMParser support.

Closes #1093
---
 package.json       |  2 +-
 src/node/window.js | 19 -------------------
 2 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/package.json b/package.json
index 3be0b94c..13c11907 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
     "node": ">=4.0.0 <7.0.0"
   },
   "dependencies": {
-    "jsdom": "^8.3.0",
+    "jsdom": "^9.4.0",
     "source-map-support": "^0.4.0"
   },
   "optionalDependencies": {
diff --git a/src/node/window.js b/src/node/window.js
index 4d66ef84..598526c6 100644
--- a/src/node/window.js
+++ b/src/node/window.js
@@ -52,25 +52,6 @@ XMLSerializer.prototype.serializeToString = function(node) {
     return text;
 };
 
-function DOMParser() {
-}
-
-DOMParser.prototype.parseFromString = function(string, contentType) {
-    // Create a new document, since we're supposed to always return one.
-    var doc = document.implementation.createHTMLDocument(''),
-        body = doc.body,
-        last;
-    // Set the body's HTML, then change the DOM according the specs.
-    body.innerHTML = string;
-    // Remove all top-level children (<html><head/><body/></html>)
-    while (last = doc.lastChild)
-        doc.removeChild(last);
-    // Insert the first child of the body at the top.
-    doc.appendChild(body.firstChild);
-    return doc;
-};
-
 window.XMLSerializer = XMLSerializer;
-window.DOMParser = DOMParser;
 
 module.exports = window;

From cb4ffc7945b039359086e34a6257b7fb502edeb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 3 Jul 2016 14:13:50 +0200
Subject: [PATCH 21/58] Update to latest gulp-qunits.

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 13c11907..3f3b0065 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
     "gulp-git-streamed": "^1.8.0",
     "gulp-jshint": "^2.0.0",
     "gulp-prepro": "^2.4.0",
-    "gulp-qunits": "^2.0.1",
+    "gulp-qunits": "^2.1.0",
     "gulp-rename": "^1.2.2",
     "gulp-shell": "^0.5.2",
     "gulp-symlink": "^2.1.3",

From f04dd1430984f5414f7b20ce2b4275660d0be06f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 3 Jul 2016 14:16:17 +0200
Subject: [PATCH 22/58] Remove jsdom legacy code.

---
 src/node/canvas.js | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/src/node/canvas.js b/src/node/canvas.js
index 94dd232a..c6bc25ef 100644
--- a/src/node/canvas.js
+++ b/src/node/canvas.js
@@ -21,24 +21,17 @@ var Canvas = require('canvas'),
 module.exports = function(window) {
     var HTMLCanvasElement = window.HTMLCanvasElement;
 
-    function getImplementation(obj) {
-        // Try implForWrapper() first, fall back on obj. This appears to be
-        // necessary on v7.2.2, but not anymore once we can switch to 8.0.0
-        var impl = idlUtils.implForWrapper(obj);
-        return impl && impl._canvas ? impl : obj;
-    }
-
     // Add fake HTMLCanvasElement#type property:
     Object.defineProperty(HTMLCanvasElement.prototype, 'type', {
         get: function() {
-            var canvas = getImplementation(this)._canvas;
+            var canvas = idlUtils.implForWrapper(this)._canvas;
             return canvas && canvas.type || 'image';
         },
 
         set: function(type) {
             // Allow replacement of internal node-canvas, so we can switch to a
             // PDF canvas.
-            var impl = getImplementation(this),
+            var impl = idlUtils.implForWrapper(this),
                 size = impl._canvas || impl;
             impl._canvas = new Canvas(size.width, size.height, type);
             impl._context = null;
@@ -49,7 +42,7 @@ module.exports = function(window) {
     ['toBuffer', 'pngStream', 'createPNGStream', 'jpgStream', 'createJPGStream']
         .forEach(function(key) {
             HTMLCanvasElement.prototype[key] = function() {
-                var canvas = getImplementation(this)._canvas;
+                var canvas = idlUtils.implForWrapper(this)._canvas;
                 return canvas[key].apply(canvas, arguments);
             };
         });

From 866dcb50dd1a19fc6a4e33f843bdbd4f5635f699 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Thu, 7 Jul 2016 06:21:20 +0200
Subject: [PATCH 23/58] Some tweaks to potentially support strict mode.

---
 src/core/PaperScript.js | 4 ++--
 src/paper.js            | 2 +-
 src/style/Style.js      | 4 +++-
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js
index bf29a2e2..048fce4f 100644
--- a/src/core/PaperScript.js
+++ b/src/core/PaperScript.js
@@ -14,7 +14,7 @@
  * @name PaperScript
  * @namespace
  */
-Base.exports.PaperScript = (function() {
+Base.exports.PaperScript = function() {
     // Locally turn of exports and define for inlined acorn.
     // Just declaring the local vars is enough, as they will be undefined.
     var exports, define,
@@ -590,4 +590,4 @@ Base.exports.PaperScript = (function() {
     };
 // Pass on `this` as the binding object, so we can reference Acorn both in
 // development and in the built library.
-}).call(this);
+}.call(this);
diff --git a/src/paper.js b/src/paper.js
index 7b44d3a3..7d30d91f 100644
--- a/src/paper.js
+++ b/src/paper.js
@@ -123,4 +123,4 @@ var paper = function(self, undefined) {
 
 /*#*/ include('export.js');
 return paper;
-}(typeof self === 'object' ? self : null);
+}.call(this, typeof self === 'object' ? self : null);
diff --git a/src/style/Style.js b/src/style/Style.js
index 00f97daf..61386a52 100644
--- a/src/style/Style.js
+++ b/src/style/Style.js
@@ -171,7 +171,9 @@ var Style = Base.extend(new function() {
                 var old = this._values[key];
                 if (old !== value) {
                     if (isColor) {
-                        if (old)
+                        // The old value may be a native string or other color
+                        // description that wasn't coerced to a color object yet
+                        if (old && old._owner !== undefined)
                             old._owner = undefined;
                         if (value && value.constructor === Color) {
                             // Clone color if it already has an owner.

From 1914e64e4bfa6e2952d450705e0579007389f65f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Fri, 8 Jul 2016 23:05:50 +0200
Subject: [PATCH 24/58] Fix boolean tests to compare with improved results.

Disovered thanks to @sapics' improved solveCubic() in #1087
---
 test/tests/Path_Boolean.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/test/tests/Path_Boolean.js b/test/tests/Path_Boolean.js
index 739c2095..3beef6c7 100644
--- a/test/tests/Path_Boolean.js
+++ b/test/tests/Path_Boolean.js
@@ -1013,7 +1013,7 @@ test('Isolated edge-cases from @iconexperience\'s boolean-test suite', function(
     ]];
     var results = [
         ['M240,270l4.48298,-20.84932l-14.48298,0.84932l7.67824,-56.20204l82.32176,46.20204z M237.67824,193.79796z', 'M244.48298,249.15068l6.05168,-28.14496l12.77751,27.04076z'],
-        ['M450,230l-87.53067,34.43944l-0.01593,-0.02371c-0.91969,-0.32388 -30.35274,-0.48069 -30.67835,2.89141l-2.76789,-52.67014z', 'M362.46933,264.43944l-0.01593,-0.02371c0.02221,0.00782 0.02779,0.01574 0.01593,0.02371z'],
+        ['M450,230l-87.53067,34.43944l-0.01593,-0.02371l0,0c-0.91969,-0.32388 -30.35274,-0.48069 -30.67835,2.89141l-2.76789,-52.67014z', 'M362.46933,264.43944l-0.01593,-0.02371c0.02221,0.00782 0.02779,0.01574 0.01593,0.02371z'],
         ['M211.76471,391.55301c-1.13066,-11.28456 3.81977,12.25688 -5.47954,24.76763l-28.00902,-21.41225l-26.21252,2.62636l13.04584,-12.69198l-22.93592,-17.53397l30.159,10.50681l46.32376,-45.06725c-9.58101,10.09791 -8.78302,39.92732 -6.89161,58.80464z', 'M178.27615,394.90839l-13.16668,-10.06562l7.22309,-7.02716l39.43215,13.7374z'],
         ['M138.31417,456.06811c1.62465,-1.18877 -18.69614,16.61617 -34.61033,15.37458l22.34488,-66.7556l-23.16516,-97.04078l209.03396,72.10619c-68.45789,0.5466 -139.96009,51.6986 -173.60335,76.31563z', 'M126.04871,404.68708l21.5947,-64.51445l-9.32924,115.89547z'],
         ['M300.04122,200l-0.02301,55.81328l19.98178,24.18672l-19.98771,-9.82138l-0.01229,29.82138l-29.04124,-44.09743l-40.1367,-19.722z', 'M300.01822,255.81328l-0.00592,14.36534l-29.05353,-14.27606l-10.39571,-15.78528l29.74019,3.93662z'],
@@ -1035,9 +1035,9 @@ test('Isolated edge-cases from @iconexperience\'s boolean-test suite', function(
         ['M150,290l30,-30l50,10l-24,16l14,14l-50,10l21.17647,-14.11765z', 'M206,286l14,14l-28.82353,-4.11765z'],
         ['M324.40827,86.1091l0.45123,-0.29442l-16.06828,-25.33943l22.46895,-3.97479l18.72801,12.91832c4.53222,6.94617 -10.24683,11.75354 -25.05014,16.51976l15.98481,25.2078l-22.46194,3.97305l6.36357,-29.14428c-0.13874,0.04467 -0.27748,0.08933 -0.4162,0.134z M324.40827,86.1091l-24.66974,16.09646c-4.37001,-6.69756 10.04945,-11.38915 24.66974,-16.09646z', 'M324.8595,85.81469l0,0l0,0z M324.93803,85.93854c-0.03785,0.01219 -0.07571,0.02438 -0.11356,0.03656l0.03503,-0.16042z'],
         ['M388.92139,223.32159c120.27613,-2.24369 208.69681,19.62691 208.69681,19.62691l0.0116,0.00003l0,0l21.89025,-21.07283c0,0 8.54573,10.72909 8.51542,21.16115c-0.03104,10.68629 -208.75655,121.23392 -208.75655,121.23392z', 'M597.62979,242.94854l-21.33555,20.53884l-8.25852,-20.6248z'],
-        ['M272.11155,196.81853l-22.11155,-66.81853l32.64261,64.05832c-6.17669,-1.04412 -8.29,-0.01335 -8.40866,0.04617l-0.00118,-0.00313c-0.09777,0.03858 -0.90866,0.4932 -2.12123,2.71717z', ''],
+        ['M272.11155,196.81853l-22.11155,-66.81853l32.64261,64.05832c-6.17669,-1.04412 -8.29,-0.01335 -8.40866,0.04617l-0.00118,-0.00313c-0.09777,0.03858 -0.90866,0.4932 -2.12123,2.71717z', 'M274.23395,194.10449l-0.00118,-0.00313c0.01275,-0.00503 0.01337,-0.00299 0.00118,0.00313z'],
         ['M386.40934,270.73027c77.4169,15.77719 129.39044,24.64733 142.22581,18.90659l5.47489,12.24096l0,0l40.60627,23.71608l-21.58416,18.81428z', 'M528.63515,289.63686l5.47489,12.24096l-11.2043,-6.54387c2.3982,-4.10616 5.41393,-5.55599 5.72941,-5.69709z'],
-        ['M525,345l32.31797,18.04379l23.72504,-18.37449l6.0793,21.87157l-87.1223,33.45913z', 'M557.31797,363.04379l-23.71188,18.3643l-6.07498,-21.85933z'],
+        ['M525,345l32.31797,18.04379l23.72504,-18.37449l6.0793,21.87157l-87.1223,33.45913z', 'M557.31797,363.04379l0,0l0,0z M557.31797,363.04379l-23.71188,18.3643l-6.07498,-21.85933z'],
         ['M250,150l-15.25375,32.05024l29.10275,-7.1942z M225.84314,153.10482l-45.84314,36.89518l63.48255,20.45333z', 'M205.60228,189.25463l0,0.2l0.01028,-0.20254z'],
         ['M598.5487,408.11025l-42.28034,59.10612l0,0l-37.73535,-87.53938l36.05709,27.56285l0.78705,28.12706z', 'M556.26835,467.21638l-3.83913,-29.98828l2.94792,-1.86119z'],
         ['M570,290l5.8176,33.58557l-28.17314,-14.439c-14.32289,2.0978 -28.17688,4.12693 -28.17688,4.12693l19.08162,-8.78834l-16.12739,-8.26544l27.9654,2.81326z', 'M538.5492,304.48516l11.83801,-5.45218l9.61279,0.96702l15.8176,23.58557z'],

From 02658c9e743685973b6779d60116adc28008df04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 01:01:19 +0200
Subject: [PATCH 25/58] Clean-up code from PR #1087

Closes #1085
---
 src/util/Numerical.js   | 93 ++++++++++++++++++++++-------------------
 test/tests/Numerical.js | 45 ++++++++++++++++++++
 test/tests/load.js      |  2 +
 3 files changed, 96 insertions(+), 44 deletions(-)
 create mode 100644 test/tests/Numerical.js

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index 9c339b89..d08a93dc 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -60,6 +60,7 @@ var Numerical = new function() {
     var abs = Math.abs,
         sqrt = Math.sqrt,
         pow = Math.pow,
+        // Constants
         EPSILON = 1e-12,
         MACHINE_EPSILON = 1.12e-16;
 
@@ -67,23 +68,37 @@ var Numerical = new function() {
         return value < min ? min : value > max ? max : value;
     }
 
-    function splitDouble(X) {
-        var bigX = X * 134217729, // X*(2^27 + 1)
-            Y = X - bigX,
-            Xh = Y + bigX; // Don't optimize Y away!
-        return [Xh, X - Xh];
+    function getDiscriminant(a, b, c) {
+        // Ported from @hkrish's polysolve.c
+        function split(a) {
+            var x = a * 134217729,
+                y = a - x,
+                hi = y + x, // Don't optimize y away!
+                lo = a - hi;
+            return [hi, lo];
+        }
+
+        var D = b * b - a * c,
+            E = b * b + a * c;
+        if (abs(D) * 3 < E) {
+            var ad = split(a),
+                bd = split(b),
+                cd = split(c),
+                p = b * b,
+                dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
+                q = a * c,
+                dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
+                        + ad[1] * cd[1];
+            D = (p - q) + (dp - dq); // Don’t omit parentheses!
+        }
+        return D;
     }
 
-    function higherPrecisionDiscriminant(a, b, c) {
-        var ad = splitDouble(a),
-            bd = splitDouble(b),
-            cd = splitDouble(c),
-            p = b * b,
-            dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
-            q = a * c,
-            dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
-                    + ad[1] * cd[1];
-        return (p - q) + (dp - dq);
+    function getNormalizationFactor(x) {
+        // Normalization is done by scaling coefficients with a power of 2, so
+        // that all the bits in the mantissa remain unchanged.
+        return pow(2,  -Math.floor(
+                Math.log(x || MACHINE_EPSILON) * Math.LOG2E + 0.5));
     }
 
     return /** @lends Numerical */{
@@ -241,31 +256,21 @@ var Numerical = new function() {
                 eMax = max + EPSILON,
                 x1, x2 = Infinity,
                 B = b,
-                D, E, pi = 3;
+                D, E;
             // a, b, c are expected to be the coefficients of the equation:
             // Ax² - 2Bx + C == 0, so we take b = -B/2:
-            b /= -2;
-            D = b * b - a * c; // Discriminant
-            E = b * b + a * c;
-            if (pi * abs(D) < E) {
-                D = higherPrecisionDiscriminant(a, b, c);
-            }
+            b *= -0.5;
+            D = getDiscriminant(a, b, c);
             // If the discriminant is very small, we can try to pre-condition
             // the coefficients, so that we may get better accuracy
-            if (D !== 0 && abs(D) < MACHINE_EPSILON) {
-                // If the geometric mean of the coefficients is small enough
-                var sc = (abs(a) + abs(b) + abs(c)) || MACHINE_EPSILON;
-                sc = pow(2, -Math.floor(Math.log(sc) * Math.LOG2E + 0.5));
-                a *= sc;
-                b *= sc;
-                c *= sc;
-                // Recalculate the discriminant
-                D = b * b - a * c;
-                E = b * b + a * c;
-                B = - 2.0 * b;
-                if (pi * abs(D) < E) {
-                    D = higherPrecisionDiscriminant(a, b, c);
-                }
+            if (D && abs(D) < MACHINE_EPSILON) {
+                // Normalize coefficients.
+                var f = getNormalizationFactor(abs(a) + abs(b) + abs(c));
+                a *= f;
+                b *= f;
+                c *= f;
+                B *= f;
+                D = getDiscriminant(a, b, c);
             }
             if (abs(a) < EPSILON) {
                 // This could just be a linear equation
@@ -326,18 +331,18 @@ var Numerical = new function() {
          * @author Harikrishnan Gopalakrishnan <hari.exeption@gmail.com>
          */
         solveCubic: function(a, b, c, d, roots, min, max) {
-            var count = 0, x, b1, c2,
+            var x, b1, c2,
                 s = Math.max(abs(a), abs(b), abs(c), abs(d));
-            // Normalise coefficients a la Jenkins & Traub's RPOLY
-            if ((s < 1e-7 && s > 0) || s > 1e7) {
+            // Normalize coefficients à la Jenkins & Traub's RPOLY
+            if (s < 1e-8 || s > 1e8) {
                 // Scale the coefficients by a multiple of the exponent of
                 // coefficients so that all the bits in the mantissa are
                 // preserved.
-                var p = pow(2, -Math.floor(Math.log(s) * Math.LOG2E));
-                a *= p;
-                b *= p;
-                c *= p;
-                d *= p;
+                var f = getNormalizationFactor(s);
+                a *= f;
+                b *= f;
+                c *= f;
+                d *= f;
             }
             // If a or d is zero, we only need to solve a quadratic, so we set
             // the coefficients appropriately.
diff --git a/test/tests/Numerical.js b/test/tests/Numerical.js
new file mode 100644
index 00000000..01a5cb08
--- /dev/null
+++ b/test/tests/Numerical.js
@@ -0,0 +1,45 @@
+/*
+ * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
+ * http://scratchdisk.com/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ */
+
+QUnit.module('Numerical');
+
+test('Numerical.solveQuadratic()', function() {
+    function solve(s) {
+        var roots = [],
+            count = Numerical.solveQuadratic(s, 0, -s, roots);
+        return roots;
+    }
+
+    var expected = [1, -1];
+
+    equals(solve(1), expected,
+            'Numerical.solveQuadratic().');
+    equals(solve(Numerical.EPSILON), expected,
+            'Numerical.solveQuadratic() with an identical set of' +
+            'coefficients at different scale.');
+});
+
+test('Numerical.solveCubic()', function() {
+    function solve(s) {
+        var roots = [],
+            count = Numerical.solveCubic(0.5 * s, -s, -s, -s, roots);
+        return roots;
+    }
+
+    var expected = [2.919639565839418];
+
+    equals(solve(1), expected,
+            'Numerical.solveCubic().');
+    equals(solve(Numerical.EPSILON), expected,
+            'Numerical.solveCubic() with an identical set of' +
+            'coefficients at different scale.');
+});
diff --git a/test/tests/load.js b/test/tests/load.js
index 6514919d..c1f9f6aa 100644
--- a/test/tests/load.js
+++ b/test/tests/load.js
@@ -58,3 +58,5 @@
 
 /*#*/ include('SvgImport.js');
 /*#*/ include('SvgExport.js');
+
+/*#*/ include('Numerical.js');

From 7e3d18f5d4149e0b25c3675050ed9682be9a4499 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 01:10:55 +0200
Subject: [PATCH 26/58] Further cleanups in Numerical.solveQuadratic()

---
 src/util/Numerical.js | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index d08a93dc..aea08537 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -255,31 +255,29 @@ var Numerical = new function() {
                 eMin = min - EPSILON,
                 eMax = max + EPSILON,
                 x1, x2 = Infinity,
-                B = b,
-                D, E;
-            // a, b, c are expected to be the coefficients of the equation:
-            // Ax² - 2Bx + C == 0, so we take b = -B/2:
-            b *= -0.5;
-            D = getDiscriminant(a, b, c);
+                // a, b, c are expected to be the coefficients of the equation:
+                // Ax² - 2Bx + C == 0, so we take B = -b/2:
+                B = b * -0.5,
+                D = getDiscriminant(a, B, c);
             // If the discriminant is very small, we can try to pre-condition
             // the coefficients, so that we may get better accuracy
             if (D && abs(D) < MACHINE_EPSILON) {
                 // Normalize coefficients.
-                var f = getNormalizationFactor(abs(a) + abs(b) + abs(c));
+                var f = getNormalizationFactor(abs(a) + abs(B) + abs(c));
                 a *= f;
                 b *= f;
                 c *= f;
                 B *= f;
-                D = getDiscriminant(a, b, c);
+                D = getDiscriminant(a, B, c);
             }
             if (abs(a) < EPSILON) {
                 // This could just be a linear equation
-                if (abs(B) < EPSILON)
+                if (abs(b) < EPSILON)
                     return abs(c) < EPSILON ? -1 : 0;
-                x1 = -c / B;
+                x1 = -c / b;
             } else if (D >= -MACHINE_EPSILON) { // No real roots if D < 0
                 var Q = D < 0 ? 0 : sqrt(D),
-                    R = b + (b < 0 ? -Q : Q);
+                    R = B + (B < 0 ? -Q : Q);
                 // Try to minimize floating point noise.
                 if (R === 0) {
                     x1 = c / a;

From 2532f205a7c3c7c0d8a6148386fb7952b6cca42c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 12:54:17 +0200
Subject: [PATCH 27/58] Prefer native Math.log2(), but support IE through
 internalized polyfill.

---
 src/util/Numerical.js | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index aea08537..a621b134 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -60,6 +60,10 @@ var Numerical = new function() {
     var abs = Math.abs,
         sqrt = Math.sqrt,
         pow = Math.pow,
+        // Fallback to polyfill:
+        log2 = Math.log2 || function(x) {
+            return Math.log(x) * Math.LOG2E;
+        },
         // Constants
         EPSILON = 1e-12,
         MACHINE_EPSILON = 1.12e-16;
@@ -97,8 +101,7 @@ var Numerical = new function() {
     function getNormalizationFactor(x) {
         // Normalization is done by scaling coefficients with a power of 2, so
         // that all the bits in the mantissa remain unchanged.
-        return pow(2,  -Math.floor(
-                Math.log(x || MACHINE_EPSILON) * Math.LOG2E + 0.5));
+        return pow(2, -Math.round(log2(x || MACHINE_EPSILON)));
     }
 
     return /** @lends Numerical */{

From 9d6aab3802082439f0fe933a22fddf14dfe34173 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 13:28:50 +0200
Subject: [PATCH 28/58] Streamline handling of getNormalizationFactor() to
 share more code.

Based on comments by @hkrish in https://github.com/paperjs/paper.js/pull/1087#issuecomment-231529361
---
 src/util/Numerical.js | 103 ++++++++++++++++++++++--------------------
 1 file changed, 53 insertions(+), 50 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index a621b134..7d3d0a5d 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -74,11 +74,11 @@ var Numerical = new function() {
 
     function getDiscriminant(a, b, c) {
         // Ported from @hkrish's polysolve.c
-        function split(a) {
-            var x = a * 134217729,
-                y = a - x,
+        function split(v) {
+            var x = v * 134217729,
+                y = v - x,
                 hi = y + x, // Don't optimize y away!
-                lo = a - hi;
+                lo = v - hi;
             return [hi, lo];
         }
 
@@ -98,10 +98,14 @@ var Numerical = new function() {
         return D;
     }
 
-    function getNormalizationFactor(x) {
+    function getNormalizationFactor() {
+        var max = Math.max.apply(Math, arguments);
+        // Normalize coefficients à la Jenkins & Traub's RPOLY.
         // Normalization is done by scaling coefficients with a power of 2, so
         // that all the bits in the mantissa remain unchanged.
-        return pow(2, -Math.round(log2(x || MACHINE_EPSILON)));
+        return max && (max < 1e-8 || max > 1e8)
+                ? pow(2, -Math.round(log2(max)))
+                : 0;
     }
 
     return /** @lends Numerical */{
@@ -254,49 +258,52 @@ var Numerical = new function() {
          * @author Harikrishnan Gopalakrishnan <hari.exeption@gmail.com>
          */
         solveQuadratic: function(a, b, c, roots, min, max) {
-            var count = 0,
-                eMin = min - EPSILON,
-                eMax = max + EPSILON,
-                x1, x2 = Infinity,
-                // a, b, c are expected to be the coefficients of the equation:
-                // Ax² - 2Bx + C == 0, so we take B = -b/2:
-                B = b * -0.5,
-                D = getDiscriminant(a, B, c);
-            // If the discriminant is very small, we can try to pre-condition
-            // the coefficients, so that we may get better accuracy
-            if (D && abs(D) < MACHINE_EPSILON) {
-                // Normalize coefficients.
-                var f = getNormalizationFactor(abs(a) + abs(B) + abs(c));
-                a *= f;
-                b *= f;
-                c *= f;
-                B *= f;
-                D = getDiscriminant(a, B, c);
-            }
+            var x1, x2 = Infinity;
             if (abs(a) < EPSILON) {
                 // This could just be a linear equation
                 if (abs(b) < EPSILON)
                     return abs(c) < EPSILON ? -1 : 0;
                 x1 = -c / b;
-            } else if (D >= -MACHINE_EPSILON) { // No real roots if D < 0
-                var Q = D < 0 ? 0 : sqrt(D),
-                    R = B + (B < 0 ? -Q : Q);
-                // Try to minimize floating point noise.
-                if (R === 0) {
-                    x1 = c / a;
-                    x2 = -x1;
-                } else {
-                    x1 = R / a;
-                    x2 = c / R;
+            } else {
+                // a, b, c are expected to be the coefficients of the equation:
+                // Ax² - 2Bx + C == 0, so we take b = -b/2:
+                b *= -0.5;
+                var D = getDiscriminant(a, b, c);
+                // If the discriminant is very small, we can try to normalize
+                // the coefficients, so that we may get better accuracy.
+                if (D && abs(D) < MACHINE_EPSILON) {
+                    var f = getNormalizationFactor(abs(a), abs(b), abs(c));
+                    if (f) {
+                        a *= f;
+                        b *= f;
+                        c *= f;
+                        D = getDiscriminant(a, b, c);
+                    }
+                }
+                if (D >= -MACHINE_EPSILON) { // No real roots if D < 0
+                    var Q = D < 0 ? 0 : sqrt(D),
+                        R = b + (b < 0 ? -Q : Q);
+                    // Try to minimize floating point noise.
+                    if (R === 0) {
+                        x1 = c / a;
+                        x2 = -x1;
+                    } else {
+                        x1 = R / a;
+                        x2 = c / R;
+                    }
                 }
             }
+            var count = 0,
+                boundless = min == null,
+                minB = min - EPSILON,
+                maxB = max + EPSILON;
             // We need to include EPSILON in the comparisons with min / max,
             // as some solutions are ever so lightly out of bounds.
-            if (isFinite(x1) && (min == null || x1 > eMin && x1 < eMax))
-                roots[count++] = min == null ? x1 : clamp(x1, min, max);
+            if (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))
+                roots[count++] = boundless ? x1 : clamp(x1, min, max);
             if (x2 !== x1
-                    && isFinite(x2) && (min == null || x2 > eMin && x2 < eMax))
-                roots[count++] = min == null ? x2 : clamp(x2, min, max);
+                    && isFinite(x2) && (boundless || x2 > minB && x2 < maxB))
+                roots[count++] = boundless ? x2 : clamp(x2, min, max);
             return count;
         },
 
@@ -332,14 +339,9 @@ var Numerical = new function() {
          * @author Harikrishnan Gopalakrishnan <hari.exeption@gmail.com>
          */
         solveCubic: function(a, b, c, d, roots, min, max) {
-            var x, b1, c2,
-                s = Math.max(abs(a), abs(b), abs(c), abs(d));
-            // Normalize coefficients à la Jenkins & Traub's RPOLY
-            if (s < 1e-8 || s > 1e8) {
-                // Scale the coefficients by a multiple of the exponent of
-                // coefficients so that all the bits in the mantissa are
-                // preserved.
-                var f = getNormalizationFactor(s);
+            var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),
+                x, b1, c2;
+            if (f) {
                 a *= f;
                 b *= f;
                 c *= f;
@@ -398,11 +400,12 @@ var Numerical = new function() {
                 }
             }
             // The cubic has been deflated to a quadratic.
-            var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max);
+            var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),
+                boundless = min == null;
             if (isFinite(x) && (count === 0
                     || count > 0 && x !== roots[0] && x !== roots[1])
-                    && (min == null || x > min - EPSILON && x < max + EPSILON))
-                roots[count++] = min == null ? x : clamp(x, min, max);
+                    && (boundless || x > min - EPSILON && x < max + EPSILON))
+                roots[count++] = boundless ? x : clamp(x, min, max);
             return count;
         }
     };

From da78e837a1f4e4ef5a3e3e34ace3a3c5b3ef4209 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 13:54:02 +0200
Subject: [PATCH 29/58] Simplify Numerical.solveCubic() code by introducing
 evaluate() closure.

---
 src/util/Numerical.js | 59 +++++++++++++++++++++----------------------
 1 file changed, 29 insertions(+), 30 deletions(-)

diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index 7d3d0a5d..69ac0953 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -99,12 +99,14 @@ var Numerical = new function() {
     }
 
     function getNormalizationFactor() {
-        var max = Math.max.apply(Math, arguments);
         // Normalize coefficients à la Jenkins & Traub's RPOLY.
         // Normalization is done by scaling coefficients with a power of 2, so
         // that all the bits in the mantissa remain unchanged.
-        return max && (max < 1e-8 || max > 1e8)
-                ? pow(2, -Math.round(log2(max)))
+        // Use the infinity norm (max(sum(abs(a)…)) to determine the appropriate
+        // scale factor. See @hkrish in #1087#issuecomment-231526156
+        var norm = Math.max.apply(Math, arguments);
+        return norm && (norm < 1e-8 || norm > 1e8)
+                ? pow(2, -Math.round(log2(norm)))
                 : 0;
     }
 
@@ -340,13 +342,24 @@ var Numerical = new function() {
          */
         solveCubic: function(a, b, c, d, roots, min, max) {
             var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),
-                x, b1, c2;
+                x, b1, c2, qd, q;
             if (f) {
                 a *= f;
                 b *= f;
                 c *= f;
                 d *= f;
             }
+
+            function evaluate(x0) {
+                x = x0;
+                // Evaluate q, q', b1 and c2 at x
+                var tmp = a * x;
+                b1 = tmp + b;
+                c2 = b1 * x + c;
+                qd = (tmp + b1) * x + c2;
+                q = c2 * x + d;
+            }
+
             // If a or d is zero, we only need to solve a quadratic, so we set
             // the coefficients appropriately.
             if (abs(a) < EPSILON) {
@@ -359,38 +372,24 @@ var Numerical = new function() {
                 c2 = c;
                 x = 0;
             } else {
-                var ec = 1 + MACHINE_EPSILON, // 1.000...002
-                    x0, q, qd, t, r, s, tmp;
                 // Here onwards we iterate for the leftmost root. Proceed to
                 // deflate the cubic into a quadratic (as a side effect to the
                 // iteration) and solve the quadratic.
-                x = -(b / a) / 3;
-                // Evaluate q, q', b1 and c2 at x
-                tmp = a * x;
-                b1 = tmp + b;
-                c2 = b1 * x + c;
-                qd = (tmp + b1) * x + c2;
-                q = c2 * x + d;
+                evaluate(-(b / a) / 3);
                 // Get a good initial approximation.
-                t = q / a;
-                r = pow(abs(t), 1/3);
-                s = t < 0 ? -1 : 1;
-                t = -qd / a;
-                // See Kahan's notes on why 1.324718*... works.
-                r = t > 0 ? 1.324717957244746 * Math.max(r, sqrt(t)) : r;
-                x0 = x - s * r;
+                var t = q / a,
+                    r = pow(abs(t), 1/3),
+                    s = t < 0 ? -1 : 1,
+                    td = -qd / a,
+                    // See Kahan's notes on why 1.324718*... works.
+                    rd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,
+                    x0 = x - s * rd;
                 if (x0 !== x) {
                     do {
-                        x = x0;
-                        // Evaluate q, q', b1 and c2 at x
-                        tmp = a * x;
-                        b1 = tmp + b;
-                        c2 = b1 * x + c;
-                        qd = (tmp + b1) * x + c2;
-                        q = c2 * x + d;
-                        // Newton's. Divide by ec to avoid x0 crossing over a
-                        // root.
-                        x0 = qd === 0 ? x : x - q / qd / ec;
+                        evaluate(x0);
+                        // Newton's. Divide by 1 + MACHINE_EPSILON (1.000...002)
+                        // to avoid x0 crossing over a root.
+                        x0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);
                     } while (s * x0 > s * x);
                     // Adjust the coefficients for the quadratic.
                     if (abs(a) * x * x > abs(d / x)) {

From e15de7834733e597c8f0cf7a37487fd2e8ddaf9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 14:32:01 +0200
Subject: [PATCH 30/58] Update JSHint and fix some some hinting errors.

---
 .jshintrc            |  9 +++++----
 package.json         |  4 ++--
 src/item/Item.js     |  3 ++-
 src/path/Path.js     | 29 ++++++++++++++++-------------
 src/svg/SvgImport.js |  4 ++--
 src/view/View.js     | 27 ++++++++++++---------------
 6 files changed, 39 insertions(+), 37 deletions(-)

diff --git a/.jshintrc b/.jshintrc
index 5e8108bf..01894348 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -1,16 +1,17 @@
 {
+  "esversion": 5,
   "browser": true,
   "node": true,
   "wsh": true,
   "evil": true,
-  "trailing": false,
-  "smarttabs": false,
-  "sub": true,
   "supernew": true,
   "laxbreak": true,
   "eqeqeq": false,
   "eqnull": true,
   "loopfunc": true,
   "boss": true,
-  "shadow": true
+  "shadow": true,
+  "funcscope": false,
+  "latedef": "nofunc",
+  "freeze": true
 }
diff --git a/package.json b/package.json
index 3f3b0065..2873cab7 100644
--- a/package.json
+++ b/package.json
@@ -56,8 +56,8 @@
     "gulp-util": "^3.0.0",
     "gulp-webserver": "^0.9.1",
     "gulp-whitespace": "^0.1.0",
-    "gulp-zip": "^3.0.2",
-    "jshint": "2.8.x",
+    "gulp-zip": "^3.2.0",
+    "jshint": "^2.9.2",
     "jshint-summary": "^0.4.0",
     "merge-stream": "^1.0.0",
     "prepro": "^2.4.0",
diff --git a/src/item/Item.js b/src/item/Item.js
index 5e526262..8c56ba7c 100644
--- a/src/item/Item.js
+++ b/src/item/Item.js
@@ -1893,6 +1893,7 @@ new function() { // Injection scope for hit-test functions shared with project
                 || options.class && !(this instanceof options.class)),
             callback = options.match,
             that = this,
+            bounds,
             res;
 
         function match(hit) {
@@ -1913,7 +1914,7 @@ new function() { // Injection scope for hit-test functions shared with project
         if (checkSelf && (options.center || options.bounds) && this._parent) {
             // Don't get the transformed bounds, check against transformed
             // points instead
-            var bounds = this.getInternalBounds();
+            bounds = this.getInternalBounds();
             if (options.center) {
                 res = checkBounds('center', 'Center');
             }
diff --git a/src/path/Path.js b/src/path/Path.js
index 517720b8..41666fac 100644
--- a/src/path/Path.js
+++ b/src/path/Path.js
@@ -1285,6 +1285,13 @@ var Path = PathItem.extend(/** @lends Path# */{
 
     // NOTE: Documentation is in PathItem#smooth()
     smooth: function(options) {
+        var that = this,
+            opts = options || {},
+            type = opts.type || 'asymmetric',
+            segments = this._segments,
+            length = segments.length,
+            closed = this._closed;
+
         // Helper method to pick the right from / to indices.
         // Supports numbers and segment objects.
         // For numbers, the `to` index is exclusive, while for segments and
@@ -1313,15 +1320,10 @@ var Path = PathItem.extend(/** @lends Path# */{
                     : index < 0 ? index + length : index, length - 1);
         }
 
-        var that = this,
-            opts = options || {},
-            type = opts.type || 'asymmetric',
-            segments = this._segments,
-            length = segments.length,
-            closed = this._closed,
-            loop = closed && opts.from === undefined && opts.to === undefined,
+        var loop = closed && opts.from === undefined && opts.to === undefined,
             from = getIndex(opts.from, 0),
             to = getIndex(opts.to, length - 1);
+
         if (from > to) {
             if (closed) {
                 from -= length;
@@ -2048,7 +2050,9 @@ new function() { // Scope for drawing
     // performance.
 
     function drawHandles(ctx, segments, matrix, size) {
-        var half = size / 2;
+        var half = size / 2,
+            coords = new Array(6),
+            pX, pY;
 
         function drawHandle(index) {
             var hX = coords[index],
@@ -2064,13 +2068,12 @@ new function() { // Scope for drawing
             }
         }
 
-        var coords = new Array(6);
         for (var i = 0, l = segments.length; i < l; i++) {
-            var segment = segments[i];
+            var segment = segments[i],
+                selection = segment._selection;
             segment._transformCoordinates(matrix, coords);
-            var selection = segment._selection,
-                pX = coords[0],
-                pY = coords[1];
+            pX = coords[0];
+            pY = coords[1];
             if (selection & /*#=*/SegmentSelection.HANDLE_IN)
                 drawHandle(2);
             if (selection & /*#=*/SegmentSelection.HANDLE_OUT)
diff --git a/src/svg/SvgImport.js b/src/svg/SvgImport.js
index 7a8141e5..8a750375 100644
--- a/src/svg/SvgImport.js
+++ b/src/svg/SvgImport.js
@@ -19,7 +19,8 @@ new function() {
     // objects, dealing with baseVal, and item lists.
     // index is option, and if passed, causes a lookup in a list.
 
-    var rootSize;
+    var definitions = {},
+        rootSize;
 
     function getValue(node, name, isString, allowNull, allowPercent) {
         // Interpret value as number. Never return NaN, but 0 instead.
@@ -547,7 +548,6 @@ new function() {
         return item;
     }
 
-    var definitions = {};
     function getDefinition(value) {
         // When url() comes from a style property, '#'' seems to be missing on
         // WebKit. We also get variations of quotes or no quotes, single or
diff --git a/src/view/View.js b/src/view/View.js
index 0cb9446b..278e14bd 100644
--- a/src/view/View.js
+++ b/src/view/View.js
@@ -1152,7 +1152,18 @@ new function() { // Injection scope for event handling on the browser
         fallbacks = {
             doubleclick: 'click',
             mousedrag: 'mousemove'
-        };
+        },
+        // Various variables required by #_handleMouseEvent()
+        wasInView = false,
+        overView,
+        downPoint,
+        lastPoint,
+        downItem,
+        overItem,
+        dragItem,
+        clickItem,
+        clickTime,
+        dblClick;
 
     // Returns true if event was prevented, false otherwise.
     function emitMouseEvent(obj, target, type, event, point, prevPoint,
@@ -1248,20 +1259,6 @@ new function() { // Injection scope for event handling on the browser
         }
     };
 
-    /**
-     * Various variables required by #_handleMouseEvent()
-     */
-    var downPoint,
-        lastPoint,
-        downItem,
-        overItem,
-        dragItem,
-        clickItem,
-        clickTime,
-        dblClick,
-        overView,
-        wasInView = false;
-
     return {
         _viewEvents: viewEvents,
 

From 2667dc159edeb8468b927c80982f46ade8698f92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 15:48:21 +0200
Subject: [PATCH 31/58] Use pre-commit to lint code before commits, and
 pre-push to run tests.

---
 CHANGELOG.md |  2 ++
 package.json | 14 +++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f28bf76a..272139a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -248,6 +248,8 @@ contribute to the code.
   rounding (#1045).
 - Improve reliability of fat-line clipping for curves that are very similar
   (#904).
+- Improve precision of `Numerical.solveQuadratic()` and
+  `Numerical.solveCubic()` for edge-cases (#1085).
 
 ### Removed
 - Canvas attributes "resize" and "data-paper-resize" no longer cause paper to
diff --git a/package.json b/package.json
index 2873cab7..d2a6c67e 100644
--- a/package.json
+++ b/package.json
@@ -15,10 +15,20 @@
   ],
   "main": "dist/paper-full.js",
   "scripts": {
-    "lint": "jshint src",
     "prepublish": "gulp minify",
+    "build": "gulp build",
+    "dist": "gulp dist",
+    "docs": "gulp docs",
+    "load": "gulp load",
+    "jshint": "gulp jshint",
     "test": "gulp test"
   },
+  "pre-commit": [
+    "jshint"
+  ],
+  "pre-push": [
+    "test"
+  ],
   "files": [
     "AUTHORS.md",
     "dist/",
@@ -60,6 +70,8 @@
     "jshint": "^2.9.2",
     "jshint-summary": "^0.4.0",
     "merge-stream": "^1.0.0",
+    "pre-commit": "^1.1.3",
+    "pre-push": "^0.1.1",
     "prepro": "^2.4.0",
     "qunitjs": "^1.20.0",
     "require-dir": "^0.3.0",

From 7936ca6677aec13e3f904810382a35b700b64c17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 16:10:29 +0200
Subject: [PATCH 32/58] Update NPM dependencies.

---
 package.json | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index d2a6c67e..eac18a39 100644
--- a/package.json
+++ b/package.json
@@ -48,11 +48,11 @@
   },
   "devDependencies": {
     "acorn": "~0.5.0",
-    "del": "^2.2.0",
+    "del": "^2.2.1",
     "extend": "^3.0.0",
-    "gulp": "^3.9.0",
+    "gulp": "^3.9.1",
     "gulp-add-src": "^0.2.0",
-    "gulp-bump": "^1.0.0",
+    "gulp-bump": "^2.2.0",
     "gulp-cached": "^1.1.0",
     "gulp-git-streamed": "^1.8.0",
     "gulp-jshint": "^2.0.0",
@@ -60,10 +60,10 @@
     "gulp-qunits": "^2.1.0",
     "gulp-rename": "^1.2.2",
     "gulp-shell": "^0.5.2",
-    "gulp-symlink": "^2.1.3",
-    "gulp-uglify": "^1.5.1",
+    "gulp-symlink": "^2.1.4",
+    "gulp-uglify": "^1.5.4",
     "gulp-uncomment": "^0.3.0",
-    "gulp-util": "^3.0.0",
+    "gulp-util": "^3.0.7",
     "gulp-webserver": "^0.9.1",
     "gulp-whitespace": "^0.1.0",
     "gulp-zip": "^3.2.0",
@@ -73,10 +73,10 @@
     "pre-commit": "^1.1.3",
     "pre-push": "^0.1.1",
     "prepro": "^2.4.0",
-    "qunitjs": "^1.20.0",
+    "qunitjs": "^1.23.0",
     "require-dir": "^0.3.0",
-    "resemblejs": "^2.1.0",
-    "stats.js": "0.0.14-master",
+    "resemblejs": "^2.2.1",
+    "stats.js": "0.16.0",
     "straps": "^1.9.0"
   },
   "browser": {

From 7e20770126f7069d1827e7d0c27bd3b9575da1f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 16:11:18 +0200
Subject: [PATCH 33/58] Gulp: Fix docs task.

Omitted return means streaming wasn't working.
---
 gulp/tasks/docs.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gulp/tasks/docs.js b/gulp/tasks/docs.js
index 13249a5a..0854ac14 100644
--- a/gulp/tasks/docs.js
+++ b/gulp/tasks/docs.js
@@ -22,7 +22,7 @@ var docOptions = {
 };
 
 gulp.task('docs', ['docs:local', 'build:full'], function() {
-    gulp.src('dist/paper-full.js')
+    return gulp.src('dist/paper-full.js')
         .pipe(rename({ basename: 'paper' }))
         .pipe(gulp.dest('dist/docs/assets/js/'));
 });

From cbbc7f0bbcaef450f77489465b013169448b5983 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 16:28:08 +0200
Subject: [PATCH 34/58] Switch to husky for git precommit / prepush handling.

---
 package.json | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/package.json b/package.json
index eac18a39..210231f0 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,8 @@
   "main": "dist/paper-full.js",
   "scripts": {
     "prepublish": "gulp minify",
+    "precommit": "gulp jshint",
+    "prepush": "gulp test",
     "build": "gulp build",
     "dist": "gulp dist",
     "docs": "gulp docs",
@@ -23,12 +25,6 @@
     "jshint": "gulp jshint",
     "test": "gulp test"
   },
-  "pre-commit": [
-    "jshint"
-  ],
-  "pre-push": [
-    "test"
-  ],
   "files": [
     "AUTHORS.md",
     "dist/",
@@ -67,11 +63,10 @@
     "gulp-webserver": "^0.9.1",
     "gulp-whitespace": "^0.1.0",
     "gulp-zip": "^3.2.0",
+    "husky": "^0.11.4",
     "jshint": "^2.9.2",
     "jshint-summary": "^0.4.0",
     "merge-stream": "^1.0.0",
-    "pre-commit": "^1.1.3",
-    "pre-push": "^0.1.1",
     "prepro": "^2.4.0",
     "qunitjs": "^1.23.0",
     "require-dir": "^0.3.0",

From 6aa983f36795ff9454205b99893e7838ab889682 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 16:37:00 +0200
Subject: [PATCH 35/58] Gulp: Use correct depenency sequence for publish task.

---
 gulp/tasks/publish.js | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gulp/tasks/publish.js b/gulp/tasks/publish.js
index 588520e7..d70277a2 100644
--- a/gulp/tasks/publish.js
+++ b/gulp/tasks/publish.js
@@ -17,8 +17,6 @@ var gulp = require('gulp'),
     shell = require('gulp-shell'),
     options = require('../utils/options.js')({ suffix: false });
 
-gulp.task('publish', ['publish:bump', 'publish:release']);
-
 gulp.task('publish:bump', function() {
     return gulp.src([ 'package.json', 'component.json' ])
         .pipe(bump({ version: options.version }))
@@ -27,7 +25,7 @@ gulp.task('publish:bump', function() {
         .pipe(git.add());
 });
 
-gulp.task('publish:release', function() {
+gulp.task('publish', ['publish:bump'], function() {
     if (options.branch !== 'develop') {
         throw new Error('Publishing is only allowed on the develop branch.');
     }

From 0b31b5fdc67ff484dee6f89c525f4f16c066a555 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 16:37:39 +0200
Subject: [PATCH 36/58] Release version 0.10.0

---
 component.json | 2 +-
 package.json   | 2 +-
 src/options.js | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/component.json b/component.json
index 485411c8..02810bfc 100644
--- a/component.json
+++ b/component.json
@@ -1,6 +1,6 @@
 {
   "name": "paper",
-  "version": "0.9.25",
+  "version": "0.10.0",
   "description": "The Swiss Army Knife of Vector Graphics Scripting",
   "license": "MIT",
   "repo": "paperjs/paper.js",
diff --git a/package.json b/package.json
index 210231f0..6535c60a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "paper",
-  "version": "0.9.25",
+  "version": "0.10.0",
   "description": "The Swiss Army Knife of Vector Graphics Scripting",
   "license": "MIT",
   "homepage": "http://paperjs.org",
diff --git a/src/options.js b/src/options.js
index e7d5fcf2..6f09bab8 100644
--- a/src/options.js
+++ b/src/options.js
@@ -17,7 +17,7 @@
 // The paper.js version.
 // NOTE: Adjust value here before calling `gulp publish`, which then updates and
 // publishes the various JSON package files automatically.
-var version = '0.9.25';
+var version = '0.10.0';
 // If this file is loaded in the browser, we're in load.js mode.
 var load = typeof window === 'object';
 

From f6189c7ab19de335f183ec7cf224bf48e8e2d73e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 16:51:58 +0200
Subject: [PATCH 37/58] Remove "Unreleased" now that 0.10.0 is finally out.

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 272139a7..006293d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@ All notable changes to Paper.js shall be documented in this file, following
 common [CHANGELOG](http://keepachangelog.com/) conventions. As of `0.10.0`,
 Paper.js adheres to [Semantic Versioning](http://semver.org/).
 
-## `0.10.0` (Unreleased)
+## `0.10.0`
 
 ### Preamble
 

From e13300440e28e2be77d54fbcc5713ca199e66969 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 17:13:15 +0200
Subject: [PATCH 38/58] Correct a few issues with documentation and NPM
 publishing that slipped through in the v0.10.0 release.

---
 CHANGELOG.md | 8 +++++++-
 gulp/jsdoc   | 2 +-
 package.json | 2 +-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 006293d8..d57ebfa3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,12 @@ All notable changes to Paper.js shall be documented in this file, following
 common [CHANGELOG](http://keepachangelog.com/) conventions. As of `0.10.0`,
 Paper.js adheres to [Semantic Versioning](http://semver.org/).
 
+## `0.10.1` (Unreleased)
+
+### Fixed
+- Correct a few issues with documentation and NPM publishing that slipped
+  through in the `0.10.0` release.
+
 ## `0.10.0`
 
 ### Preamble
@@ -221,7 +227,7 @@ contribute to the code.
   invertible transformations (#558).
 - Scaling shadows now works correctly with browser- and view-zoom (#831).
 - `Path#arcTo()` correctly handles zero sizes.
-- `#importSVG()` handles onLoad and onError callbacks for string inputs that
+- `#importSVG()` handles `onLoad` and `onError` callbacks for string inputs that
   load external resources (#827).
 - `#importJSON()` and `#exportJSON()` now handle non-`Item` objects correctly
   (#392).
diff --git a/gulp/jsdoc b/gulp/jsdoc
index 4a90c050..698991bf 160000
--- a/gulp/jsdoc
+++ b/gulp/jsdoc
@@ -1 +1 @@
-Subproject commit 4a90c0501d3d0a1f5fec2363e9dce623d0758401
+Subproject commit 698991bfba9210c6d94c08bd70ba9f815ea98bdf
diff --git a/package.json b/package.json
index 6535c60a..301f3e9a 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
   ],
   "main": "dist/paper-full.js",
   "scripts": {
-    "prepublish": "gulp minify",
+    "prepublish": "gulp build minify docs",
     "precommit": "gulp jshint",
     "prepush": "gulp test",
     "build": "gulp build",

From 9fefa7dbf02b44509162c89dd9bb15581017d8bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 17:17:22 +0200
Subject: [PATCH 39/58] Release version 0.10.1

---
 component.json | 2 +-
 package.json   | 2 +-
 src/options.js | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/component.json b/component.json
index 02810bfc..c7c4cdf9 100644
--- a/component.json
+++ b/component.json
@@ -1,6 +1,6 @@
 {
   "name": "paper",
-  "version": "0.10.0",
+  "version": "0.10.1",
   "description": "The Swiss Army Knife of Vector Graphics Scripting",
   "license": "MIT",
   "repo": "paperjs/paper.js",
diff --git a/package.json b/package.json
index 301f3e9a..23b356a2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "paper",
-  "version": "0.10.0",
+  "version": "0.10.1",
   "description": "The Swiss Army Knife of Vector Graphics Scripting",
   "license": "MIT",
   "homepage": "http://paperjs.org",
diff --git a/src/options.js b/src/options.js
index 6f09bab8..d0397f12 100644
--- a/src/options.js
+++ b/src/options.js
@@ -17,7 +17,7 @@
 // The paper.js version.
 // NOTE: Adjust value here before calling `gulp publish`, which then updates and
 // publishes the various JSON package files automatically.
-var version = '0.10.0';
+var version = '0.10.1';
 // If this file is loaded in the browser, we're in load.js mode.
 var load = typeof window === 'object';
 

From b29a1e4028ac0c0218e22134b78968127116b156 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 18:02:16 +0200
Subject: [PATCH 40/58] Version 0.10.1 is released, adjust Changelog title.

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d57ebfa3..c2c45b2b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@ All notable changes to Paper.js shall be documented in this file, following
 common [CHANGELOG](http://keepachangelog.com/) conventions. As of `0.10.0`,
 Paper.js adheres to [Semantic Versioning](http://semver.org/).
 
-## `0.10.1` (Unreleased)
+## `0.10.1`
 
 ### Fixed
 - Correct a few issues with documentation and NPM publishing that slipped

From 1b1b9a16066403228f88c1da983fd6af3f5c8021 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 19:48:02 +0200
Subject: [PATCH 41/58] Gulp: Change publish task so that dist folder contains
 built versions on master branch.

As required by Bower...
---
 .gitignore            |  2 +-
 .travis.yml           |  2 +-
 gulp/tasks/dist.js    |  6 ++++--
 gulp/tasks/publish.js | 40 +++++++++++++++++++++++++++++++---------
 package.json          |  3 ++-
 5 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/.gitignore b/.gitignore
index b0a5c349..8dc9c779 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
 /node_modules/
-/dist/
+/dist/*/
diff --git a/.travis.yml b/.travis.yml
index 8ce3097f..cc943b55 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -38,6 +38,6 @@ script:
 - gulp jshint
 - gulp minify
 - gulp test
-- gulp dist
+- gulp zip
 after_script:
 - '[ "${TRAVIS_BRANCH}" = "develop" ] && [ "${TRAVIS_NODE_VERSION}" = "stable" ] && travis/deploy-prebuilt.sh'
diff --git a/gulp/tasks/dist.js b/gulp/tasks/dist.js
index 33f0dc9e..b86ce6b9 100644
--- a/gulp/tasks/dist.js
+++ b/gulp/tasks/dist.js
@@ -15,7 +15,9 @@ var gulp = require('gulp'),
     merge = require('merge-stream'),
     zip = require('gulp-zip');
 
-gulp.task('dist', ['minify', 'docs', 'clean:dist'], function() {
+gulp.task('dist', ['build', 'minify', 'docs']);
+
+gulp.task('zip', ['clean:zip', 'dist'], function() {
     return merge(
             gulp.src([
                 'dist/paper-full*.js',
@@ -31,7 +33,7 @@ gulp.task('dist', ['minify', 'docs', 'clean:dist'], function() {
         .pipe(gulp.dest('dist'));
 });
 
-gulp.task('clean:dist', function() {
+gulp.task('clean:zip', function() {
     return del([
         'dist/paperjs.zip'
     ]);
diff --git a/gulp/tasks/publish.js b/gulp/tasks/publish.js
index d70277a2..b07fe442 100644
--- a/gulp/tasks/publish.js
+++ b/gulp/tasks/publish.js
@@ -11,31 +11,53 @@
  */
 
 var gulp = require('gulp'),
-    addSrc = require('gulp-add-src'),
     bump = require('gulp-bump'),
     git = require('gulp-git-streamed'),
+    run = require('run-sequence'),
     shell = require('gulp-shell'),
     options = require('../utils/options.js')({ suffix: false });
 
+gulp.task('publish', function() {
+    if (options.branch !== 'develop') {
+        throw new Error('Publishing is only allowed on the develop branch.');
+    }
+    return run(
+        'publish:bump',
+        'publish:dist',
+        'publish:commit',
+        'publish:release',
+        'publish:load'
+    );
+});
+
 gulp.task('publish:bump', function() {
     return gulp.src([ 'package.json', 'component.json' ])
         .pipe(bump({ version: options.version }))
-        .pipe(gulp.dest('./'))
-        .pipe(addSrc('src/options.js'))
-        .pipe(git.add());
+        .pipe(gulp.dest('.'));
 });
 
-gulp.task('publish', ['publish:bump'], function() {
-    if (options.branch !== 'develop') {
-        throw new Error('Publishing is only allowed on the develop branch.');
-    }
+gulp.task('publish:dist', ['dist']);
+
+gulp.task('publish:commit', function() {
     var message = 'Release version ' + options.version;
     return gulp.src('.')
+        .pipe(git.add())
         .pipe(git.commit(message))
-        .pipe(git.tag('v' + options.version, message))
+        .pipe(git.tag('v' + options.version, message));
+});
+
+gulp.task('publish:release', function() {
+    return gulp.src('.')
         .pipe(git.checkout('master'))
         .pipe(git.merge('develop', { args: '-X theirs' }))
         .pipe(git.push('origin', ['master', 'develop'], { args: '--tags' }))
         .pipe(shell('npm publish'))
         .pipe(git.checkout('develop'));
 });
+
+gulp.task('publish:load', ['load'], function() {
+    return gulp.src('dist')
+        .pipe(git.add())
+        .pipe(git.commit('Switch back to load.js versions for development.'))
+        .pipe(git.push('origin', 'develop'));
+});
diff --git a/package.json b/package.json
index 23b356a2..cddcc5bc 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
     "prepush": "gulp test",
     "build": "gulp build",
     "dist": "gulp dist",
+    "zip": "gulp zip",
     "docs": "gulp docs",
     "load": "gulp load",
     "jshint": "gulp jshint",
@@ -47,7 +48,6 @@
     "del": "^2.2.1",
     "extend": "^3.0.0",
     "gulp": "^3.9.1",
-    "gulp-add-src": "^0.2.0",
     "gulp-bump": "^2.2.0",
     "gulp-cached": "^1.1.0",
     "gulp-git-streamed": "^1.8.0",
@@ -71,6 +71,7 @@
     "qunitjs": "^1.23.0",
     "require-dir": "^0.3.0",
     "resemblejs": "^2.2.1",
+    "run-sequence": "^1.2.2",
     "stats.js": "0.16.0",
     "straps": "^1.9.0"
   },

From 0311c267f542dd92bbf9f14c7e9ac4ee56aff21f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 20:56:58 +0200
Subject: [PATCH 42/58] Gulp: More work on improved publish task for Bower.

---
 CHANGELOG.md          | 17 +++++++++++------
 bower.json            |  8 ++++----
 gulp/jsdoc            |  2 +-
 gulp/tasks/build.js   |  2 +-
 gulp/tasks/docs.js    |  2 +-
 gulp/tasks/load.js    |  2 +-
 gulp/tasks/publish.js | 11 +++++++----
 gulp/tasks/watch.js   |  1 -
 gulp/utils/options.js | 27 ++++++++++++++-------------
 9 files changed, 40 insertions(+), 32 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2c45b2b..22d3d8d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,9 @@
 # Change Log
-All notable changes to Paper.js shall be documented in this file, following
-common [CHANGELOG](http://keepachangelog.com/) conventions. As of `0.10.0`,
-Paper.js adheres to [Semantic Versioning](http://semver.org/).
+
+## `0.10.2`
+
+### Fixed
+- Get published version to work correctly in Bower again.
 
 ## `0.10.1`
 
@@ -14,9 +16,12 @@ Paper.js adheres to [Semantic Versioning](http://semver.org/).
 ### Preamble
 
 This is a huge release for Paper.js as we aim for a version `1.0.0` release
-later this year. There are many items in the changelog (and many more items not
-in the changelog) so here a high-level overview to frame the long list of
-changes:
+later this year. As of this version, all notable changes are documented in the
+change-log following common [CHANGELOG](http://keepachangelog.com/) conventions.
+Paper.js now also adheres to [Semantic Versioning](http://semver.org/).
+
+There are many items in the changelog (and many more items not in the changelog)
+so here a high-level overview to frame the long list of changes:
 
 - Boolean operations have been improved and overhauled for reliability and
   efficiency. These include the path functions to unite, intersect, subtract,
diff --git a/bower.json b/bower.json
index b0dd0e83..7be82ba4 100644
--- a/bower.json
+++ b/bower.json
@@ -15,13 +15,13 @@
   "main": "dist/paper-full.js",
   "ignore": [
     "build",
-    "components",
-    "dist/paper-node.js",
-    "projects",
+    "gulp",
     "node_modules",
     "package.json",
+    "projects",
     "src",
-    "test"
+    "test",
+    "travis"
   ],
   "keywords": [
     "vector",
diff --git a/gulp/jsdoc b/gulp/jsdoc
index 698991bf..b6f36edb 160000
--- a/gulp/jsdoc
+++ b/gulp/jsdoc
@@ -1 +1 @@
-Subproject commit 698991bfba9210c6d94c08bd70ba9f815ea98bdf
+Subproject commit b6f36edba33690cee908cadcb24515ec5be97b1d
diff --git a/gulp/tasks/build.js b/gulp/tasks/build.js
index b0c4636b..7fb687e5 100644
--- a/gulp/tasks/build.js
+++ b/gulp/tasks/build.js
@@ -17,7 +17,7 @@ var gulp = require('gulp'),
     whitespace = require('gulp-whitespace'),
     del = require('del'),
     extend = require('extend'),
-    options = require('../utils/options.js')({ suffix: true });
+    options = require('../utils/options.js');
 
 // Options to be used in Prepro.js preprocessing through the global __options
 // object, merged in with the options required above.
diff --git a/gulp/tasks/docs.js b/gulp/tasks/docs.js
index 0854ac14..217b7293 100644
--- a/gulp/tasks/docs.js
+++ b/gulp/tasks/docs.js
@@ -14,7 +14,7 @@ var gulp = require('gulp'),
     del = require('del'),
     rename = require('gulp-rename'),
     shell = require('gulp-shell'),
-    options = require('../utils/options.js')({ suffix: true });
+    options = require('../utils/options.js');
 
 var docOptions = {
     local: 'docs', // Generates the offline docs
diff --git a/gulp/tasks/load.js b/gulp/tasks/load.js
index f34fe48b..1d301aab 100644
--- a/gulp/tasks/load.js
+++ b/gulp/tasks/load.js
@@ -21,5 +21,5 @@ gulp.task('load', ['clean:load'], function() {
 });
 
 gulp.task('clean:load', function() {
-    return del([ 'dist/paper-full.js', 'dist/paper-core.js', 'dist/node/**' ]);
+    return del([ 'dist/*.js', 'dist/node/**' ]);
 });
diff --git a/gulp/tasks/publish.js b/gulp/tasks/publish.js
index b07fe442..376e404c 100644
--- a/gulp/tasks/publish.js
+++ b/gulp/tasks/publish.js
@@ -15,14 +15,14 @@ var gulp = require('gulp'),
     git = require('gulp-git-streamed'),
     run = require('run-sequence'),
     shell = require('gulp-shell'),
-    options = require('../utils/options.js')({ suffix: false });
+    options = require('../utils/options.js');
 
 gulp.task('publish', function() {
     if (options.branch !== 'develop') {
         throw new Error('Publishing is only allowed on the develop branch.');
     }
     return run(
-        'publish:bump',
+        'publish:version',
         'publish:dist',
         'publish:commit',
         'publish:release',
@@ -30,7 +30,10 @@ gulp.task('publish', function() {
     );
 });
 
-gulp.task('publish:bump', function() {
+gulp.task('publish:version', function() {
+    // Since we're executing this on the develop branch but we don't wan the
+    // version suffixed, reset the version value again.
+    options.resetVersion();
     return gulp.src([ 'package.json', 'component.json' ])
         .pipe(bump({ version: options.version }))
         .pipe(gulp.dest('.'));
@@ -58,6 +61,6 @@ gulp.task('publish:release', function() {
 gulp.task('publish:load', ['load'], function() {
     return gulp.src('dist')
         .pipe(git.add())
-        .pipe(git.commit('Switch back to load.js versions for development.'))
+        .pipe(git.commit('Switch back to load.js versions on develop branch.'))
         .pipe(git.push('origin', 'develop'));
 });
diff --git a/gulp/tasks/watch.js b/gulp/tasks/watch.js
index ce138803..5864e895 100644
--- a/gulp/tasks/watch.js
+++ b/gulp/tasks/watch.js
@@ -14,7 +14,6 @@ var gulp = require('gulp'),
     path = require('path'),
     gutil = require('gulp-util');
 
-
 gulp.task('watch', function () {
     gulp.watch('src/**/*.js', ['jshint'])
         .on('change', function(event) {
diff --git a/gulp/utils/options.js b/gulp/utils/options.js
index 1b6b9111..7773e863 100644
--- a/gulp/utils/options.js
+++ b/gulp/utils/options.js
@@ -20,19 +20,20 @@ function git(command) {
     return execSync('git ' + command).toString().trim();
 }
 
+options.date = git('log -1 --pretty=format:%ad');
+options.branch = git('rev-parse --abbrev-ref HEAD');
+
 // Get the date of the last commit from this branch for release date:
-var date = git('log -1 --pretty=format:%ad'),
-    branch = git('rev-parse --abbrev-ref HEAD');
+var version = options.version,
+    branch = options.branch;
 
-extend(options, {
-    date: date,
-    branch: branch,
-    // If we're not on the master branch, use the branch name as a suffix:
-    suffix: branch === 'master' ? '' : '-' + branch
-});
+// If we're not on the master branch, use the branch name as a suffix:
+if (branch !== 'master')
+    options.version += '-' + branch;
 
-module.exports = function(opts) {
-    return extend({}, options, opts && opts.suffix && {
-        version: options.version + options.suffix
-    });
-};
+// Allow the removal of the suffix again, as needed by the publish task.
+options.resetVersion = function() {
+    options.version = version;
+}
+
+module.exports = options;

From a02f181c00ae59451a75e8b7345e727da8f8382d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 21:04:37 +0200
Subject: [PATCH 43/58] Release version 0.10.2

---
 component.json         |     2 +-
 dist/paper-core.js     | 14249 ++++++++++++++++++++++++++++++++++++++
 dist/paper-core.min.js |    38 +
 dist/paper-full.js     | 14623 +++++++++++++++++++++++++++++++++++++++
 dist/paper-full.min.js |    39 +
 package.json           |     2 +-
 src/options.js         |     2 +-
 7 files changed, 28952 insertions(+), 3 deletions(-)
 create mode 100644 dist/paper-core.js
 create mode 100644 dist/paper-core.min.js
 create mode 100644 dist/paper-full.js
 create mode 100644 dist/paper-full.min.js

diff --git a/component.json b/component.json
index c7c4cdf9..c48eed0c 100644
--- a/component.json
+++ b/component.json
@@ -1,6 +1,6 @@
 {
   "name": "paper",
-  "version": "0.10.1",
+  "version": "0.10.2",
   "description": "The Swiss Army Knife of Vector Graphics Scripting",
   "license": "MIT",
   "repo": "paperjs/paper.js",
diff --git a/dist/paper-core.js b/dist/paper-core.js
new file mode 100644
index 00000000..f2d5a28f
--- /dev/null
+++ b/dist/paper-core.js
@@ -0,0 +1,14249 @@
+/*!
+ * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
+ * http://scratchdisk.com/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ *
+ * Date: Sat Jul 9 20:56:58 2016 +0200
+ *
+ ***
+ *
+ * Straps.js - Class inheritance library with support for bean-style accessors
+ *
+ * Copyright (c) 2006 - 2016 Juerg Lehni
+ * http://scratchdisk.com/
+ *
+ * Distributed under the MIT license.
+ *
+ ***
+ *
+ * Acorn.js
+ * http://marijnhaverbeke.nl/acorn/
+ *
+ * Acorn is a tiny, fast JavaScript parser written in JavaScript,
+ * created by Marijn Haverbeke and released under an MIT license.
+ *
+ */
+
+var paper = function(self, undefined) {
+
+var window = self ? self.window : require('./node/window'),
+	document = window && window.document;
+
+self = self || window;
+
+var Base = new function() {
+	var hidden = /^(statics|enumerable|beans|preserve)$/,
+
+		forEach = [].forEach || function(iter, bind) {
+			for (var i = 0, l = this.length; i < l; i++)
+				iter.call(bind, this[i], i, this);
+		},
+
+		forIn = function(iter, bind) {
+			for (var i in this)
+				if (this.hasOwnProperty(i))
+					iter.call(bind, this[i], i, this);
+		},
+
+		create = Object.create || function(proto) {
+			return { __proto__: proto };
+		},
+
+		describe = Object.getOwnPropertyDescriptor || function(obj, name) {
+			var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
+			return get
+					? { get: get, set: obj.__lookupSetter__(name),
+						enumerable: true, configurable: true }
+					: obj.hasOwnProperty(name)
+						? { value: obj[name], enumerable: true,
+							configurable: true, writable: true }
+						: null;
+		},
+
+		_define = Object.defineProperty || function(obj, name, desc) {
+			if ((desc.get || desc.set) && obj.__defineGetter__) {
+				if (desc.get)
+					obj.__defineGetter__(name, desc.get);
+				if (desc.set)
+					obj.__defineSetter__(name, desc.set);
+			} else {
+				obj[name] = desc.value;
+			}
+			return obj;
+		},
+
+		define = function(obj, name, desc) {
+			delete obj[name];
+			return _define(obj, name, desc);
+		};
+
+	function inject(dest, src, enumerable, beans, preserve) {
+		var beansNames = {};
+
+		function field(name, val) {
+			val = val || (val = describe(src, name))
+					&& (val.get ? val : val.value);
+			if (typeof val === 'string' && val[0] === '#')
+				val = dest[val.substring(1)] || val;
+			var isFunc = typeof val === 'function',
+				res = val,
+				prev = preserve || isFunc && !val.base
+						? (val && val.get ? name in dest : dest[name])
+						: null,
+				bean;
+			if (!preserve || !prev) {
+				if (isFunc && prev)
+					val.base = prev;
+				if (isFunc && beans !== false
+						&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
+					beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
+				if (!res || isFunc || !res.get || typeof res.get !== 'function'
+						|| !Base.isPlainObject(res))
+					res = { value: res, writable: true };
+				if ((describe(dest, name)
+						|| { configurable: true }).configurable) {
+					res.configurable = true;
+					res.enumerable = enumerable;
+				}
+				define(dest, name, res);
+			}
+		}
+		if (src) {
+			for (var name in src) {
+				if (src.hasOwnProperty(name) && !hidden.test(name))
+					field(name);
+			}
+			for (var name in beansNames) {
+				var part = beansNames[name],
+					set = dest['set' + part],
+					get = dest['get' + part] || set && dest['is' + part];
+				if (get && (beans === true || get.length === 0))
+					field(name, { get: get, set: set });
+			}
+		}
+		return dest;
+	}
+
+	function each(obj, iter, bind) {
+		if (obj)
+			('length' in obj && !obj.getLength
+					&& typeof obj.length === 'number'
+				? forEach
+				: forIn).call(obj, iter, bind = bind || obj);
+		return bind;
+	}
+
+	function set(obj, args, start) {
+		for (var i = start, l = args.length; i < l; i++) {
+			var props = args[i];
+			for (var key in props)
+				if (props.hasOwnProperty(key))
+					obj[key] = props[key];
+		}
+		return obj;
+	}
+
+	return inject(function Base() {
+		set(this, arguments, 0);
+	}, {
+		inject: function(src) {
+			if (src) {
+				var statics = src.statics === true ? src : src.statics,
+					beans = src.beans,
+					preserve = src.preserve;
+				if (statics !== src)
+					inject(this.prototype, src, src.enumerable, beans, preserve);
+				inject(this, statics, true, beans, preserve);
+			}
+			for (var i = 1, l = arguments.length; i < l; i++)
+				this.inject(arguments[i]);
+			return this;
+		},
+
+		extend: function() {
+			var base = this,
+				ctor,
+				proto;
+			for (var i = 0, obj, l = arguments.length;
+					i < l && !(ctor && proto); i++) {
+				obj = arguments[i];
+				ctor = ctor || obj.initialize;
+				proto = proto || obj.prototype;
+			}
+			ctor = ctor || function() {
+				base.apply(this, arguments);
+			};
+			proto = ctor.prototype = proto || create(this.prototype);
+			define(proto, 'constructor',
+					{ value: ctor, writable: true, configurable: true });
+			inject(ctor, this, true);
+			if (arguments.length)
+				this.inject.apply(ctor, arguments);
+			ctor.base = base;
+			return ctor;
+		}
+	}, true).inject({
+		inject: function() {
+			for (var i = 0, l = arguments.length; i < l; i++) {
+				var src = arguments[i];
+				if (src)
+					inject(this, src, src.enumerable, src.beans, src.preserve);
+			}
+			return this;
+		},
+
+		extend: function() {
+			var res = create(this);
+			return res.inject.apply(res, arguments);
+		},
+
+		each: function(iter, bind) {
+			return each(this, iter, bind);
+		},
+
+		set: function() {
+			return set(this, arguments, 0);
+		},
+
+		clone: function() {
+			return new this.constructor(this);
+		},
+
+		statics: {
+			each: each,
+			create: create,
+			define: define,
+			describe: describe,
+
+			set: function(obj) {
+				return set(obj, arguments, 1);
+			},
+
+			clone: function(obj) {
+				return set(new obj.constructor(), arguments, 0);
+			},
+
+			isPlainObject: function(obj) {
+				var ctor = obj != null && obj.constructor;
+				return ctor && (ctor === Object || ctor === Base
+						|| ctor.name === 'Object');
+			},
+
+			pick: function(a, b) {
+				return a !== undefined ? a : b;
+			}
+		}
+	});
+};
+
+if (typeof module !== 'undefined')
+	module.exports = Base;
+
+Base.inject({
+	toString: function() {
+		return this._id != null
+			?  (this._class || 'Object') + (this._name
+				? " '" + this._name + "'"
+				: ' @' + this._id)
+			: '{ ' + Base.each(this, function(value, key) {
+				if (!/^_/.test(key)) {
+					var type = typeof value;
+					this.push(key + ': ' + (type === 'number'
+							? Formatter.instance.number(value)
+							: type === 'string' ? "'" + value + "'" : value));
+				}
+			}, []).join(', ') + ' }';
+	},
+
+	getClassName: function() {
+		return this._class || '';
+	},
+
+	importJSON: function(json) {
+		return Base.importJSON(json, this);
+	},
+
+	exportJSON: function(options) {
+		return Base.exportJSON(this, options);
+	},
+
+	toJSON: function() {
+		return Base.serialize(this);
+	},
+
+	_set: function(props) {
+		if (props && Base.isPlainObject(props))
+			return Base.filter(this, props);
+	},
+
+	statics: {
+
+		exports: {
+			enumerable: true
+		},
+
+		extend: function extend() {
+			var res = extend.base.apply(this, arguments),
+				name = res.prototype._class;
+			if (name && !Base.exports[name])
+				Base.exports[name] = res;
+			return res;
+		},
+
+		equals: function(obj1, obj2) {
+			if (obj1 === obj2)
+				return true;
+			if (obj1 && obj1.equals)
+				return obj1.equals(obj2);
+			if (obj2 && obj2.equals)
+				return obj2.equals(obj1);
+			if (obj1 && obj2
+					&& typeof obj1 === 'object' && typeof obj2 === 'object') {
+				if (Array.isArray(obj1) && Array.isArray(obj2)) {
+					var length = obj1.length;
+					if (length !== obj2.length)
+						return false;
+					while (length--) {
+						if (!Base.equals(obj1[length], obj2[length]))
+							return false;
+					}
+				} else {
+					var keys = Object.keys(obj1),
+						length = keys.length;
+					if (length !== Object.keys(obj2).length)
+						return false;
+					while (length--) {
+						var key = keys[length];
+						if (!(obj2.hasOwnProperty(key)
+								&& Base.equals(obj1[key], obj2[key])))
+							return false;
+					}
+				}
+				return true;
+			}
+			return false;
+		},
+
+		read: function(list, start, options, length) {
+			if (this === Base) {
+				var value = this.peek(list, start);
+				list.__index++;
+				return value;
+			}
+			var proto = this.prototype,
+				readIndex = proto._readIndex,
+				index = start || readIndex && list.__index || 0;
+			if (!length)
+				length = list.length - index;
+			var obj = list[index];
+			if (obj instanceof this
+				|| options && options.readNull && obj == null && length <= 1) {
+				if (readIndex)
+					list.__index = index + 1;
+				return obj && options && options.clone ? obj.clone() : obj;
+			}
+			obj = Base.create(this.prototype);
+			if (readIndex)
+				obj.__read = true;
+			obj = obj.initialize.apply(obj, index > 0 || length < list.length
+				? Array.prototype.slice.call(list, index, index + length)
+				: list) || obj;
+			if (readIndex) {
+				list.__index = index + obj.__read;
+				obj.__read = undefined;
+			}
+			return obj;
+		},
+
+		peek: function(list, start) {
+			return list[list.__index = start || list.__index || 0];
+		},
+
+		remain: function(list) {
+			return list.length - (list.__index || 0);
+		},
+
+		readAll: function(list, start, options) {
+			var res = [],
+				entry;
+			for (var i = start || 0, l = list.length; i < l; i++) {
+				res.push(Array.isArray(entry = list[i])
+						? this.read(entry, 0, options)
+						: this.read(list, i, options, 1));
+			}
+			return res;
+		},
+
+		readNamed: function(list, name, start, options, length) {
+			var value = this.getNamed(list, name),
+				hasObject = value !== undefined;
+			if (hasObject) {
+				var filtered = list._filtered;
+				if (!filtered) {
+					filtered = list._filtered = Base.create(list[0]);
+					filtered._filtering = list[0];
+				}
+				filtered[name] = undefined;
+			}
+			return this.read(hasObject ? [value] : list, start, options, length);
+		},
+
+		getNamed: function(list, name) {
+			var arg = list[0];
+			if (list._hasObject === undefined)
+				list._hasObject = list.length === 1 && Base.isPlainObject(arg);
+			if (list._hasObject)
+				return name ? arg[name] : list._filtered || arg;
+		},
+
+		hasNamed: function(list, name) {
+			return !!this.getNamed(list, name);
+		},
+
+		filter: function(dest, source, exclude) {
+			var keys = Object.keys(source._filtering || source);
+			for (var i = 0, l = keys.length; i < l; i++) {
+				var key = keys[i];
+				if (!(exclude && exclude[key])) {
+					var value = source[key];
+					if (value !== undefined)
+						dest[key] = value;
+				}
+			}
+			return dest;
+		},
+
+		isPlainValue: function(obj, asString) {
+			return this.isPlainObject(obj) || Array.isArray(obj)
+					|| asString && typeof obj === 'string';
+		},
+
+		serialize: function(obj, options, compact, dictionary) {
+			options = options || {};
+
+			var isRoot = !dictionary,
+				res;
+			if (isRoot) {
+				options.formatter = new Formatter(options.precision);
+				dictionary = {
+					length: 0,
+					definitions: {},
+					references: {},
+					add: function(item, create) {
+						var id = '#' + item._id,
+							ref = this.references[id];
+						if (!ref) {
+							this.length++;
+							var res = create.call(item),
+								name = item._class;
+							if (name && res[0] !== name)
+								res.unshift(name);
+							this.definitions[id] = res;
+							ref = this.references[id] = [id];
+						}
+						return ref;
+					}
+				};
+			}
+			if (obj && obj._serialize) {
+				res = obj._serialize(options, dictionary);
+				var name = obj._class;
+				if (name && !obj._compactSerialize && (isRoot || !compact)
+						&& res[0] !== name) {
+					res.unshift(name);
+				}
+			} else if (Array.isArray(obj)) {
+				res = [];
+				for (var i = 0, l = obj.length; i < l; i++)
+					res[i] = Base.serialize(obj[i], options, compact,
+							dictionary);
+			} else if (Base.isPlainObject(obj)) {
+				res = {};
+				var keys = Object.keys(obj);
+				for (var i = 0, l = keys.length; i < l; i++) {
+					var key = keys[i];
+					res[key] = Base.serialize(obj[key], options, compact,
+							dictionary);
+				}
+			} else if (typeof obj === 'number') {
+				res = options.formatter.number(obj, options.precision);
+			} else {
+				res = obj;
+			}
+			return isRoot && dictionary.length > 0
+					? [['dictionary', dictionary.definitions], res]
+					: res;
+		},
+
+		deserialize: function(json, create, _data, _setDictionary, _isRoot) {
+			var res = json,
+				isFirst = !_data,
+				hasDictionary = isFirst && json && json.length
+					&& json[0][0] === 'dictionary';
+			_data = _data || {};
+			if (Array.isArray(json)) {
+				var type = json[0],
+					isDictionary = type === 'dictionary';
+				if (json.length == 1 && /^#/.test(type)) {
+					return _data.dictionary[type];
+				}
+				type = Base.exports[type];
+				res = [];
+				for (var i = type ? 1 : 0, l = json.length; i < l; i++) {
+					res.push(Base.deserialize(json[i], create, _data,
+							isDictionary, hasDictionary));
+				}
+				if (type) {
+					var args = res;
+					if (create) {
+						res = create(type, args, isFirst || _isRoot);
+					} else {
+						res = Base.create(type.prototype);
+						type.apply(res, args);
+					}
+				}
+			} else if (Base.isPlainObject(json)) {
+				res = {};
+				if (_setDictionary)
+					_data.dictionary = res;
+				for (var key in json)
+					res[key] = Base.deserialize(json[key], create, _data);
+			}
+			return hasDictionary ? res[1] : res;
+		},
+
+		exportJSON: function(obj, options) {
+			var json = Base.serialize(obj, options);
+			return options && options.asString === false
+					? json
+					: JSON.stringify(json);
+		},
+
+		importJSON: function(json, target) {
+			return Base.deserialize(
+					typeof json === 'string' ? JSON.parse(json) : json,
+					function(ctor, args, isRoot) {
+						var useTarget = isRoot && target
+								&& target.constructor === ctor,
+							obj = useTarget ? target
+								: Base.create(ctor.prototype);
+						if (args.length === 1 && obj instanceof Item
+								&& (useTarget || !(obj instanceof Layer))) {
+							var arg = args[0];
+							if (Base.isPlainObject(arg))
+								arg.insert = false;
+						}
+						(useTarget ? obj._set : ctor).apply(obj, args);
+						if (useTarget)
+							target = null;
+						return obj;
+					});
+		},
+
+		splice: function(list, items, index, remove) {
+			var amount = items && items.length,
+				append = index === undefined;
+			index = append ? list.length : index;
+			if (index > list.length)
+				index = list.length;
+			for (var i = 0; i < amount; i++)
+				items[i]._index = index + i;
+			if (append) {
+				list.push.apply(list, items);
+				return [];
+			} else {
+				var args = [index, remove];
+				if (items)
+					args.push.apply(args, items);
+				var removed = list.splice.apply(list, args);
+				for (var i = 0, l = removed.length; i < l; i++)
+					removed[i]._index = undefined;
+				for (var i = index + amount, l = list.length; i < l; i++)
+					list[i]._index = i;
+				return removed;
+			}
+		},
+
+		capitalize: function(str) {
+			return str.replace(/\b[a-z]/g, function(match) {
+				return match.toUpperCase();
+			});
+		},
+
+		camelize: function(str) {
+			return str.replace(/-(.)/g, function(all, chr) {
+				return chr.toUpperCase();
+			});
+		},
+
+		hyphenate: function(str) {
+			return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
+		}
+	}
+});
+
+var Emitter = {
+	on: function(type, func) {
+		if (typeof type !== 'string') {
+			Base.each(type, function(value, key) {
+				this.on(key, value);
+			}, this);
+		} else {
+			var types = this._eventTypes,
+				entry = types && types[type],
+				handlers = this._callbacks = this._callbacks || {};
+			handlers = handlers[type] = handlers[type] || [];
+			if (handlers.indexOf(func) === -1) {
+				handlers.push(func);
+				if (entry && entry.install && handlers.length === 1)
+					entry.install.call(this, type);
+			}
+		}
+		return this;
+	},
+
+	off: function(type, func) {
+		if (typeof type !== 'string') {
+			Base.each(type, function(value, key) {
+				this.off(key, value);
+			}, this);
+			return;
+		}
+		var types = this._eventTypes,
+			entry = types && types[type],
+			handlers = this._callbacks && this._callbacks[type],
+			index;
+		if (handlers) {
+			if (!func || (index = handlers.indexOf(func)) !== -1
+					&& handlers.length === 1) {
+				if (entry && entry.uninstall)
+					entry.uninstall.call(this, type);
+				delete this._callbacks[type];
+			} else if (index !== -1) {
+				handlers.splice(index, 1);
+			}
+		}
+		return this;
+	},
+
+	once: function(type, func) {
+		return this.on(type, function() {
+			func.apply(this, arguments);
+			this.off(type, func);
+		});
+	},
+
+	emit: function(type, event) {
+		var handlers = this._callbacks && this._callbacks[type];
+		if (!handlers)
+			return false;
+		var args = [].slice.call(arguments, 1),
+			setTarget = event && event.target && !event.currentTarget;
+		handlers = handlers.slice();
+		if (setTarget)
+			event.currentTarget = this;
+		for (var i = 0, l = handlers.length; i < l; i++) {
+			if (handlers[i].apply(this, args) === false) {
+				if (event && event.stop)
+					event.stop();
+				break;
+		   }
+		}
+		if (setTarget)
+			delete event.currentTarget;
+		return true;
+	},
+
+	responds: function(type) {
+		return !!(this._callbacks && this._callbacks[type]);
+	},
+
+	attach: '#on',
+	detach: '#off',
+	fire: '#emit',
+
+	_installEvents: function(install) {
+		var types = this._eventTypes,
+			handlers = this._callbacks,
+			key = install ? 'install' : 'uninstall';
+		if (types) {
+			for (var type in handlers) {
+				if (handlers[type].length > 0) {
+					var entry = types[type],
+						func = entry && entry[key];
+					if (func)
+						func.call(this, type);
+				}
+		}
+		}
+	},
+
+	statics: {
+		inject: function inject(src) {
+			var events = src._events;
+			if (events) {
+				var types = {};
+				Base.each(events, function(entry, key) {
+					var isString = typeof entry === 'string',
+						name = isString ? entry : key,
+						part = Base.capitalize(name),
+						type = name.substring(2).toLowerCase();
+					types[type] = isString ? {} : entry;
+					name = '_' + name;
+					src['get' + part] = function() {
+						return this[name];
+					};
+					src['set' + part] = function(func) {
+						var prev = this[name];
+						if (prev)
+							this.off(type, prev);
+						if (func)
+							this.on(type, func);
+						this[name] = func;
+					};
+				});
+				src._eventTypes = types;
+			}
+			return inject.base.apply(this, arguments);
+		}
+	}
+};
+
+var PaperScope = Base.extend({
+	_class: 'PaperScope',
+
+	initialize: function PaperScope() {
+		paper = this;
+		this.settings = new Base({
+			applyMatrix: true,
+			insertItems: true,
+			handleSize: 4,
+			hitTolerance: 0
+		});
+		this.project = null;
+		this.projects = [];
+		this.tools = [];
+		this.palettes = [];
+		this._id = PaperScope._id++;
+		PaperScope._scopes[this._id] = this;
+		var proto = PaperScope.prototype;
+		if (!this.support) {
+			var ctx = CanvasProvider.getContext(1, 1) || {};
+			proto.support = {
+				nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
+				nativeBlendModes: BlendMode.nativeModes
+			};
+			CanvasProvider.release(ctx);
+		}
+		if (!this.agent) {
+			var user = self.navigator.userAgent.toLowerCase(),
+				os = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],
+				platform = os === 'darwin' ? 'mac' : os,
+				agent = proto.agent = proto.browser = { platform: platform };
+			if (platform)
+				agent[platform] = true;
+			user.replace(
+				/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,
+				function(all, n, v1, v2, rv) {
+					if (!agent.chrome) {
+						var v = n === 'opera' ? v2 :
+								/^(node|trident)$/.test(n) ? rv : v1;
+						agent.version = v;
+						agent.versionNumber = parseFloat(v);
+						n = n === 'trident' ? 'msie' : n;
+						agent.name = n;
+						agent[n] = true;
+					}
+				}
+			);
+			if (agent.chrome)
+				delete agent.webkit;
+			if (agent.atom)
+				delete agent.chrome;
+		}
+	},
+
+	version: "0.10.2",
+
+	getView: function() {
+		var project = this.project;
+		return project && project._view;
+	},
+
+	getPaper: function() {
+		return this;
+	},
+
+	execute: function(code, options) {
+		paper.PaperScript.execute(code, this, options);
+		View.updateFocus();
+	},
+
+	install: function(scope) {
+		var that = this;
+		Base.each(['project', 'view', 'tool'], function(key) {
+			Base.define(scope, key, {
+				configurable: true,
+				get: function() {
+					return that[key];
+				}
+			});
+		});
+		for (var key in this)
+			if (!/^_/.test(key) && this[key])
+				scope[key] = this[key];
+	},
+
+	setup: function(element) {
+		paper = this;
+		this.project = new Project(element);
+		return this;
+	},
+
+	createCanvas: function(width, height) {
+		return CanvasProvider.getCanvas(width, height);
+	},
+
+	activate: function() {
+		paper = this;
+	},
+
+	clear: function() {
+		var projects = this.projects,
+			tools = this.tools,
+			palettes = this.palettes;
+		for (var i = projects.length - 1; i >= 0; i--)
+			projects[i].remove();
+		for (var i = tools.length - 1; i >= 0; i--)
+			tools[i].remove();
+		for (var i = palettes.length - 1; i >= 0; i--)
+			palettes[i].remove();
+	},
+
+	remove: function() {
+		this.clear();
+		delete PaperScope._scopes[this._id];
+	},
+
+	statics: new function() {
+		function handleAttribute(name) {
+			name += 'Attribute';
+			return function(el, attr) {
+				return el[name](attr) || el[name]('data-paper-' + attr);
+			};
+		}
+
+		return {
+			_scopes: {},
+			_id: 0,
+
+			get: function(id) {
+				return this._scopes[id] || null;
+			},
+
+			getAttribute: handleAttribute('get'),
+			hasAttribute: handleAttribute('has')
+		};
+	}
+});
+
+var PaperScopeItem = Base.extend(Emitter, {
+
+	initialize: function(activate) {
+		this._scope = paper;
+		this._index = this._scope[this._list].push(this) - 1;
+		if (activate || !this._scope[this._reference])
+			this.activate();
+	},
+
+	activate: function() {
+		if (!this._scope)
+			return false;
+		var prev = this._scope[this._reference];
+		if (prev && prev !== this)
+			prev.emit('deactivate');
+		this._scope[this._reference] = this;
+		this.emit('activate', prev);
+		return true;
+	},
+
+	isActive: function() {
+		return this._scope[this._reference] === this;
+	},
+
+	remove: function() {
+		if (this._index == null)
+			return false;
+		Base.splice(this._scope[this._list], null, this._index, 1);
+		if (this._scope[this._reference] == this)
+			this._scope[this._reference] = null;
+		this._scope = null;
+		return true;
+	},
+
+	getView: function() {
+		return this._scope.getView();
+	}
+});
+
+var Formatter = Base.extend({
+	initialize: function(precision) {
+		this.precision = Base.pick(precision, 5);
+		this.multiplier = Math.pow(10, this.precision);
+	},
+
+	number: function(val) {
+		return this.precision < 16
+				? Math.round(val * this.multiplier) / this.multiplier : val;
+	},
+
+	pair: function(val1, val2, separator) {
+		return this.number(val1) + (separator || ',') + this.number(val2);
+	},
+
+	point: function(val, separator) {
+		return this.number(val.x) + (separator || ',') + this.number(val.y);
+	},
+
+	size: function(val, separator) {
+		return this.number(val.width) + (separator || ',')
+				+ this.number(val.height);
+	},
+
+	rectangle: function(val, separator) {
+		return this.point(val, separator) + (separator || ',')
+				+ this.size(val, separator);
+	}
+});
+
+Formatter.instance = new Formatter();
+
+var Numerical = new function() {
+
+	var abscissas = [
+		[  0.5773502691896257645091488],
+		[0,0.7745966692414833770358531],
+		[  0.3399810435848562648026658,0.8611363115940525752239465],
+		[0,0.5384693101056830910363144,0.9061798459386639927976269],
+		[  0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],
+		[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],
+		[  0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],
+		[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],
+		[  0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],
+		[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],
+		[  0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],
+		[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],
+		[  0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],
+		[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],
+		[  0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]
+	];
+
+	var weights = [
+		[1],
+		[0.8888888888888888888888889,0.5555555555555555555555556],
+		[0.6521451548625461426269361,0.3478548451374538573730639],
+		[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],
+		[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],
+		[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],
+		[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],
+		[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],
+		[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],
+		[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],
+		[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],
+		[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],
+		[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],
+		[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],
+		[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]
+	];
+
+	var abs = Math.abs,
+		sqrt = Math.sqrt,
+		pow = Math.pow,
+		log2 = Math.log2 || function(x) {
+			return Math.log(x) * Math.LOG2E;
+		},
+		EPSILON = 1e-12,
+		MACHINE_EPSILON = 1.12e-16;
+
+	function clamp(value, min, max) {
+		return value < min ? min : value > max ? max : value;
+	}
+
+	function getDiscriminant(a, b, c) {
+		function split(v) {
+			var x = v * 134217729,
+				y = v - x,
+				hi = y + x,
+				lo = v - hi;
+			return [hi, lo];
+		}
+
+		var D = b * b - a * c,
+			E = b * b + a * c;
+		if (abs(D) * 3 < E) {
+			var ad = split(a),
+				bd = split(b),
+				cd = split(c),
+				p = b * b,
+				dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
+				q = a * c,
+				dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
+						+ ad[1] * cd[1];
+			D = (p - q) + (dp - dq);
+		}
+		return D;
+	}
+
+	function getNormalizationFactor() {
+		var norm = Math.max.apply(Math, arguments);
+		return norm && (norm < 1e-8 || norm > 1e8)
+				? pow(2, -Math.round(log2(norm)))
+				: 0;
+	}
+
+	return {
+		TOLERANCE: 1e-6,
+		EPSILON: EPSILON,
+		MACHINE_EPSILON: MACHINE_EPSILON,
+		CURVETIME_EPSILON: 4e-7,
+		GEOMETRIC_EPSILON: 2e-7,
+		WINDING_EPSILON: 2e-7,
+		TRIGONOMETRIC_EPSILON: 1e-7,
+		CLIPPING_EPSILON: 1e-9,
+		KAPPA: 4 * (sqrt(2) - 1) / 3,
+
+		isZero: function(val) {
+			return val >= -EPSILON && val <= EPSILON;
+		},
+
+		clamp: clamp,
+
+		integrate: function(f, a, b, n) {
+			var x = abscissas[n - 2],
+				w = weights[n - 2],
+				A = (b - a) * 0.5,
+				B = A + a,
+				i = 0,
+				m = (n + 1) >> 1,
+				sum = n & 1 ? w[i++] * f(B) : 0;
+			while (i < m) {
+				var Ax = A * x[i];
+				sum += w[i++] * (f(B + Ax) + f(B - Ax));
+			}
+			return A * sum;
+		},
+
+		findRoot: function(f, df, x, a, b, n, tolerance) {
+			for (var i = 0; i < n; i++) {
+				var fx = f(x),
+					dx = fx / df(x),
+					nx = x - dx;
+				if (abs(dx) < tolerance)
+					return nx;
+				if (fx > 0) {
+					b = x;
+					x = nx <= a ? (a + b) * 0.5 : nx;
+				} else {
+					a = x;
+					x = nx >= b ? (a + b) * 0.5 : nx;
+				}
+			}
+			return x;
+		},
+
+		solveQuadratic: function(a, b, c, roots, min, max) {
+			var x1, x2 = Infinity;
+			if (abs(a) < EPSILON) {
+				if (abs(b) < EPSILON)
+					return abs(c) < EPSILON ? -1 : 0;
+				x1 = -c / b;
+			} else {
+				b *= -0.5;
+				var D = getDiscriminant(a, b, c);
+				if (D && abs(D) < MACHINE_EPSILON) {
+					var f = getNormalizationFactor(abs(a), abs(b), abs(c));
+					if (f) {
+						a *= f;
+						b *= f;
+						c *= f;
+						D = getDiscriminant(a, b, c);
+					}
+				}
+				if (D >= -MACHINE_EPSILON) {
+					var Q = D < 0 ? 0 : sqrt(D),
+						R = b + (b < 0 ? -Q : Q);
+					if (R === 0) {
+						x1 = c / a;
+						x2 = -x1;
+					} else {
+						x1 = R / a;
+						x2 = c / R;
+					}
+				}
+			}
+			var count = 0,
+				boundless = min == null,
+				minB = min - EPSILON,
+				maxB = max + EPSILON;
+			if (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))
+				roots[count++] = boundless ? x1 : clamp(x1, min, max);
+			if (x2 !== x1
+					&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))
+				roots[count++] = boundless ? x2 : clamp(x2, min, max);
+			return count;
+		},
+
+		solveCubic: function(a, b, c, d, roots, min, max) {
+			var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),
+				x, b1, c2, qd, q;
+			if (f) {
+				a *= f;
+				b *= f;
+				c *= f;
+				d *= f;
+			}
+
+			function evaluate(x0) {
+				x = x0;
+				var tmp = a * x;
+				b1 = tmp + b;
+				c2 = b1 * x + c;
+				qd = (tmp + b1) * x + c2;
+				q = c2 * x + d;
+			}
+
+			if (abs(a) < EPSILON) {
+				a = b;
+				b1 = c;
+				c2 = d;
+				x = Infinity;
+			} else if (abs(d) < EPSILON) {
+				b1 = b;
+				c2 = c;
+				x = 0;
+			} else {
+				evaluate(-(b / a) / 3);
+				var t = q / a,
+					r = pow(abs(t), 1/3),
+					s = t < 0 ? -1 : 1,
+					td = -qd / a,
+					rd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,
+					x0 = x - s * rd;
+				if (x0 !== x) {
+					do {
+						evaluate(x0);
+						x0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);
+					} while (s * x0 > s * x);
+					if (abs(a) * x * x > abs(d / x)) {
+						c2 = -d / x;
+						b1 = (c2 - c) / x;
+					}
+				}
+			}
+			var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),
+				boundless = min == null;
+			if (isFinite(x) && (count === 0
+					|| count > 0 && x !== roots[0] && x !== roots[1])
+					&& (boundless || x > min - EPSILON && x < max + EPSILON))
+				roots[count++] = boundless ? x : clamp(x, min, max);
+			return count;
+		}
+	};
+};
+
+var UID = {
+	_id: 1,
+	_pools: {},
+
+	get: function(name) {
+		if (name) {
+			var pool = this._pools[name];
+			if (!pool)
+				pool = this._pools[name] = { _id: 1 };
+			return pool._id++;
+		} else {
+			return this._id++;
+		}
+	}
+};
+
+var Point = Base.extend({
+	_class: 'Point',
+	_readIndex: true,
+
+	initialize: function Point(arg0, arg1) {
+		var type = typeof arg0;
+		if (type === 'number') {
+			var hasY = typeof arg1 === 'number';
+			this.x = arg0;
+			this.y = hasY ? arg1 : arg0;
+			if (this.__read)
+				this.__read = hasY ? 2 : 1;
+		} else if (type === 'undefined' || arg0 === null) {
+			this.x = this.y = 0;
+			if (this.__read)
+				this.__read = arg0 === null ? 1 : 0;
+		} else {
+			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
+			if (Array.isArray(obj)) {
+				this.x = obj[0];
+				this.y = obj.length > 1 ? obj[1] : obj[0];
+			} else if ('x' in obj) {
+				this.x = obj.x;
+				this.y = obj.y;
+			} else if ('width' in obj) {
+				this.x = obj.width;
+				this.y = obj.height;
+			} else if ('angle' in obj) {
+				this.x = obj.length;
+				this.y = 0;
+				this.setAngle(obj.angle);
+			} else {
+				this.x = this.y = 0;
+				if (this.__read)
+					this.__read = 0;
+			}
+			if (this.__read)
+				this.__read = 1;
+		}
+	},
+
+	set: function(x, y) {
+		this.x = x;
+		this.y = y;
+		return this;
+	},
+
+	equals: function(point) {
+		return this === point || point
+				&& (this.x === point.x && this.y === point.y
+					|| Array.isArray(point)
+						&& this.x === point[0] && this.y === point[1])
+				|| false;
+	},
+
+	clone: function() {
+		return new Point(this.x, this.y);
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';
+	},
+
+	_serialize: function(options) {
+		var f = options.formatter;
+		return [f.number(this.x), f.number(this.y)];
+	},
+
+	getLength: function() {
+		return Math.sqrt(this.x * this.x + this.y * this.y);
+	},
+
+	setLength: function(length) {
+		if (this.isZero()) {
+			var angle = this._angle || 0;
+			this.set(
+				Math.cos(angle) * length,
+				Math.sin(angle) * length
+			);
+		} else {
+			var scale = length / this.getLength();
+			if (Numerical.isZero(scale))
+				this.getAngle();
+			this.set(
+				this.x * scale,
+				this.y * scale
+			);
+		}
+	},
+	getAngle: function() {
+		return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;
+	},
+
+	setAngle: function(angle) {
+		this.setAngleInRadians.call(this, angle * Math.PI / 180);
+	},
+
+	getAngleInDegrees: '#getAngle',
+	setAngleInDegrees: '#setAngle',
+
+	getAngleInRadians: function() {
+		if (!arguments.length) {
+			return this.isZero()
+					? this._angle || 0
+					: this._angle = Math.atan2(this.y, this.x);
+		} else {
+			var point = Point.read(arguments),
+				div = this.getLength() * point.getLength();
+			if (Numerical.isZero(div)) {
+				return NaN;
+			} else {
+				var a = this.dot(point) / div;
+				return Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);
+			}
+		}
+	},
+
+	setAngleInRadians: function(angle) {
+		this._angle = angle;
+		if (!this.isZero()) {
+			var length = this.getLength();
+			this.set(
+				Math.cos(angle) * length,
+				Math.sin(angle) * length
+			);
+		}
+	},
+
+	getQuadrant: function() {
+		return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
+	}
+}, {
+	beans: false,
+
+	getDirectedAngle: function() {
+		var point = Point.read(arguments);
+		return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;
+	},
+
+	getDistance: function() {
+		var point = Point.read(arguments),
+			x = point.x - this.x,
+			y = point.y - this.y,
+			d = x * x + y * y,
+			squared = Base.read(arguments);
+		return squared ? d : Math.sqrt(d);
+	},
+
+	normalize: function(length) {
+		if (length === undefined)
+			length = 1;
+		var current = this.getLength(),
+			scale = current !== 0 ? length / current : 0,
+			point = new Point(this.x * scale, this.y * scale);
+		if (scale >= 0)
+			point._angle = this._angle;
+		return point;
+	},
+
+	rotate: function(angle, center) {
+		if (angle === 0)
+			return this.clone();
+		angle = angle * Math.PI / 180;
+		var point = center ? this.subtract(center) : this,
+			sin = Math.sin(angle),
+			cos = Math.cos(angle);
+		point = new Point(
+			point.x * cos - point.y * sin,
+			point.x * sin + point.y * cos
+		);
+		return center ? point.add(center) : point;
+	},
+
+	transform: function(matrix) {
+		return matrix ? matrix._transformPoint(this) : this;
+	},
+
+	add: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x + point.x, this.y + point.y);
+	},
+
+	subtract: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x - point.x, this.y - point.y);
+	},
+
+	multiply: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x * point.x, this.y * point.y);
+	},
+
+	divide: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x / point.x, this.y / point.y);
+	},
+
+	modulo: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x % point.x, this.y % point.y);
+	},
+
+	negate: function() {
+		return new Point(-this.x, -this.y);
+	},
+
+	isInside: function() {
+		return Rectangle.read(arguments).contains(this);
+	},
+
+	isClose: function() {
+		var point = Point.read(arguments),
+			tolerance = Base.read(arguments);
+		return this.getDistance(point) <= tolerance;
+	},
+
+	isCollinear: function() {
+		var point = Point.read(arguments);
+		return Point.isCollinear(this.x, this.y, point.x, point.y);
+	},
+
+	isColinear: '#isCollinear',
+
+	isOrthogonal: function() {
+		var point = Point.read(arguments);
+		return Point.isOrthogonal(this.x, this.y, point.x, point.y);
+	},
+
+	isZero: function() {
+		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
+	},
+
+	isNaN: function() {
+		return isNaN(this.x) || isNaN(this.y);
+	},
+
+	dot: function() {
+		var point = Point.read(arguments);
+		return this.x * point.x + this.y * point.y;
+	},
+
+	cross: function() {
+		var point = Point.read(arguments);
+		return this.x * point.y - this.y * point.x;
+	},
+
+	project: function() {
+		var point = Point.read(arguments),
+			scale = point.isZero() ? 0 : this.dot(point) / point.dot(point);
+		return new Point(
+			point.x * scale,
+			point.y * scale
+		);
+	},
+
+	statics: {
+		min: function() {
+			var point1 = Point.read(arguments),
+				point2 = Point.read(arguments);
+			return new Point(
+				Math.min(point1.x, point2.x),
+				Math.min(point1.y, point2.y)
+			);
+		},
+
+		max: function() {
+			var point1 = Point.read(arguments),
+				point2 = Point.read(arguments);
+			return new Point(
+				Math.max(point1.x, point2.x),
+				Math.max(point1.y, point2.y)
+			);
+		},
+
+		random: function() {
+			return new Point(Math.random(), Math.random());
+		},
+
+		isCollinear: function(x1, y1, x2, y2) {
+			return Math.abs(x1 * y2 - y1 * x2)
+					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
+						* 1e-7;
+		},
+
+		isOrthogonal: function(x1, y1, x2, y2) {
+			return Math.abs(x1 * x2 + y1 * y2)
+					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
+						* 1e-7;
+		}
+	}
+}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
+	var op = Math[key];
+	this[key] = function() {
+		return new Point(op(this.x), op(this.y));
+	};
+}, {}));
+
+var LinkedPoint = Point.extend({
+	initialize: function Point(x, y, owner, setter) {
+		this._x = x;
+		this._y = y;
+		this._owner = owner;
+		this._setter = setter;
+	},
+
+	set: function(x, y, _dontNotify) {
+		this._x = x;
+		this._y = y;
+		if (!_dontNotify)
+			this._owner[this._setter](this);
+		return this;
+	},
+
+	getX: function() {
+		return this._x;
+	},
+
+	setX: function(x) {
+		this._x = x;
+		this._owner[this._setter](this);
+	},
+
+	getY: function() {
+		return this._y;
+	},
+
+	setY: function(y) {
+		this._y = y;
+		this._owner[this._setter](this);
+	},
+
+	isSelected: function() {
+		return !!(this._owner._selection & this._getSelection());
+	},
+
+	setSelected: function(selected) {
+		this._owner.changeSelection(this._getSelection(), selected);
+	},
+
+	_getSelection: function() {
+		return this._setter === 'setPosition' ? 4 : 0;
+	}
+});
+
+var Size = Base.extend({
+	_class: 'Size',
+	_readIndex: true,
+
+	initialize: function Size(arg0, arg1) {
+		var type = typeof arg0;
+		if (type === 'number') {
+			var hasHeight = typeof arg1 === 'number';
+			this.width = arg0;
+			this.height = hasHeight ? arg1 : arg0;
+			if (this.__read)
+				this.__read = hasHeight ? 2 : 1;
+		} else if (type === 'undefined' || arg0 === null) {
+			this.width = this.height = 0;
+			if (this.__read)
+				this.__read = arg0 === null ? 1 : 0;
+		} else {
+			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
+			if (Array.isArray(obj)) {
+				this.width = obj[0];
+				this.height = obj.length > 1 ? obj[1] : obj[0];
+			} else if ('width' in obj) {
+				this.width = obj.width;
+				this.height = obj.height;
+			} else if ('x' in obj) {
+				this.width = obj.x;
+				this.height = obj.y;
+			} else {
+				this.width = this.height = 0;
+				if (this.__read)
+					this.__read = 0;
+			}
+			if (this.__read)
+				this.__read = 1;
+		}
+	},
+
+	set: function(width, height) {
+		this.width = width;
+		this.height = height;
+		return this;
+	},
+
+	equals: function(size) {
+		return size === this || size && (this.width === size.width
+				&& this.height === size.height
+				|| Array.isArray(size) && this.width === size[0]
+					&& this.height === size[1]) || false;
+	},
+
+	clone: function() {
+		return new Size(this.width, this.height);
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '{ width: ' + f.number(this.width)
+				+ ', height: ' + f.number(this.height) + ' }';
+	},
+
+	_serialize: function(options) {
+		var f = options.formatter;
+		return [f.number(this.width),
+				f.number(this.height)];
+	},
+
+	add: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width + size.width, this.height + size.height);
+	},
+
+	subtract: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width - size.width, this.height - size.height);
+	},
+
+	multiply: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width * size.width, this.height * size.height);
+	},
+
+	divide: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width / size.width, this.height / size.height);
+	},
+
+	modulo: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width % size.width, this.height % size.height);
+	},
+
+	negate: function() {
+		return new Size(-this.width, -this.height);
+	},
+
+	isZero: function() {
+		return Numerical.isZero(this.width) && Numerical.isZero(this.height);
+	},
+
+	isNaN: function() {
+		return isNaN(this.width) || isNaN(this.height);
+	},
+
+	statics: {
+		min: function(size1, size2) {
+			return new Size(
+				Math.min(size1.width, size2.width),
+				Math.min(size1.height, size2.height));
+		},
+
+		max: function(size1, size2) {
+			return new Size(
+				Math.max(size1.width, size2.width),
+				Math.max(size1.height, size2.height));
+		},
+
+		random: function() {
+			return new Size(Math.random(), Math.random());
+		}
+	}
+}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
+	var op = Math[key];
+	this[key] = function() {
+		return new Size(op(this.width), op(this.height));
+	};
+}, {}));
+
+var LinkedSize = Size.extend({
+	initialize: function Size(width, height, owner, setter) {
+		this._width = width;
+		this._height = height;
+		this._owner = owner;
+		this._setter = setter;
+	},
+
+	set: function(width, height, _dontNotify) {
+		this._width = width;
+		this._height = height;
+		if (!_dontNotify)
+			this._owner[this._setter](this);
+		return this;
+	},
+
+	getWidth: function() {
+		return this._width;
+	},
+
+	setWidth: function(width) {
+		this._width = width;
+		this._owner[this._setter](this);
+	},
+
+	getHeight: function() {
+		return this._height;
+	},
+
+	setHeight: function(height) {
+		this._height = height;
+		this._owner[this._setter](this);
+	}
+});
+
+var Rectangle = Base.extend({
+	_class: 'Rectangle',
+	_readIndex: true,
+	beans: true,
+
+	initialize: function Rectangle(arg0, arg1, arg2, arg3) {
+		var type = typeof arg0,
+			read = 0;
+		if (type === 'number') {
+			this.x = arg0;
+			this.y = arg1;
+			this.width = arg2;
+			this.height = arg3;
+			read = 4;
+		} else if (type === 'undefined' || arg0 === null) {
+			this.x = this.y = this.width = this.height = 0;
+			read = arg0 === null ? 1 : 0;
+		} else if (arguments.length === 1) {
+			if (Array.isArray(arg0)) {
+				this.x = arg0[0];
+				this.y = arg0[1];
+				this.width = arg0[2];
+				this.height = arg0[3];
+				read = 1;
+			} else if (arg0.x !== undefined || arg0.width !== undefined) {
+				this.x = arg0.x || 0;
+				this.y = arg0.y || 0;
+				this.width = arg0.width || 0;
+				this.height = arg0.height || 0;
+				read = 1;
+			} else if (arg0.from === undefined && arg0.to === undefined) {
+				this.x = this.y = this.width = this.height = 0;
+				this._set(arg0);
+				read = 1;
+			}
+		}
+		if (!read) {
+			var point = Point.readNamed(arguments, 'from'),
+				next = Base.peek(arguments);
+			this.x = point.x;
+			this.y = point.y;
+			if (next && next.x !== undefined || Base.hasNamed(arguments, 'to')) {
+				var to = Point.readNamed(arguments, 'to');
+				this.width = to.x - point.x;
+				this.height = to.y - point.y;
+				if (this.width < 0) {
+					this.x = to.x;
+					this.width = -this.width;
+				}
+				if (this.height < 0) {
+					this.y = to.y;
+					this.height = -this.height;
+				}
+			} else {
+				var size = Size.read(arguments);
+				this.width = size.width;
+				this.height = size.height;
+			}
+			read = arguments.__index;
+		}
+		if (this.__read)
+			this.__read = read;
+	},
+
+	set: function(x, y, width, height) {
+		this.x = x;
+		this.y = y;
+		this.width = width;
+		this.height = height;
+		return this;
+	},
+
+	clone: function() {
+		return new Rectangle(this.x, this.y, this.width, this.height);
+	},
+
+	equals: function(rect) {
+		var rt = Base.isPlainValue(rect)
+				? Rectangle.read(arguments)
+				: rect;
+		return rt === this
+				|| rt && this.x === rt.x && this.y === rt.y
+					&& this.width === rt.width && this.height === rt.height
+				|| false;
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '{ x: ' + f.number(this.x)
+				+ ', y: ' + f.number(this.y)
+				+ ', width: ' + f.number(this.width)
+				+ ', height: ' + f.number(this.height)
+				+ ' }';
+	},
+
+	_serialize: function(options) {
+		var f = options.formatter;
+		return [f.number(this.x),
+				f.number(this.y),
+				f.number(this.width),
+				f.number(this.height)];
+	},
+
+	getPoint: function(_dontLink) {
+		var ctor = _dontLink ? Point : LinkedPoint;
+		return new ctor(this.x, this.y, this, 'setPoint');
+	},
+
+	setPoint: function() {
+		var point = Point.read(arguments);
+		this.x = point.x;
+		this.y = point.y;
+	},
+
+	getSize: function(_dontLink) {
+		var ctor = _dontLink ? Size : LinkedSize;
+		return new ctor(this.width, this.height, this, 'setSize');
+	},
+
+	setSize: function() {
+		var size = Size.read(arguments);
+		if (this._fixX)
+			this.x += (this.width - size.width) * this._fixX;
+		if (this._fixY)
+			this.y += (this.height - size.height) * this._fixY;
+		this.width = size.width;
+		this.height = size.height;
+		this._fixW = 1;
+		this._fixH = 1;
+	},
+
+	getLeft: function() {
+		return this.x;
+	},
+
+	setLeft: function(left) {
+		if (!this._fixW)
+			this.width -= left - this.x;
+		this.x = left;
+		this._fixX = 0;
+	},
+
+	getTop: function() {
+		return this.y;
+	},
+
+	setTop: function(top) {
+		if (!this._fixH)
+			this.height -= top - this.y;
+		this.y = top;
+		this._fixY = 0;
+	},
+
+	getRight: function() {
+		return this.x + this.width;
+	},
+
+	setRight: function(right) {
+		if (this._fixX !== undefined && this._fixX !== 1)
+			this._fixW = 0;
+		if (this._fixW)
+			this.x = right - this.width;
+		else
+			this.width = right - this.x;
+		this._fixX = 1;
+	},
+
+	getBottom: function() {
+		return this.y + this.height;
+	},
+
+	setBottom: function(bottom) {
+		if (this._fixY !== undefined && this._fixY !== 1)
+			this._fixH = 0;
+		if (this._fixH)
+			this.y = bottom - this.height;
+		else
+			this.height = bottom - this.y;
+		this._fixY = 1;
+	},
+
+	getCenterX: function() {
+		return this.x + this.width * 0.5;
+	},
+
+	setCenterX: function(x) {
+		this.x = x - this.width * 0.5;
+		this._fixX = 0.5;
+	},
+
+	getCenterY: function() {
+		return this.y + this.height * 0.5;
+	},
+
+	setCenterY: function(y) {
+		this.y = y - this.height * 0.5;
+		this._fixY = 0.5;
+	},
+
+	getCenter: function(_dontLink) {
+		var ctor = _dontLink ? Point : LinkedPoint;
+		return new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');
+	},
+
+	setCenter: function() {
+		var point = Point.read(arguments);
+		this.setCenterX(point.x);
+		this.setCenterY(point.y);
+		return this;
+	},
+
+	getArea: function() {
+		return this.width * this.height;
+	},
+
+	isEmpty: function() {
+		return this.width === 0 || this.height === 0;
+	},
+
+	contains: function(arg) {
+		return arg && arg.width !== undefined
+				|| (Array.isArray(arg) ? arg : arguments).length === 4
+				? this._containsRectangle(Rectangle.read(arguments))
+				: this._containsPoint(Point.read(arguments));
+	},
+
+	_containsPoint: function(point) {
+		var x = point.x,
+			y = point.y;
+		return x >= this.x && y >= this.y
+				&& x <= this.x + this.width
+				&& y <= this.y + this.height;
+	},
+
+	_containsRectangle: function(rect) {
+		var x = rect.x,
+			y = rect.y;
+		return x >= this.x && y >= this.y
+				&& x + rect.width <= this.x + this.width
+				&& y + rect.height <= this.y + this.height;
+	},
+
+	intersects: function() {
+		var rect = Rectangle.read(arguments);
+		return rect.x + rect.width > this.x
+				&& rect.y + rect.height > this.y
+				&& rect.x < this.x + this.width
+				&& rect.y < this.y + this.height;
+	},
+
+	touches: function() {
+		var rect = Rectangle.read(arguments);
+		return rect.x + rect.width >= this.x
+				&& rect.y + rect.height >= this.y
+				&& rect.x <= this.x + this.width
+				&& rect.y <= this.y + this.height;
+	},
+
+	intersect: function() {
+		var rect = Rectangle.read(arguments),
+			x1 = Math.max(this.x, rect.x),
+			y1 = Math.max(this.y, rect.y),
+			x2 = Math.min(this.x + this.width, rect.x + rect.width),
+			y2 = Math.min(this.y + this.height, rect.y + rect.height);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	},
+
+	unite: function() {
+		var rect = Rectangle.read(arguments),
+			x1 = Math.min(this.x, rect.x),
+			y1 = Math.min(this.y, rect.y),
+			x2 = Math.max(this.x + this.width, rect.x + rect.width),
+			y2 = Math.max(this.y + this.height, rect.y + rect.height);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	},
+
+	include: function() {
+		var point = Point.read(arguments);
+		var x1 = Math.min(this.x, point.x),
+			y1 = Math.min(this.y, point.y),
+			x2 = Math.max(this.x + this.width, point.x),
+			y2 = Math.max(this.y + this.height, point.y);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	},
+
+	expand: function() {
+		var amount = Size.read(arguments),
+			hor = amount.width,
+			ver = amount.height;
+		return new Rectangle(this.x - hor / 2, this.y - ver / 2,
+				this.width + hor, this.height + ver);
+	},
+
+	scale: function(hor, ver) {
+		return this.expand(this.width * hor - this.width,
+				this.height * (ver === undefined ? hor : ver) - this.height);
+	}
+}, Base.each([
+		['Top', 'Left'], ['Top', 'Right'],
+		['Bottom', 'Left'], ['Bottom', 'Right'],
+		['Left', 'Center'], ['Top', 'Center'],
+		['Right', 'Center'], ['Bottom', 'Center']
+	],
+	function(parts, index) {
+		var part = parts.join(''),
+			xFirst = /^[RL]/.test(part);
+		if (index >= 4)
+			parts[1] += xFirst ? 'Y' : 'X';
+		var x = parts[xFirst ? 0 : 1],
+			y = parts[xFirst ? 1 : 0],
+			getX = 'get' + x,
+			getY = 'get' + y,
+			setX = 'set' + x,
+			setY = 'set' + y,
+			get = 'get' + part,
+			set = 'set' + part;
+		this[get] = function(_dontLink) {
+			var ctor = _dontLink ? Point : LinkedPoint;
+			return new ctor(this[getX](), this[getY](), this, set);
+		};
+		this[set] = function() {
+			var point = Point.read(arguments);
+			this[setX](point.x);
+			this[setY](point.y);
+		};
+	}, {
+		beans: true
+	}
+));
+
+var LinkedRectangle = Rectangle.extend({
+	initialize: function Rectangle(x, y, width, height, owner, setter) {
+		this.set(x, y, width, height, true);
+		this._owner = owner;
+		this._setter = setter;
+	},
+
+	set: function(x, y, width, height, _dontNotify) {
+		this._x = x;
+		this._y = y;
+		this._width = width;
+		this._height = height;
+		if (!_dontNotify)
+			this._owner[this._setter](this);
+		return this;
+	}
+},
+new function() {
+	var proto = Rectangle.prototype;
+
+	return Base.each(['x', 'y', 'width', 'height'], function(key) {
+		var part = Base.capitalize(key),
+			internal = '_' + key;
+		this['get' + part] = function() {
+			return this[internal];
+		};
+
+		this['set' + part] = function(value) {
+			this[internal] = value;
+			if (!this._dontNotify)
+				this._owner[this._setter](this);
+		};
+	}, Base.each(['Point', 'Size', 'Center',
+			'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',
+			'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
+			'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],
+		function(key) {
+			var name = 'set' + key;
+			this[name] = function() {
+				this._dontNotify = true;
+				proto[name].apply(this, arguments);
+				this._dontNotify = false;
+				this._owner[this._setter](this);
+			};
+		}, {
+			isSelected: function() {
+				return !!(this._owner._selection & 2);
+			},
+
+			setSelected: function(selected) {
+				var owner = this._owner;
+				if (owner.changeSelection) {
+					owner.changeSelection(2, selected);
+				}
+			}
+		})
+	);
+});
+
+var Matrix = Base.extend({
+	_class: 'Matrix',
+
+	initialize: function Matrix(arg) {
+		var count = arguments.length,
+			ok = true;
+		if (count === 6) {
+			this.set.apply(this, arguments);
+		} else if (count === 1) {
+			if (arg instanceof Matrix) {
+				this.set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty);
+			} else if (Array.isArray(arg)) {
+				this.set.apply(this, arg);
+			} else {
+				ok = false;
+			}
+		} else if (count === 0) {
+			this.reset();
+		} else {
+			ok = false;
+		}
+		if (!ok) {
+			throw new Error('Unsupported matrix parameters');
+		}
+	},
+
+	set: function(a, b, c, d, tx, ty, _dontNotify) {
+		this._a = a;
+		this._b = b;
+		this._c = c;
+		this._d = d;
+		this._tx = tx;
+		this._ty = ty;
+		if (!_dontNotify)
+			this._changed();
+		return this;
+	},
+
+	_serialize: function(options, dictionary) {
+		return Base.serialize(this.getValues(), options, true, dictionary);
+	},
+
+	_changed: function() {
+		var owner = this._owner;
+		if (owner) {
+			if (owner._applyMatrix) {
+				owner.transform(null, true);
+			} else {
+				owner._changed(9);
+			}
+		}
+	},
+
+	clone: function() {
+		return new Matrix(this._a, this._b, this._c, this._d,
+				this._tx, this._ty);
+	},
+
+	equals: function(mx) {
+		return mx === this || mx && this._a === mx._a && this._b === mx._b
+				&& this._c === mx._c && this._d === mx._d
+				&& this._tx === mx._tx && this._ty === mx._ty;
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '[[' + [f.number(this._a), f.number(this._c),
+					f.number(this._tx)].join(', ') + '], ['
+				+ [f.number(this._b), f.number(this._d),
+					f.number(this._ty)].join(', ') + ']]';
+	},
+
+	reset: function(_dontNotify) {
+		this._a = this._d = 1;
+		this._b = this._c = this._tx = this._ty = 0;
+		if (!_dontNotify)
+			this._changed();
+		return this;
+	},
+
+	apply: function(recursively, _setApplyMatrix) {
+		var owner = this._owner;
+		if (owner) {
+			owner.transform(null, true, Base.pick(recursively, true),
+					_setApplyMatrix);
+			return this.isIdentity();
+		}
+		return false;
+	},
+
+	translate: function() {
+		var point = Point.read(arguments),
+			x = point.x,
+			y = point.y;
+		this._tx += x * this._a + y * this._c;
+		this._ty += x * this._b + y * this._d;
+		this._changed();
+		return this;
+	},
+
+	scale: function() {
+		var scale = Point.read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		if (center)
+			this.translate(center);
+		this._a *= scale.x;
+		this._b *= scale.x;
+		this._c *= scale.y;
+		this._d *= scale.y;
+		if (center)
+			this.translate(center.negate());
+		this._changed();
+		return this;
+	},
+
+	rotate: function(angle ) {
+		angle *= Math.PI / 180;
+		var center = Point.read(arguments, 1),
+			x = center.x,
+			y = center.y,
+			cos = Math.cos(angle),
+			sin = Math.sin(angle),
+			tx = x - x * cos + y * sin,
+			ty = y - x * sin - y * cos,
+			a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d;
+		this._a = cos * a + sin * c;
+		this._b = cos * b + sin * d;
+		this._c = -sin * a + cos * c;
+		this._d = -sin * b + cos * d;
+		this._tx += tx * a + ty * c;
+		this._ty += tx * b + ty * d;
+		this._changed();
+		return this;
+	},
+
+	shear: function() {
+		var shear = Point.read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		if (center)
+			this.translate(center);
+		var a = this._a,
+			b = this._b;
+		this._a += shear.y * this._c;
+		this._b += shear.y * this._d;
+		this._c += shear.x * a;
+		this._d += shear.x * b;
+		if (center)
+			this.translate(center.negate());
+		this._changed();
+		return this;
+	},
+
+	skew: function() {
+		var skew = Point.read(arguments),
+			center = Point.read(arguments, 0, { readNull: true }),
+			toRadians = Math.PI / 180,
+			shear = new Point(Math.tan(skew.x * toRadians),
+				Math.tan(skew.y * toRadians));
+		return this.shear(shear, center);
+	},
+
+	append: function(mx) {
+		if (mx) {
+			var a1 = this._a,
+				b1 = this._b,
+				c1 = this._c,
+				d1 = this._d,
+				a2 = mx._a,
+				b2 = mx._c,
+				c2 = mx._b,
+				d2 = mx._d,
+				tx2 = mx._tx,
+				ty2 = mx._ty;
+			this._a = a2 * a1 + c2 * c1;
+			this._c = b2 * a1 + d2 * c1;
+			this._b = a2 * b1 + c2 * d1;
+			this._d = b2 * b1 + d2 * d1;
+			this._tx += tx2 * a1 + ty2 * c1;
+			this._ty += tx2 * b1 + ty2 * d1;
+			this._changed();
+		}
+		return this;
+	},
+
+	prepend: function(mx) {
+		if (mx) {
+			var a1 = this._a,
+				b1 = this._b,
+				c1 = this._c,
+				d1 = this._d,
+				tx1 = this._tx,
+				ty1 = this._ty,
+				a2 = mx._a,
+				b2 = mx._c,
+				c2 = mx._b,
+				d2 = mx._d,
+				tx2 = mx._tx,
+				ty2 = mx._ty;
+			this._a = a2 * a1 + b2 * b1;
+			this._c = a2 * c1 + b2 * d1;
+			this._b = c2 * a1 + d2 * b1;
+			this._d = c2 * c1 + d2 * d1;
+			this._tx = a2 * tx1 + b2 * ty1 + tx2;
+			this._ty = c2 * tx1 + d2 * ty1 + ty2;
+			this._changed();
+		}
+		return this;
+	},
+
+	appended: function(mx) {
+		return this.clone().append(mx);
+	},
+
+	prepended: function(mx) {
+		return this.clone().prepend(mx);
+	},
+
+	invert: function() {
+		var a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d,
+			tx = this._tx,
+			ty = this._ty,
+			det = a * d - b * c,
+			res = null;
+		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
+			this._a = d / det;
+			this._b = -b / det;
+			this._c = -c / det;
+			this._d = a / det;
+			this._tx = (c * ty - d * tx) / det;
+			this._ty = (b * tx - a * ty) / det;
+			res = this;
+		}
+		return res;
+	},
+
+	inverted: function() {
+		return this.clone().invert();
+	},
+
+	concatenate: '#append',
+	preConcatenate: '#prepend',
+	chain: '#appended',
+
+	_shiftless: function() {
+		return new Matrix(this._a, this._b, this._c, this._d, 0, 0);
+	},
+
+	_orNullIfIdentity: function() {
+		return this.isIdentity() ? null : this;
+	},
+
+	isIdentity: function() {
+		return this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1
+				&& this._tx === 0 && this._ty === 0;
+	},
+
+	isInvertible: function() {
+		var det = this._a * this._d - this._c * this._b;
+		return det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);
+	},
+
+	isSingular: function() {
+		return !this.isInvertible();
+	},
+
+	transform: function( src, dst, count) {
+		return arguments.length < 3
+			? this._transformPoint(Point.read(arguments))
+			: this._transformCoordinates(src, dst, count);
+	},
+
+	_transformPoint: function(point, dest, _dontNotify) {
+		var x = point.x,
+			y = point.y;
+		if (!dest)
+			dest = new Point();
+		return dest.set(
+				x * this._a + y * this._c + this._tx,
+				x * this._b + y * this._d + this._ty,
+				_dontNotify);
+	},
+
+	_transformCoordinates: function(src, dst, count) {
+		for (var i = 0, max = 2 * count; i < max; i += 2) {
+			var x = src[i],
+				y = src[i + 1];
+			dst[i] = x * this._a + y * this._c + this._tx;
+			dst[i + 1] = x * this._b + y * this._d + this._ty;
+		}
+		return dst;
+	},
+
+	_transformCorners: function(rect) {
+		var x1 = rect.x,
+			y1 = rect.y,
+			x2 = x1 + rect.width,
+			y2 = y1 + rect.height,
+			coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];
+		return this._transformCoordinates(coords, coords, 4);
+	},
+
+	_transformBounds: function(bounds, dest, _dontNotify) {
+		var coords = this._transformCorners(bounds),
+			min = coords.slice(0, 2),
+			max = min.slice();
+		for (var i = 2; i < 8; i++) {
+			var val = coords[i],
+				j = i & 1;
+			if (val < min[j]) {
+				min[j] = val;
+			} else if (val > max[j]) {
+				max[j] = val;
+			}
+		}
+		if (!dest)
+			dest = new Rectangle();
+		return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1],
+				_dontNotify);
+	},
+
+	inverseTransform: function() {
+		return this._inverseTransform(Point.read(arguments));
+	},
+
+	_inverseTransform: function(point, dest, _dontNotify) {
+		var a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d,
+			tx = this._tx,
+			ty = this._ty,
+			det = a * d - b * c,
+			res = null;
+		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
+			var x = point.x - this._tx,
+				y = point.y - this._ty;
+			if (!dest)
+				dest = new Point();
+			res = dest.set(
+					(x * d - y * c) / det,
+					(y * a - x * b) / det,
+					_dontNotify);
+		}
+		return res;
+	},
+
+	decompose: function() {
+		var a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d,
+			det = a * d - b * c,
+			sqrt = Math.sqrt,
+			atan2 = Math.atan2,
+			degrees = 180 / Math.PI,
+			rotate,
+			scale,
+			skew;
+		if (a !== 0 || b !== 0) {
+			var r = sqrt(a * a + b * b);
+			rotate = Math.acos(a / r) * (b > 0 ? 1 : -1);
+			scale = [r, det / r];
+			skew = [atan2(a * c + b * d, r * r), 0];
+		} else if (c !== 0 || d !== 0) {
+			var s = sqrt(c * c + d * d);
+			rotate = Math.asin(c / s)  * (d > 0 ? 1 : -1);
+			scale = [det / s, s];
+			skew = [0, atan2(a * c + b * d, s * s)];
+		} else {
+			rotate = 0;
+			skew = scale = [0, 0];
+		}
+		return {
+			translation: this.getTranslation(),
+			rotation: rotate * degrees,
+			scaling: new Point(scale),
+			skewing: new Point(skew[0] * degrees, skew[1] * degrees)
+		};
+	},
+
+	getValues: function() {
+		return [ this._a, this._b, this._c, this._d, this._tx, this._ty ];
+	},
+
+	getTranslation: function() {
+		return new Point(this._tx, this._ty);
+	},
+
+	getScaling: function() {
+		return (this.decompose() || {}).scaling;
+	},
+
+	getRotation: function() {
+		return (this.decompose() || {}).rotation;
+	},
+
+	applyToContext: function(ctx) {
+		if (!this.isIdentity()) {
+			ctx.transform(this._a, this._b, this._c, this._d,
+					this._tx, this._ty);
+		}
+	}
+}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {
+	var part = Base.capitalize(key),
+		prop = '_' + key;
+	this['get' + part] = function() {
+		return this[prop];
+	};
+	this['set' + part] = function(value) {
+		this[prop] = value;
+		this._changed();
+	};
+}, {}));
+
+var Line = Base.extend({
+	_class: 'Line',
+
+	initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
+		var asVector = false;
+		if (arguments.length >= 4) {
+			this._px = arg0;
+			this._py = arg1;
+			this._vx = arg2;
+			this._vy = arg3;
+			asVector = arg4;
+		} else {
+			this._px = arg0.x;
+			this._py = arg0.y;
+			this._vx = arg1.x;
+			this._vy = arg1.y;
+			asVector = arg2;
+		}
+		if (!asVector) {
+			this._vx -= this._px;
+			this._vy -= this._py;
+		}
+	},
+
+	getPoint: function() {
+		return new Point(this._px, this._py);
+	},
+
+	getVector: function() {
+		return new Point(this._vx, this._vy);
+	},
+
+	getLength: function() {
+		return this.getVector().getLength();
+	},
+
+	intersect: function(line, isInfinite) {
+		return Line.intersect(
+				this._px, this._py, this._vx, this._vy,
+				line._px, line._py, line._vx, line._vy,
+				true, isInfinite);
+	},
+
+	getSide: function(point, isInfinite) {
+		return Line.getSide(
+				this._px, this._py, this._vx, this._vy,
+				point.x, point.y, true, isInfinite);
+	},
+
+	getDistance: function(point) {
+		return Math.abs(Line.getSignedDistance(
+				this._px, this._py, this._vx, this._vy,
+				point.x, point.y, true));
+	},
+
+	isCollinear: function(line) {
+		return Point.isCollinear(this._vx, this._vy, line._vx, line._vy);
+	},
+
+	isOrthogonal: function(line) {
+		return Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);
+	},
+
+	statics: {
+		intersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,
+				isInfinite) {
+			if (!asVector) {
+				v1x -= p1x;
+				v1y -= p1y;
+				v2x -= p2x;
+				v2y -= p2y;
+			}
+			var cross = v1x * v2y - v1y * v2x;
+			if (!Numerical.isZero(cross)) {
+				var dx = p1x - p2x,
+					dy = p1y - p2y,
+					u1 = (v2x * dy - v2y * dx) / cross,
+					u2 = (v1x * dy - v1y * dx) / cross,
+					epsilon = 1e-12,
+					uMin = -epsilon,
+					uMax = 1 + epsilon;
+				if (isInfinite
+						|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {
+					if (!isInfinite) {
+						u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;
+					}
+					return new Point(
+							p1x + u1 * v1x,
+							p1y + u1 * v1y);
+				}
+			}
+		},
+
+		getSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {
+			if (!asVector) {
+				vx -= px;
+				vy -= py;
+			}
+			var v2x = x - px,
+				v2y = y - py,
+				ccw = v2x * vy - v2y * vx;
+			if (ccw === 0 && !isInfinite) {
+				ccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);
+				if (ccw >= 0 && ccw <= 1)
+					ccw = 0;
+			}
+			return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
+		},
+
+		getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
+			if (!asVector) {
+				vx -= px;
+				vy -= py;
+			}
+			return vx === 0 ? vy > 0 ? x - px : px - x
+				 : vy === 0 ? vx < 0 ? y - py : py - y
+				 : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);
+		}
+	}
+});
+
+var Project = PaperScopeItem.extend({
+	_class: 'Project',
+	_list: 'projects',
+	_reference: 'project',
+	_compactSerialize: true,
+
+	initialize: function Project(element) {
+		PaperScopeItem.call(this, true);
+		this._children = [];
+		this._namedChildren = {};
+		this._activeLayer = null;
+		this._currentStyle = new Style(null, null, this);
+		this._view = View.create(this,
+				element || CanvasProvider.getCanvas(1, 1));
+		this._selectionItems = {};
+		this._selectionCount = 0;
+		this._updateVersion = 0;
+	},
+
+	_serialize: function(options, dictionary) {
+		return Base.serialize(this._children, options, true, dictionary);
+	},
+
+	_changed: function(flags, item) {
+		if (flags & 1) {
+			var view = this._view;
+			if (view) {
+				view._needsUpdate = true;
+				if (!view._requested && view._autoUpdate)
+					view.requestUpdate();
+			}
+		}
+		var changes = this._changes;
+		if (changes && item) {
+			var changesById = this._changesById,
+				id = item._id,
+				entry = changesById[id];
+			if (entry) {
+				entry.flags |= flags;
+			} else {
+				changes.push(changesById[id] = { item: item, flags: flags });
+			}
+		}
+	},
+
+	clear: function() {
+		var children = this._children;
+		for (var i = children.length - 1; i >= 0; i--)
+			children[i].remove();
+	},
+
+	isEmpty: function() {
+		return this._children.length === 0;
+	},
+
+	remove: function remove() {
+		if (!remove.base.call(this))
+			return false;
+		if (this._view)
+			this._view.remove();
+		return true;
+	},
+
+	getView: function() {
+		return this._view;
+	},
+
+	getCurrentStyle: function() {
+		return this._currentStyle;
+	},
+
+	setCurrentStyle: function(style) {
+		this._currentStyle.initialize(style);
+	},
+
+	getIndex: function() {
+		return this._index;
+	},
+
+	getOptions: function() {
+		return this._scope.settings;
+	},
+
+	getLayers: function() {
+		return this._children;
+	},
+
+	getActiveLayer: function() {
+		return this._activeLayer || new Layer({ project: this, insert: true });
+	},
+
+	getSymbolDefinitions: function() {
+		var definitions = [],
+			ids = {};
+		this.getItems({
+			class: SymbolItem,
+			match: function(item) {
+				var definition = item._definition,
+					id = definition._id;
+				if (!ids[id]) {
+					ids[id] = true;
+					definitions.push(definition);
+				}
+				return false;
+			}
+		});
+		return definitions;
+	},
+
+	getSymbols: 'getSymbolDefinitions',
+
+	getSelectedItems: function() {
+		var selectionItems = this._selectionItems,
+			items = [];
+		for (var id in selectionItems) {
+			var item = selectionItems[id],
+				selection = item._selection;
+			if (selection & 1 && item.isInserted()) {
+				items.push(item);
+			} else if (!selection) {
+				this._updateSelection(item);
+			}
+		}
+		return items;
+	},
+
+	_updateSelection: function(item) {
+		var id = item._id,
+			selectionItems = this._selectionItems;
+		if (item._selection) {
+			if (selectionItems[id] !== item) {
+				this._selectionCount++;
+				selectionItems[id] = item;
+			}
+		} else if (selectionItems[id] === item) {
+			this._selectionCount--;
+			delete selectionItems[id];
+		}
+	},
+
+	selectAll: function() {
+		var children = this._children;
+		for (var i = 0, l = children.length; i < l; i++)
+			children[i].setFullySelected(true);
+	},
+
+	deselectAll: function() {
+		var selectionItems = this._selectionItems;
+		for (var i in selectionItems)
+			selectionItems[i].setFullySelected(false);
+	},
+
+	addLayer: function(layer) {
+		return this.insertLayer(undefined, layer);
+	},
+
+	insertLayer: function(index, layer) {
+		if (layer instanceof Layer) {
+			layer._remove(false, true);
+			Base.splice(this._children, [layer], index, 0);
+			layer._setProject(this, true);
+			var name = layer._name;
+			if (name)
+				layer.setName(name);
+			if (this._changes)
+				layer._changed(5);
+			if (!this._activeLayer)
+				this._activeLayer = layer;
+		} else {
+			layer = null;
+		}
+		return layer;
+	},
+
+	_insertItem: function(index, item, _preserve, _created) {
+		item = this.insertLayer(index, item)
+				|| (this._activeLayer || this._insertItem(undefined,
+						new Layer(Item.NO_INSERT), true, true))
+						.insertChild(index, item, _preserve);
+		if (_created && item.activate)
+			item.activate();
+		return item;
+	},
+
+	getItems: function(options) {
+		return Item._getItems(this, options);
+	},
+
+	getItem: function(options) {
+		return Item._getItems(this, options, null, null, true)[0] || null;
+	},
+
+	importJSON: function(json) {
+		this.activate();
+		var layer = this._activeLayer;
+		return Base.importJSON(json, layer && layer.isEmpty() && layer);
+	},
+
+	removeOn: function(type) {
+		var sets = this._removeSets;
+		if (sets) {
+			if (type === 'mouseup')
+				sets.mousedrag = null;
+			var set = sets[type];
+			if (set) {
+				for (var id in set) {
+					var item = set[id];
+					for (var key in sets) {
+						var other = sets[key];
+						if (other && other != set)
+							delete other[item._id];
+					}
+					item.remove();
+				}
+				sets[type] = null;
+			}
+		}
+	},
+
+	draw: function(ctx, matrix, pixelRatio) {
+		this._updateVersion++;
+		ctx.save();
+		matrix.applyToContext(ctx);
+		var children = this._children,
+			param = new Base({
+				offset: new Point(0, 0),
+				pixelRatio: pixelRatio,
+				viewMatrix: matrix.isIdentity() ? null : matrix,
+				matrices: [new Matrix()],
+				updateMatrix: true
+			});
+		for (var i = 0, l = children.length; i < l; i++) {
+			children[i].draw(ctx, param);
+		}
+		ctx.restore();
+
+		if (this._selectionCount > 0) {
+			ctx.save();
+			ctx.strokeWidth = 1;
+			var items = this._selectionItems,
+				size = this._scope.settings.handleSize,
+				version = this._updateVersion;
+			for (var id in items) {
+				items[id]._drawSelection(ctx, matrix, size, items, version);
+			}
+			ctx.restore();
+		}
+	}
+});
+
+var Item = Base.extend(Emitter, {
+	statics: {
+		extend: function extend(src) {
+			if (src._serializeFields)
+				src._serializeFields = Base.set({},
+					this.prototype._serializeFields, src._serializeFields);
+			return extend.base.apply(this, arguments);
+		},
+
+		NO_INSERT: { insert: false }
+	},
+
+	_class: 'Item',
+	_name: null,
+	_applyMatrix: true,
+	_canApplyMatrix: true,
+	_canScaleStroke: false,
+	_pivot: null,
+	_visible: true,
+	_blendMode: 'normal',
+	_opacity: 1,
+	_locked: false,
+	_guide: false,
+	_clipMask: false,
+	_selection: 0,
+	_selectBounds: true,
+	_selectChildren: false,
+	_serializeFields: {
+		name: null,
+		applyMatrix: null,
+		matrix: new Matrix(),
+		pivot: null,
+		visible: true,
+		blendMode: 'normal',
+		opacity: 1,
+		locked: false,
+		guide: false,
+		clipMask: false,
+		selected: false,
+		data: {}
+	}
+},
+new function() {
+	var handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
+			'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];
+	return Base.each(handlers,
+		function(name) {
+			this._events[name] = {
+				install: function(type) {
+					this.getView()._countItemEvent(type, 1);
+				},
+
+				uninstall: function(type) {
+					this.getView()._countItemEvent(type, -1);
+				}
+			};
+		}, {
+			_events: {
+				onFrame: {
+					install: function() {
+						this.getView()._animateItem(this, true);
+					},
+
+					uninstall: function() {
+						this.getView()._animateItem(this, false);
+					}
+				},
+
+				onLoad: {},
+				onError: {}
+			},
+			statics: {
+				_itemHandlers: handlers
+			}
+		}
+	);
+}, {
+	initialize: function Item() {
+	},
+
+	_initialize: function(props, point) {
+		var hasProps = props && Base.isPlainObject(props),
+			internal = hasProps && props.internal === true,
+			matrix = this._matrix = new Matrix(),
+			project = hasProps && props.project || paper.project,
+			settings = paper.settings;
+		this._id = internal ? null : UID.get();
+		this._parent = this._index = null;
+		this._applyMatrix = this._canApplyMatrix && settings.applyMatrix;
+		if (point)
+			matrix.translate(point);
+		matrix._owner = this;
+		this._style = new Style(project._currentStyle, this, project);
+		if (internal || hasProps && props.insert === false
+			|| !settings.insertItems && !(hasProps && props.insert === true)) {
+			this._setProject(project);
+		} else {
+			(hasProps && props.parent || project)
+					._insertItem(undefined, this, true, true);
+		}
+		if (hasProps && props !== Item.NO_INSERT) {
+			Base.filter(this, props, {
+				internal: true, insert: true, project: true, parent: true
+			});
+		}
+		return hasProps;
+	},
+
+	_serialize: function(options, dictionary) {
+		var props = {},
+			that = this;
+
+		function serialize(fields) {
+			for (var key in fields) {
+				var value = that[key];
+				if (!Base.equals(value, key === 'leading'
+						? fields.fontSize * 1.2 : fields[key])) {
+					props[key] = Base.serialize(value, options,
+							key !== 'data', dictionary);
+				}
+			}
+		}
+
+		serialize(this._serializeFields);
+		if (!(this instanceof Group))
+			serialize(this._style._defaults);
+		return [ this._class, props ];
+	},
+
+	_changed: function(flags) {
+		var symbol = this._symbol,
+			cacheParent = this._parent || symbol,
+			project = this._project;
+		if (flags & 8) {
+			this._bounds = this._position = this._decomposed =
+					this._globalMatrix = undefined;
+		}
+		if (cacheParent
+				&& (flags & 40)) {
+			Item._clearBoundsCache(cacheParent);
+		}
+		if (flags & 2) {
+			Item._clearBoundsCache(this);
+		}
+		if (project)
+			project._changed(flags, this);
+		if (symbol)
+			symbol._changed(flags);
+	},
+
+	set: function(props) {
+		if (props)
+			this._set(props);
+		return this;
+	},
+
+	getId: function() {
+		return this._id;
+	},
+
+	getName: function() {
+		return this._name;
+	},
+
+	setName: function(name) {
+
+		if (this._name)
+			this._removeNamed();
+		if (name === (+name) + '')
+			throw new Error(
+					'Names consisting only of numbers are not supported.');
+		var owner = this._getOwner();
+		if (name && owner) {
+			var children = owner._children,
+				namedChildren = owner._namedChildren;
+			(namedChildren[name] = namedChildren[name] || []).push(this);
+			if (!(name in children))
+				children[name] = this;
+		}
+		this._name = name || undefined;
+		this._changed(128);
+	},
+
+	getStyle: function() {
+		return this._style;
+	},
+
+	setStyle: function(style) {
+		this.getStyle().set(style);
+	}
+}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],
+	function(name) {
+		var part = Base.capitalize(name),
+			name = '_' + name;
+		this['get' + part] = function() {
+			return this[name];
+		};
+		this['set' + part] = function(value) {
+			if (value != this[name]) {
+				this[name] = value;
+				this._changed(name === '_locked'
+						? 128 : 129);
+			}
+		};
+	},
+{}), {
+	beans: true,
+
+	getSelection: function() {
+		return this._selection;
+	},
+
+	setSelection: function(selection) {
+		if (selection !== this._selection) {
+			this._selection = selection;
+			var project = this._project;
+			if (project) {
+				project._updateSelection(this);
+				this._changed(129);
+			}
+		}
+	},
+
+	changeSelection: function(flag, selected) {
+		var selection = this._selection;
+		this.setSelection(selected ? selection | flag : selection & ~flag);
+	},
+
+	isSelected: function() {
+		if (this._selectChildren) {
+			var children = this._children;
+			for (var i = 0, l = children.length; i < l; i++)
+				if (children[i].isSelected())
+					return true;
+		}
+		return !!(this._selection & 1);
+	},
+
+	setSelected: function(selected) {
+		if (this._selectChildren) {
+			var children = this._children;
+			for (var i = 0, l = children.length; i < l; i++)
+				children[i].setSelected(selected);
+		}
+		this.changeSelection(1, selected);
+	},
+
+	isFullySelected: function() {
+		var children = this._children,
+			selected = !!(this._selection & 1);
+		if (children && selected) {
+			for (var i = 0, l = children.length; i < l; i++)
+				if (!children[i].isFullySelected())
+					return false;
+			return true;
+		}
+		return selected;
+	},
+
+	setFullySelected: function(selected) {
+		var children = this._children;
+		if (children) {
+			for (var i = 0, l = children.length; i < l; i++)
+				children[i].setFullySelected(selected);
+		}
+		this.changeSelection(1, selected);
+	},
+
+	isClipMask: function() {
+		return this._clipMask;
+	},
+
+	setClipMask: function(clipMask) {
+		if (this._clipMask != (clipMask = !!clipMask)) {
+			this._clipMask = clipMask;
+			if (clipMask) {
+				this.setFillColor(null);
+				this.setStrokeColor(null);
+			}
+			this._changed(129);
+			if (this._parent)
+				this._parent._changed(1024);
+		}
+	},
+
+	getData: function() {
+		if (!this._data)
+			this._data = {};
+		return this._data;
+	},
+
+	setData: function(data) {
+		this._data = data;
+	},
+
+	getPosition: function(_dontLink) {
+		var position = this._position,
+			ctor = _dontLink ? Point : LinkedPoint;
+		if (!position) {
+			var pivot = this._pivot;
+			position = this._position = pivot
+					? this._matrix._transformPoint(pivot)
+					: this.getBounds().getCenter(true);
+		}
+		return new ctor(position.x, position.y, this, 'setPosition');
+	},
+
+	setPosition: function() {
+		this.translate(Point.read(arguments).subtract(this.getPosition(true)));
+	},
+
+	getPivot: function(_dontLink) {
+		var pivot = this._pivot;
+		if (pivot) {
+			var ctor = _dontLink ? Point : LinkedPoint;
+			pivot = new ctor(pivot.x, pivot.y, this, 'setPivot');
+		}
+		return pivot;
+	},
+
+	setPivot: function() {
+		this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
+		this._position = undefined;
+	}
+}, Base.each({
+		getStrokeBounds: { stroke: true },
+		getHandleBounds: { handle: true },
+		getInternalBounds: { internal: true }
+	},
+	function(options, key) {
+		this[key] = function(matrix) {
+			return this.getBounds(matrix, options);
+		};
+	},
+{
+	beans: true,
+
+	getBounds: function(matrix, options) {
+		var hasMatrix = options || matrix instanceof Matrix,
+			opts = Base.set({}, hasMatrix ? options : matrix,
+					this._boundsOptions);
+		if (!opts.stroke || this.getStrokeScaling())
+			opts.cacheItem = this;
+		var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
+		return arguments.length === 0
+				? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
+						bounds.height, this, 'setBounds')
+				: bounds;
+	},
+
+	setBounds: function() {
+		var rect = Rectangle.read(arguments),
+			bounds = this.getBounds(),
+			_matrix = this._matrix,
+			matrix = new Matrix(),
+			center = rect.getCenter();
+		matrix.translate(center);
+		if (rect.width != bounds.width || rect.height != bounds.height) {
+			if (!_matrix.isInvertible()) {
+				_matrix.initialize(_matrix._backup
+						|| new Matrix().translate(_matrix.getTranslation()));
+				bounds = this.getBounds();
+			}
+			matrix.scale(
+					bounds.width !== 0 ? rect.width / bounds.width : 0,
+					bounds.height !== 0 ? rect.height / bounds.height : 0);
+		}
+		center = bounds.getCenter();
+		matrix.translate(-center.x, -center.y);
+		this.transform(matrix);
+	},
+
+	_getBounds: function(matrix, options) {
+		var children = this._children;
+		if (!children || children.length === 0)
+			return new Rectangle();
+		Item._updateBoundsCache(this, options.cacheItem);
+		return Item._getBounds(children, matrix, options);
+	},
+
+	_getCachedBounds: function(matrix, options) {
+		matrix = matrix && matrix._orNullIfIdentity();
+		var internal = options.internal,
+			cacheItem = options.cacheItem,
+			_matrix = internal ? null : this._matrix._orNullIfIdentity(),
+			cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
+				options.stroke ? 1 : 0,
+				options.handle ? 1 : 0,
+				internal ? 1 : 0
+			].join('');
+		Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
+		if (cacheKey && this._bounds && cacheKey in this._bounds)
+			return this._bounds[cacheKey].rect.clone();
+		var bounds = this._getBounds(matrix || _matrix, options);
+		if (cacheKey) {
+			if (!this._bounds)
+				this._bounds = {};
+			var cached = this._bounds[cacheKey] = {
+				rect: bounds.clone(),
+				internal: options.internal
+			};
+		}
+		return bounds;
+	},
+
+	_getStrokeMatrix: function(matrix, options) {
+		var parent = this.getStrokeScaling() ? null
+				: options && options.internal ? this
+					: this._parent || this._symbol && this._symbol._item,
+			mx = parent ? parent.getViewMatrix().invert() : matrix;
+		return mx && mx._shiftless();
+	},
+
+	statics: {
+		_updateBoundsCache: function(parent, item) {
+			if (parent && item) {
+				var id = item._id,
+					ref = parent._boundsCache = parent._boundsCache || {
+						ids: {},
+						list: []
+					};
+				if (!ref.ids[id]) {
+					ref.list.push(item);
+					ref.ids[id] = item;
+				}
+			}
+		},
+
+		_clearBoundsCache: function(item) {
+			var cache = item._boundsCache;
+			if (cache) {
+				item._bounds = item._position = item._boundsCache = undefined;
+				for (var i = 0, list = cache.list, l = list.length; i < l; i++){
+					var other = list[i];
+					if (other !== item) {
+						other._bounds = other._position = undefined;
+						if (other._boundsCache)
+							Item._clearBoundsCache(other);
+					}
+				}
+			}
+		},
+
+		_getBounds: function(items, matrix, options) {
+			var x1 = Infinity,
+				x2 = -x1,
+				y1 = x1,
+				y2 = x2;
+			options = options || {};
+			for (var i = 0, l = items.length; i < l; i++) {
+				var item = items[i];
+				if (item._visible && !item.isEmpty()) {
+					var rect = item._getCachedBounds(
+						matrix && matrix.appended(item._matrix), options);
+					x1 = Math.min(rect.x, x1);
+					y1 = Math.min(rect.y, y1);
+					x2 = Math.max(rect.x + rect.width, x2);
+					y2 = Math.max(rect.y + rect.height, y2);
+				}
+			}
+			return isFinite(x1)
+					? new Rectangle(x1, y1, x2 - x1, y2 - y1)
+					: new Rectangle();
+		}
+	}
+
+}), {
+	beans: true,
+
+	_decompose: function() {
+		return this._decomposed || (this._decomposed = this._matrix.decompose());
+	},
+
+	getRotation: function() {
+		var decomposed = this._decompose();
+		return decomposed && decomposed.rotation;
+	},
+
+	setRotation: function(rotation) {
+		var current = this.getRotation();
+		if (current != null && rotation != null) {
+			this.rotate(rotation - current);
+		}
+	},
+
+	getScaling: function(_dontLink) {
+		var decomposed = this._decompose(),
+			scaling = decomposed && decomposed.scaling,
+			ctor = _dontLink ? Point : LinkedPoint;
+		return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling');
+	},
+
+	setScaling: function() {
+		var current = this.getScaling(),
+			scaling = Point.read(arguments, 0, { clone: true, readNull: true });
+		if (current && scaling) {
+			this.scale(scaling.x / current.x, scaling.y / current.y);
+		}
+	},
+
+	getMatrix: function() {
+		return this._matrix;
+	},
+
+	setMatrix: function() {
+		var matrix = this._matrix;
+		matrix.initialize.apply(matrix, arguments);
+	},
+
+	getGlobalMatrix: function(_dontClone) {
+		var matrix = this._globalMatrix,
+			updateVersion = this._project._updateVersion;
+		if (matrix && matrix._updateVersion !== updateVersion)
+			matrix = null;
+		if (!matrix) {
+			matrix = this._globalMatrix = this._matrix.clone();
+			var parent = this._parent;
+			if (parent)
+				matrix.prepend(parent.getGlobalMatrix(true));
+			matrix._updateVersion = updateVersion;
+		}
+		return _dontClone ? matrix : matrix.clone();
+	},
+
+	getViewMatrix: function() {
+		return this.getGlobalMatrix().prepend(this.getView()._matrix);
+	},
+
+	getApplyMatrix: function() {
+		return this._applyMatrix;
+	},
+
+	setApplyMatrix: function(apply) {
+		if (this._applyMatrix = this._canApplyMatrix && !!apply)
+			this.transform(null, true);
+	},
+
+	getTransformContent: '#getApplyMatrix',
+	setTransformContent: '#setApplyMatrix',
+}, {
+	getProject: function() {
+		return this._project;
+	},
+
+	_setProject: function(project, installEvents) {
+		if (this._project !== project) {
+			if (this._project)
+				this._installEvents(false);
+			this._project = project;
+			var children = this._children;
+			for (var i = 0, l = children && children.length; i < l; i++)
+				children[i]._setProject(project);
+			installEvents = true;
+		}
+		if (installEvents)
+			this._installEvents(true);
+	},
+
+	getView: function() {
+		return this._project._view;
+	},
+
+	_installEvents: function _installEvents(install) {
+		_installEvents.base.call(this, install);
+		var children = this._children;
+		for (var i = 0, l = children && children.length; i < l; i++)
+			children[i]._installEvents(install);
+	},
+
+	getLayer: function() {
+		var parent = this;
+		while (parent = parent._parent) {
+			if (parent instanceof Layer)
+				return parent;
+		}
+		return null;
+	},
+
+	getParent: function() {
+		return this._parent;
+	},
+
+	setParent: function(item) {
+		return item.addChild(this);
+	},
+
+	_getOwner: '#getParent',
+
+	getChildren: function() {
+		return this._children;
+	},
+
+	setChildren: function(items, _preserve) {
+		this.removeChildren();
+		this.addChildren(items, _preserve);
+	},
+
+	getFirstChild: function() {
+		return this._children && this._children[0] || null;
+	},
+
+	getLastChild: function() {
+		return this._children && this._children[this._children.length - 1]
+				|| null;
+	},
+
+	getNextSibling: function() {
+		var owner = this._getOwner();
+		return owner && owner._children[this._index + 1] || null;
+	},
+
+	getPreviousSibling: function() {
+		var owner = this._getOwner();
+		return owner && owner._children[this._index - 1] || null;
+	},
+
+	getIndex: function() {
+		return this._index;
+	},
+
+	equals: function(item) {
+		return item === this || item && this._class === item._class
+				&& this._style.equals(item._style)
+				&& this._matrix.equals(item._matrix)
+				&& this._locked === item._locked
+				&& this._visible === item._visible
+				&& this._blendMode === item._blendMode
+				&& this._opacity === item._opacity
+				&& this._clipMask === item._clipMask
+				&& this._guide === item._guide
+				&& this._equals(item)
+				|| false;
+	},
+
+	_equals: function(item) {
+		return Base.equals(this._children, item._children);
+	},
+
+	clone: function(options) {
+		var copy = new this.constructor(Item.NO_INSERT),
+			children = this._children,
+			insert = Base.pick(options ? options.insert : undefined,
+					options === undefined || options === true),
+			deep = Base.pick(options ? options.deep : undefined, true);
+		if (children)
+			copy.copyAttributes(this);
+		if (!children || deep)
+			copy.copyContent(this);
+		if (!children)
+			copy.copyAttributes(this);
+		if (insert)
+			copy.insertAbove(this);
+		var name = this._name,
+			parent = this._parent;
+		if (name && parent) {
+			var children = parent._children,
+				orig = name,
+				i = 1;
+			while (children[name])
+				name = orig + ' ' + (i++);
+			if (name !== orig)
+				copy.setName(name);
+		}
+		return copy;
+	},
+
+	copyContent: function(source) {
+		var children = source._children;
+		for (var i = 0, l = children && children.length; i < l; i++) {
+			this.addChild(children[i].clone(false), true);
+		}
+	},
+
+	copyAttributes: function(source, excludeMatrix) {
+		this.setStyle(source._style);
+		var keys = ['_locked', '_visible', '_blendMode', '_opacity',
+				'_clipMask', '_guide'];
+		for (var i = 0, l = keys.length; i < l; i++) {
+			var key = keys[i];
+			if (source.hasOwnProperty(key))
+				this[key] = source[key];
+		}
+		if (!excludeMatrix)
+			this._matrix.initialize(source._matrix);
+		this.setApplyMatrix(source._applyMatrix);
+		this.setPivot(source._pivot);
+		this.setSelection(source._selection);
+		var data = source._data,
+			name = source._name;
+		this._data = data ? Base.clone(data) : null;
+		if (name)
+			this.setName(name);
+	},
+
+	rasterize: function(resolution, insert) {
+		var bounds = this.getStrokeBounds(),
+			scale = (resolution || this.getView().getResolution()) / 72,
+			topLeft = bounds.getTopLeft().floor(),
+			bottomRight = bounds.getBottomRight().ceil(),
+			size = new Size(bottomRight.subtract(topLeft)),
+			raster = new Raster(Item.NO_INSERT);
+		if (!size.isZero()) {
+			var canvas = CanvasProvider.getCanvas(size.multiply(scale)),
+				ctx = canvas.getContext('2d'),
+				matrix = new Matrix().scale(scale).translate(topLeft.negate());
+			ctx.save();
+			matrix.applyToContext(ctx);
+			this.draw(ctx, new Base({ matrices: [matrix] }));
+			ctx.restore();
+			raster.setCanvas(canvas);
+		}
+		raster.transform(new Matrix().translate(topLeft.add(size.divide(2)))
+				.scale(1 / scale));
+		if (insert === undefined || insert)
+			raster.insertAbove(this);
+		return raster;
+	},
+
+	contains: function() {
+		return !!this._contains(
+				this._matrix._inverseTransform(Point.read(arguments)));
+	},
+
+	_contains: function(point) {
+		var children = this._children;
+		if (children) {
+			for (var i = children.length - 1; i >= 0; i--) {
+				if (children[i].contains(point))
+					return true;
+			}
+			return false;
+		}
+		return point.isInside(this.getInternalBounds());
+	},
+
+	isInside: function() {
+		return Rectangle.read(arguments).contains(this.getBounds());
+	},
+
+	_asPathItem: function() {
+		return new Path.Rectangle({
+			rectangle: this.getInternalBounds(),
+			matrix: this._matrix,
+			insert: false,
+		});
+	},
+
+	intersects: function(item, _matrix) {
+		if (!(item instanceof Item))
+			return false;
+		return this._asPathItem().getIntersections(item._asPathItem(), null,
+				_matrix, true).length > 0;
+	}
+},
+new function() {
+	function hitTest() {
+		return this._hitTest(
+				Point.read(arguments),
+				HitResult.getOptions(arguments));
+	}
+
+	function hitTestAll() {
+		var point = Point.read(arguments),
+			options = HitResult.getOptions(arguments),
+			callback = options.match,
+			results = [];
+		options = Base.set({}, options, {
+			match: function(hit) {
+				if (!callback || callback(hit))
+					results.push(hit);
+			}
+		});
+		this._hitTest(point, options);
+		return results;
+	}
+
+	function hitTestChildren(point, options, viewMatrix, _exclude) {
+		var children = this._children;
+		if (children) {
+			for (var i = children.length - 1; i >= 0; i--) {
+				var child = children[i];
+				var res = child !== _exclude && child._hitTest(point, options,
+						viewMatrix);
+				if (res)
+					return res;
+			}
+		}
+		return null;
+	}
+
+	Project.inject({
+		hitTest: hitTest,
+		hitTestAll: hitTestAll,
+		_hitTest: hitTestChildren
+	});
+
+	return {
+		hitTest: hitTest,
+		hitTestAll: hitTestAll,
+		_hitTestChildren: hitTestChildren,
+	};
+}, {
+
+	_hitTest: function(point, options, parentViewMatrix) {
+		if (this._locked || !this._visible || this._guide && !options.guides
+				|| this.isEmpty()) {
+			return null;
+		}
+
+		var matrix = this._matrix,
+			viewMatrix = parentViewMatrix
+					? parentViewMatrix.appended(matrix)
+					: this.getGlobalMatrix().prepend(this.getView()._matrix),
+			strokeMatrix = this.getStrokeScaling()
+					? null
+					: viewMatrix.inverted()._shiftless(),
+			tolerance = Math.max(options.tolerance, 1e-6),
+			tolerancePadding = options._tolerancePadding = new Size(
+					Path._getStrokePadding(tolerance, strokeMatrix));
+		point = matrix._inverseTransform(point);
+		if (!point || !this._children &&
+			!this.getBounds({ internal: true, stroke: true, handle: true })
+				.expand(tolerancePadding.multiply(2))._containsPoint(point)) {
+			return null;
+		}
+
+		var checkSelf = !(options.guides && !this._guide
+				|| options.selected && !this.isSelected()
+				|| options.type && options.type !== Base.hyphenate(this._class)
+				|| options.class && !(this instanceof options.class)),
+			callback = options.match,
+			that = this,
+			bounds,
+			res;
+
+		function match(hit) {
+			return !callback || hit && callback(hit) ? hit : null;
+		}
+
+		function checkBounds(type, part) {
+			var pt = bounds['get' + part]();
+			if (point.subtract(pt).divide(tolerancePadding).length <= 1) {
+				return new HitResult(type, that,
+						{ name: Base.hyphenate(part), point: pt });
+			}
+		}
+
+		if (checkSelf && (options.center || options.bounds) && this._parent) {
+			bounds = this.getInternalBounds();
+			if (options.center) {
+				res = checkBounds('center', 'Center');
+			}
+			if (!res && options.bounds) {
+				var points = [
+					'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
+					'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'
+				];
+				for (var i = 0; i < 8 && !res; i++) {
+					res = checkBounds('bounds', points[i]);
+				}
+			}
+			res = match(res);
+		}
+
+		if (!res) {
+			res = this._hitTestChildren(point, options, viewMatrix)
+				|| checkSelf
+					&& match(this._hitTestSelf(point, options, viewMatrix,
+						strokeMatrix))
+				|| null;
+		}
+		if (res && res.point) {
+			res.point = matrix.transform(res.point);
+		}
+		return res;
+	},
+
+	_hitTestSelf: function(point, options) {
+		if (options.fill && this.hasFill() && this._contains(point))
+			return new HitResult('fill', this);
+	},
+
+	matches: function(name, compare) {
+		function matchObject(obj1, obj2) {
+			for (var i in obj1) {
+				if (obj1.hasOwnProperty(i)) {
+					var val1 = obj1[i],
+						val2 = obj2[i];
+					if (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {
+						if (!matchObject(val1, val2))
+							return false;
+					} else if (!Base.equals(val1, val2)) {
+						return false;
+					}
+				}
+			}
+			return true;
+		}
+		var type = typeof name;
+		if (type === 'object') {
+			for (var key in name) {
+				if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
+					return false;
+			}
+			return true;
+		} else if (type === 'function') {
+			return name(this);
+		} else if (name === 'match') {
+			return compare(this);
+		} else {
+			var value = /^(empty|editable)$/.test(name)
+					? this['is' + Base.capitalize(name)]()
+					: name === 'type'
+						? Base.hyphenate(this._class)
+						: this[name];
+			if (name === 'class') {
+				if (typeof compare === 'function')
+					return this instanceof compare;
+				value = this._class;
+			}
+			if (typeof compare === 'function') {
+				return !!compare(value);
+			} else if (compare) {
+				if (compare.test) {
+					return compare.test(value);
+				} else if (Base.isPlainObject(compare)) {
+					return matchObject(compare, value);
+				}
+			}
+			return Base.equals(value, compare);
+		}
+	},
+
+	getItems: function(options) {
+		return Item._getItems(this, options, this._matrix);
+	},
+
+	getItem: function(options) {
+		return Item._getItems(this, options, this._matrix, null, true)[0]
+				|| null;
+	},
+
+	statics: {
+		_getItems: function _getItems(item, options, matrix, param, firstOnly) {
+			if (!param) {
+				var obj = typeof options === 'object' && options,
+					overlapping = obj && obj.overlapping,
+					inside = obj && obj.inside,
+					bounds = overlapping || inside,
+					rect = bounds && Rectangle.read([bounds]);
+				param = {
+					items: [],
+					recursive: obj && obj.recursive !== false,
+					inside: !!inside,
+					overlapping: !!overlapping,
+					rect: rect,
+					path: overlapping && new Path.Rectangle({
+						rectangle: rect,
+						insert: false
+					})
+				};
+				if (obj) {
+					options = Base.filter({}, options, {
+						recursive: true, inside: true, overlapping: true
+					});
+				}
+			}
+			var children = item._children,
+				items = param.items,
+				rect = param.rect;
+			matrix = rect && (matrix || new Matrix());
+			for (var i = 0, l = children && children.length; i < l; i++) {
+				var child = children[i],
+					childMatrix = matrix && matrix.appended(child._matrix),
+					add = true;
+				if (rect) {
+					var bounds = child.getBounds(childMatrix);
+					if (!rect.intersects(bounds))
+						continue;
+					if (!(rect.contains(bounds)
+							|| param.overlapping && (bounds.contains(rect)
+								|| param.path.intersects(child, childMatrix))))
+						add = false;
+				}
+				if (add && child.matches(options)) {
+					items.push(child);
+					if (firstOnly)
+						break;
+				}
+				if (param.recursive !== false) {
+					_getItems(child, options, childMatrix, param, firstOnly);
+				}
+				if (firstOnly && items.length > 0)
+					break;
+			}
+			return items;
+		}
+	}
+}, {
+
+	importJSON: function(json) {
+		var res = Base.importJSON(json, this);
+		return res !== this ? this.addChild(res) : res;
+	},
+
+	addChild: function(item, _preserve) {
+		return this.insertChild(undefined, item, _preserve);
+	},
+
+	insertChild: function(index, item, _preserve) {
+		var res = item ? this.insertChildren(index, [item], _preserve) : null;
+		return res && res[0];
+	},
+
+	addChildren: function(items, _preserve) {
+		return this.insertChildren(this._children.length, items, _preserve);
+	},
+
+	insertChildren: function(index, items, _preserve, _proto) {
+		var children = this._children;
+		if (children && items && items.length > 0) {
+			items = Array.prototype.slice.apply(items);
+			for (var i = items.length - 1; i >= 0; i--) {
+				var item = items[i];
+				if (!item || _proto && !(item instanceof _proto)) {
+					items.splice(i, 1);
+				} else {
+					item._remove(false, true);
+				}
+			}
+			Base.splice(children, items, index, 0);
+			var project = this._project,
+				notifySelf = project._changes;
+			for (var i = 0, l = items.length; i < l; i++) {
+				var item = items[i],
+					name = item._name;
+				item._parent = this;
+				item._setProject(project, true);
+				if (name)
+					item.setName(name);
+				if (notifySelf)
+					this._changed(5);
+			}
+			this._changed(11);
+		} else {
+			items = null;
+		}
+		return items;
+	},
+
+	_insertItem: '#insertChild',
+
+	_insertAt: function(item, offset, _preserve) {
+		var res = this;
+		if (res !== item) {
+			var owner = item && item._getOwner();
+			if (owner) {
+				res._remove(false, true);
+				owner._insertItem(item._index + offset, res, _preserve);
+			} else {
+				res = null;
+			}
+		}
+		return res;
+	},
+
+	insertAbove: function(item, _preserve) {
+		return this._insertAt(item, 1, _preserve);
+	},
+
+	insertBelow: function(item, _preserve) {
+		return this._insertAt(item, 0, _preserve);
+	},
+
+	sendToBack: function() {
+		var owner = this._getOwner();
+		return owner ? owner._insertItem(0, this) : null;
+	},
+
+	bringToFront: function() {
+		var owner = this._getOwner();
+		return owner ? owner._insertItem(undefined, this) : null;
+	},
+
+	appendTop: '#addChild',
+
+	appendBottom: function(item) {
+		return this.insertChild(0, item);
+	},
+
+	moveAbove: '#insertAbove',
+
+	moveBelow: '#insertBelow',
+
+	copyTo: function(owner) {
+		return owner._insertItem(undefined, this.clone(false));
+	},
+
+	reduce: function(options) {
+		var children = this._children;
+		if (children && children.length === 1) {
+			var child = children[0].reduce(options);
+			if (this._parent) {
+				child.insertAbove(this);
+				this.remove();
+			} else {
+				child.remove();
+			}
+			return child;
+		}
+		return this;
+	},
+
+	_removeNamed: function() {
+		var owner = this._getOwner();
+		if (owner) {
+			var children = owner._children,
+				namedChildren = owner._namedChildren,
+				name = this._name,
+				namedArray = namedChildren[name],
+				index = namedArray ? namedArray.indexOf(this) : -1;
+			if (index !== -1) {
+				if (children[name] == this)
+					delete children[name];
+				namedArray.splice(index, 1);
+				if (namedArray.length) {
+					children[name] = namedArray[0];
+				} else {
+					delete namedChildren[name];
+				}
+			}
+		}
+	},
+
+	_remove: function(notifySelf, notifyParent) {
+		var owner = this._getOwner(),
+			project = this._project,
+			index = this._index;
+		if (owner) {
+			if (index != null) {
+				if (project._activeLayer === this)
+					project._activeLayer = this.getNextSibling()
+							|| this.getPreviousSibling();
+				Base.splice(owner._children, null, index, 1);
+			}
+			if (this._name)
+				this._removeNamed();
+			this._installEvents(false);
+			if (notifySelf && project._changes)
+				this._changed(5);
+			if (notifyParent)
+				owner._changed(11, this);
+			this._parent = null;
+			return true;
+		}
+		return false;
+	},
+
+	remove: function() {
+		return this._remove(true, true);
+	},
+
+	replaceWith: function(item) {
+		var ok = item && item.insertBelow(this);
+		if (ok)
+			this.remove();
+		return ok;
+	},
+
+	removeChildren: function(start, end) {
+		if (!this._children)
+			return null;
+		start = start || 0;
+		end = Base.pick(end, this._children.length);
+		var removed = Base.splice(this._children, null, start, end - start);
+		for (var i = removed.length - 1; i >= 0; i--) {
+			removed[i]._remove(true, false);
+		}
+		if (removed.length > 0)
+			this._changed(11);
+		return removed;
+	},
+
+	clear: '#removeChildren',
+
+	reverseChildren: function() {
+		if (this._children) {
+			this._children.reverse();
+			for (var i = 0, l = this._children.length; i < l; i++)
+				this._children[i]._index = i;
+			this._changed(11);
+		}
+	},
+
+	isEmpty: function() {
+		return !this._children || this._children.length === 0;
+	},
+
+	isEditable: function() {
+		var item = this;
+		while (item) {
+			if (!item._visible || item._locked)
+				return false;
+			item = item._parent;
+		}
+		return true;
+	},
+
+	hasFill: function() {
+		return this.getStyle().hasFill();
+	},
+
+	hasStroke: function() {
+		return this.getStyle().hasStroke();
+	},
+
+	hasShadow: function() {
+		return this.getStyle().hasShadow();
+	},
+
+	_getOrder: function(item) {
+		function getList(item) {
+			var list = [];
+			do {
+				list.unshift(item);
+			} while (item = item._parent);
+			return list;
+		}
+		var list1 = getList(this),
+			list2 = getList(item);
+		for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {
+			if (list1[i] != list2[i]) {
+				return list1[i]._index < list2[i]._index ? 1 : -1;
+			}
+		}
+		return 0;
+	},
+
+	hasChildren: function() {
+		return this._children && this._children.length > 0;
+	},
+
+	isInserted: function() {
+		return this._parent ? this._parent.isInserted() : false;
+	},
+
+	isAbove: function(item) {
+		return this._getOrder(item) === -1;
+	},
+
+	isBelow: function(item) {
+		return this._getOrder(item) === 1;
+	},
+
+	isParent: function(item) {
+		return this._parent === item;
+	},
+
+	isChild: function(item) {
+		return item && item._parent === this;
+	},
+
+	isDescendant: function(item) {
+		var parent = this;
+		while (parent = parent._parent) {
+			if (parent === item)
+				return true;
+		}
+		return false;
+	},
+
+	isAncestor: function(item) {
+		return item ? item.isDescendant(this) : false;
+	},
+
+	isSibling: function(item) {
+		return this._parent === item._parent;
+	},
+
+	isGroupedWith: function(item) {
+		var parent = this._parent;
+		while (parent) {
+			if (parent._parent
+				&& /^(Group|Layer|CompoundPath)$/.test(parent._class)
+				&& item.isDescendant(parent))
+					return true;
+			parent = parent._parent;
+		}
+		return false;
+	},
+
+}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
+	var rotate = key === 'rotate';
+	this[key] = function() {
+		var value = (rotate ? Base : Point).read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		return this.transform(new Matrix()[key](value,
+				center || this.getPosition(true)));
+	};
+}, {
+	translate: function() {
+		var mx = new Matrix();
+		return this.transform(mx.translate.apply(mx, arguments));
+	},
+
+	transform: function(matrix, _applyMatrix, _applyRecursively,
+			_setApplyMatrix) {
+		if (matrix && matrix.isIdentity())
+			matrix = null;
+		var _matrix = this._matrix,
+			applyMatrix = (_applyMatrix || this._applyMatrix)
+					&& ((!_matrix.isIdentity() || matrix)
+						|| _applyMatrix && _applyRecursively && this._children);
+		if (!matrix && !applyMatrix)
+			return this;
+		if (matrix) {
+			if (!matrix.isInvertible() && _matrix.isInvertible())
+				_matrix._backup = _matrix.getValues();
+			_matrix.prepend(matrix);
+		}
+		if (applyMatrix = applyMatrix && this._transformContent(_matrix,
+					_applyRecursively, _setApplyMatrix)) {
+			var pivot = this._pivot,
+				style = this._style,
+				fillColor = style.getFillColor(true),
+				strokeColor = style.getStrokeColor(true);
+			if (pivot)
+				_matrix._transformPoint(pivot, pivot, true);
+			if (fillColor)
+				fillColor.transform(_matrix);
+			if (strokeColor)
+				strokeColor.transform(_matrix);
+			_matrix.reset(true);
+			if (_setApplyMatrix && this._canApplyMatrix)
+				this._applyMatrix = true;
+		}
+		var bounds = this._bounds,
+			position = this._position;
+		this._changed(9);
+		var decomp = bounds && matrix && matrix.decompose();
+		if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
+			for (var key in bounds) {
+				var cache = bounds[key];
+				if (applyMatrix || !cache.internal) {
+					var rect = cache.rect;
+					matrix._transformBounds(rect, rect);
+				}
+			}
+			var getter = this._boundsGetter,
+				rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
+			if (rect)
+				this._position = rect.getCenter(true);
+			this._bounds = bounds;
+		} else if (matrix && position) {
+			this._position = matrix._transformPoint(position, position);
+		}
+		return this;
+	},
+
+	_transformContent: function(matrix, applyRecursively, setApplyMatrix) {
+		var children = this._children;
+		if (children) {
+			for (var i = 0, l = children.length; i < l; i++)
+				children[i].transform(matrix, true, applyRecursively,
+						setApplyMatrix);
+			return true;
+		}
+	},
+
+	globalToLocal: function() {
+		return this.getGlobalMatrix(true)._inverseTransform(
+				Point.read(arguments));
+	},
+
+	localToGlobal: function() {
+		return this.getGlobalMatrix(true)._transformPoint(
+				Point.read(arguments));
+	},
+
+	parentToLocal: function() {
+		return this._matrix._inverseTransform(Point.read(arguments));
+	},
+
+	localToParent: function() {
+		return this._matrix._transformPoint(Point.read(arguments));
+	},
+
+	fitBounds: function(rectangle, fill) {
+		rectangle = Rectangle.read(arguments);
+		var bounds = this.getBounds(),
+			itemRatio = bounds.height / bounds.width,
+			rectRatio = rectangle.height / rectangle.width,
+			scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
+					? rectangle.width / bounds.width
+					: rectangle.height / bounds.height,
+			newBounds = new Rectangle(new Point(),
+					new Size(bounds.width * scale, bounds.height * scale));
+		newBounds.setCenter(rectangle.getCenter());
+		this.setBounds(newBounds);
+	}
+}), {
+
+	_setStyles: function(ctx, param, viewMatrix) {
+		var style = this._style;
+		if (style.hasFill()) {
+			ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx);
+		}
+		if (style.hasStroke()) {
+			ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx);
+			ctx.lineWidth = style.getStrokeWidth();
+			var strokeJoin = style.getStrokeJoin(),
+				strokeCap = style.getStrokeCap(),
+				miterLimit = style.getMiterLimit();
+			if (strokeJoin)
+				ctx.lineJoin = strokeJoin;
+			if (strokeCap)
+				ctx.lineCap = strokeCap;
+			if (miterLimit)
+				ctx.miterLimit = miterLimit;
+			if (paper.support.nativeDash) {
+				var dashArray = style.getDashArray(),
+					dashOffset = style.getDashOffset();
+				if (dashArray && dashArray.length) {
+					if ('setLineDash' in ctx) {
+						ctx.setLineDash(dashArray);
+						ctx.lineDashOffset = dashOffset;
+					} else {
+						ctx.mozDash = dashArray;
+						ctx.mozDashOffset = dashOffset;
+					}
+				}
+			}
+		}
+		if (style.hasShadow()) {
+			var pixelRatio = param.pixelRatio || 1,
+				mx = viewMatrix._shiftless().prepend(
+					new Matrix().scale(pixelRatio, pixelRatio)),
+				blur = mx.transform(new Point(style.getShadowBlur(), 0)),
+				offset = mx.transform(this.getShadowOffset());
+			ctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);
+			ctx.shadowBlur = blur.getLength();
+			ctx.shadowOffsetX = offset.x;
+			ctx.shadowOffsetY = offset.y;
+		}
+	},
+
+	draw: function(ctx, param, parentStrokeMatrix) {
+		var updateVersion = this._updateVersion = this._project._updateVersion;
+		if (!this._visible || this._opacity === 0)
+			return;
+		var matrices = param.matrices,
+			viewMatrix = param.viewMatrix,
+			matrix = this._matrix,
+			globalMatrix = matrices[matrices.length - 1].appended(matrix);
+		if (!globalMatrix.isInvertible())
+			return;
+
+		viewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)
+				: globalMatrix;
+
+		matrices.push(globalMatrix);
+		if (param.updateMatrix) {
+			globalMatrix._updateVersion = updateVersion;
+			this._globalMatrix = globalMatrix;
+		}
+
+		var blendMode = this._blendMode,
+			opacity = this._opacity,
+			normalBlend = blendMode === 'normal',
+			nativeBlend = BlendMode.nativeModes[blendMode],
+			direct = normalBlend && opacity === 1
+					|| param.dontStart
+					|| param.clip
+					|| (nativeBlend || normalBlend && opacity < 1)
+						&& this._canComposite(),
+			pixelRatio = param.pixelRatio || 1,
+			mainCtx, itemOffset, prevOffset;
+		if (!direct) {
+			var bounds = this.getStrokeBounds(viewMatrix);
+			if (!bounds.width || !bounds.height)
+				return;
+			prevOffset = param.offset;
+			itemOffset = param.offset = bounds.getTopLeft().floor();
+			mainCtx = ctx;
+			ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)
+					.multiply(pixelRatio));
+			if (pixelRatio !== 1)
+				ctx.scale(pixelRatio, pixelRatio);
+		}
+		ctx.save();
+		var strokeMatrix = parentStrokeMatrix
+				? parentStrokeMatrix.appended(matrix)
+				: this._canScaleStroke && !this.getStrokeScaling(true)
+					&& viewMatrix,
+			clip = !direct && param.clipItem,
+			transform = !strokeMatrix || clip;
+		if (direct) {
+			ctx.globalAlpha = opacity;
+			if (nativeBlend)
+				ctx.globalCompositeOperation = blendMode;
+		} else if (transform) {
+			ctx.translate(-itemOffset.x, -itemOffset.y);
+		}
+		if (transform) {
+			(direct ? matrix : viewMatrix).applyToContext(ctx);
+		}
+		if (clip) {
+			param.clipItem.draw(ctx, param.extend({ clip: true }));
+		}
+		if (strokeMatrix) {
+			ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
+			var offset = param.offset;
+			if (offset)
+				ctx.translate(-offset.x, -offset.y);
+		}
+		this._draw(ctx, param, viewMatrix, strokeMatrix);
+		ctx.restore();
+		matrices.pop();
+		if (param.clip && !param.dontFinish)
+			ctx.clip();
+		if (!direct) {
+			BlendMode.process(blendMode, ctx, mainCtx, opacity,
+					itemOffset.subtract(prevOffset).multiply(pixelRatio));
+			CanvasProvider.release(ctx);
+			param.offset = prevOffset;
+		}
+	},
+
+	_isUpdated: function(updateVersion) {
+		var parent = this._parent;
+		if (parent instanceof CompoundPath)
+			return parent._isUpdated(updateVersion);
+		var updated = this._updateVersion === updateVersion;
+		if (!updated && parent && parent._visible
+				&& parent._isUpdated(updateVersion)) {
+			this._updateVersion = updateVersion;
+			updated = true;
+		}
+		return updated;
+	},
+
+	_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {
+		var selection = this._selection,
+			itemSelected = selection & 1,
+			boundsSelected = selection & 2
+					|| itemSelected && this._selectBounds,
+			positionSelected = selection & 4;
+		if (!this._drawSelected)
+			itemSelected = false;
+		if ((itemSelected || boundsSelected || positionSelected)
+				&& this._isUpdated(updateVersion)) {
+			var layer,
+				color = this.getSelectedColor(true) || (layer = this.getLayer())
+					&& layer.getSelectedColor(true),
+				mx = matrix.appended(this.getGlobalMatrix(true)),
+				half = size / 2;
+			ctx.strokeStyle = ctx.fillStyle = color
+					? color.toCanvasStyle(ctx) : '#009dec';
+			if (itemSelected)
+				this._drawSelected(ctx, mx, selectionItems);
+			if (positionSelected) {
+				var point = this.getPosition(true),
+					x = point.x,
+					y = point.y;
+				ctx.beginPath();
+				ctx.arc(x, y, half, 0, Math.PI * 2, true);
+				ctx.stroke();
+				var deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],
+					start = half,
+					end = size + 1;
+				for (var i = 0; i < 4; i++) {
+					var delta = deltas[i],
+						dx = delta[0],
+						dy = delta[1];
+					ctx.moveTo(x + dx * start, y + dy * start);
+					ctx.lineTo(x + dx * end, y + dy * end);
+					ctx.stroke();
+				}
+			}
+			if (boundsSelected) {
+				var coords = mx._transformCorners(this.getInternalBounds());
+				ctx.beginPath();
+				for (var i = 0; i < 8; i++) {
+					ctx[i === 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);
+				}
+				ctx.closePath();
+				ctx.stroke();
+				for (var i = 0; i < 8; i++) {
+					ctx.fillRect(coords[i] - half, coords[++i] - half,
+							size, size);
+				}
+			}
+		}
+	},
+
+	_canComposite: function() {
+		return false;
+	}
+}, Base.each(['down', 'drag', 'up', 'move'], function(key) {
+	this['removeOn' + Base.capitalize(key)] = function() {
+		var hash = {};
+		hash[key] = true;
+		return this.removeOn(hash);
+	};
+}, {
+
+	removeOn: function(obj) {
+		for (var name in obj) {
+			if (obj[name]) {
+				var key = 'mouse' + name,
+					project = this._project,
+					sets = project._removeSets = project._removeSets || {};
+				sets[key] = sets[key] || {};
+				sets[key][this._id] = this;
+			}
+		}
+		return this;
+	}
+}));
+
+var Group = Item.extend({
+	_class: 'Group',
+	_selectBounds: false,
+	_selectChildren: true,
+	_serializeFields: {
+		children: []
+	},
+
+	initialize: function Group(arg) {
+		this._children = [];
+		this._namedChildren = {};
+		if (!this._initialize(arg))
+			this.addChildren(Array.isArray(arg) ? arg : arguments);
+	},
+
+	_changed: function _changed(flags) {
+		_changed.base.call(this, flags);
+		if (flags & 1026) {
+			this._clipItem = undefined;
+		}
+	},
+
+	_getClipItem: function() {
+		var clipItem = this._clipItem;
+		if (clipItem === undefined) {
+			clipItem = null;
+			var children = this._children;
+			for (var i = 0, l = children.length; i < l; i++) {
+				if (children[i]._clipMask) {
+					clipItem = children[i];
+					break;
+				}
+			}
+			this._clipItem = clipItem;
+		}
+		return clipItem;
+	},
+
+	isClipped: function() {
+		return !!this._getClipItem();
+	},
+
+	setClipped: function(clipped) {
+		var child = this.getFirstChild();
+		if (child)
+			child.setClipMask(clipped);
+	},
+
+	_getBounds: function _getBounds(matrix, options) {
+		var clipItem = this._getClipItem();
+		return clipItem
+			? clipItem._getCachedBounds(
+				matrix && matrix.appended(clipItem._matrix),
+				Base.set({}, options, { stroke: false }))
+			: _getBounds.base.call(this, matrix, options);
+	},
+
+	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
+		var clipItem = this._getClipItem();
+		return (!clipItem || clipItem.contains(point))
+				&& _hitTestChildren.base.call(this, point, options, viewMatrix,
+					clipItem);
+	},
+
+	_draw: function(ctx, param) {
+		var clip = param.clip,
+			clipItem = !clip && this._getClipItem();
+		param = param.extend({ clipItem: clipItem, clip: false });
+		if (clip) {
+			ctx.beginPath();
+			param.dontStart = param.dontFinish = true;
+		} else if (clipItem) {
+			clipItem.draw(ctx, param.extend({ clip: true }));
+		}
+		var children = this._children;
+		for (var i = 0, l = children.length; i < l; i++) {
+			var item = children[i];
+			if (item !== clipItem)
+				item.draw(ctx, param);
+		}
+	}
+});
+
+var Layer = Group.extend({
+	_class: 'Layer',
+
+	initialize: function Layer() {
+		Group.apply(this, arguments);
+	},
+
+	_getOwner: function() {
+		return this._parent || this._index != null && this._project;
+	},
+
+	isInserted: function isInserted() {
+		return this._parent ? isInserted.base.call(this) : this._index != null;
+	},
+
+	activate: function() {
+		this._project._activeLayer = this;
+	},
+
+	_hitTestSelf: function() {
+	}
+});
+
+var Shape = Item.extend({
+	_class: 'Shape',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_canScaleStroke: true,
+	_serializeFields: {
+		type: null,
+		size: null,
+		radius: null
+	},
+
+	initialize: function Shape(props) {
+		this._initialize(props);
+	},
+
+	_equals: function(item) {
+		return this._type === item._type
+			&& this._size.equals(item._size)
+			&& Base.equals(this._radius, item._radius);
+	},
+
+	copyContent: function(source) {
+		this.setType(source._type);
+		this.setSize(source._size);
+		this.setRadius(source._radius);
+	},
+
+	getType: function() {
+		return this._type;
+	},
+
+	setType: function(type) {
+		this._type = type;
+	},
+
+	getShape: '#getType',
+	setShape: '#setType',
+
+	getSize: function() {
+		var size = this._size;
+		return new LinkedSize(size.width, size.height, this, 'setSize');
+	},
+
+	setSize: function() {
+		var size = Size.read(arguments);
+		if (!this._size) {
+			this._size = size.clone();
+		} else if (!this._size.equals(size)) {
+			var type = this._type,
+				width = size.width,
+				height = size.height;
+			if (type === 'rectangle') {
+				var radius = Size.min(this._radius, size.divide(2));
+				this._radius.set(radius.width, radius.height);
+			} else if (type === 'circle') {
+				width = height = (width + height) / 2;
+				this._radius = width / 2;
+			} else if (type === 'ellipse') {
+				this._radius.set(width / 2, height / 2);
+			}
+			this._size.set(width, height);
+			this._changed(9);
+		}
+	},
+
+	getRadius: function() {
+		var rad = this._radius;
+		return this._type === 'circle'
+				? rad
+				: new LinkedSize(rad.width, rad.height, this, 'setRadius');
+	},
+
+	setRadius: function(radius) {
+		var type = this._type;
+		if (type === 'circle') {
+			if (radius === this._radius)
+				return;
+			var size = radius * 2;
+			this._radius = radius;
+			this._size.set(size, size);
+		} else {
+			radius = Size.read(arguments);
+			if (!this._radius) {
+				this._radius = radius.clone();
+			} else {
+				if (this._radius.equals(radius))
+					return;
+				this._radius.set(radius.width, radius.height);
+				if (type === 'rectangle') {
+					var size = Size.max(this._size, radius.multiply(2));
+					this._size.set(size.width, size.height);
+				} else if (type === 'ellipse') {
+					this._size.set(radius.width * 2, radius.height * 2);
+				}
+			}
+		}
+		this._changed(9);
+	},
+
+	isEmpty: function() {
+		return false;
+	},
+
+	toPath: function(insert) {
+		var path = new Path[Base.capitalize(this._type)]({
+			center: new Point(),
+			size: this._size,
+			radius: this._radius,
+			insert: false
+		});
+		path.copyAttributes(this);
+		if (paper.settings.applyMatrix)
+			path.setApplyMatrix(true);
+		if (insert === undefined || insert)
+			path.insertAbove(this);
+		return path;
+	},
+
+	toShape: '#clone',
+
+	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
+		var style = this._style,
+			hasFill = style.hasFill(),
+			hasStroke = style.hasStroke(),
+			dontPaint = param.dontFinish || param.clip,
+			untransformed = !strokeMatrix;
+		if (hasFill || hasStroke || dontPaint) {
+			var type = this._type,
+				radius = this._radius,
+				isCircle = type === 'circle';
+			if (!param.dontStart)
+				ctx.beginPath();
+			if (untransformed && isCircle) {
+				ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
+			} else {
+				var rx = isCircle ? radius : radius.width,
+					ry = isCircle ? radius : radius.height,
+					size = this._size,
+					width = size.width,
+					height = size.height;
+				if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
+					ctx.rect(-width / 2, -height / 2, width, height);
+				} else {
+					var x = width / 2,
+						y = height / 2,
+						kappa = 1 - 0.5522847498307936,
+						cx = rx * kappa,
+						cy = ry * kappa,
+						c = [
+							-x, -y + ry,
+							-x, -y + cy,
+							-x + cx, -y,
+							-x + rx, -y,
+							x - rx, -y,
+							x - cx, -y,
+							x, -y + cy,
+							x, -y + ry,
+							x, y - ry,
+							x, y - cy,
+							x - cx, y,
+							x - rx, y,
+							-x + rx, y,
+							-x + cx, y,
+							-x, y - cy,
+							-x, y - ry
+						];
+					if (strokeMatrix)
+						strokeMatrix.transform(c, c, 32);
+					ctx.moveTo(c[0], c[1]);
+					ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);
+					if (x !== rx)
+						ctx.lineTo(c[8], c[9]);
+					ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);
+					if (y !== ry)
+						ctx.lineTo(c[16], c[17]);
+					ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);
+					if (x !== rx)
+						ctx.lineTo(c[24], c[25]);
+					ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);
+				}
+			}
+			ctx.closePath();
+		}
+		if (!dontPaint && (hasFill || hasStroke)) {
+			this._setStyles(ctx, param, viewMatrix);
+			if (hasFill) {
+				ctx.fill(style.getFillRule());
+				ctx.shadowColor = 'rgba(0,0,0,0)';
+			}
+			if (hasStroke)
+				ctx.stroke();
+		}
+	},
+
+	_canComposite: function() {
+		return !(this.hasFill() && this.hasStroke());
+	},
+
+	_getBounds: function(matrix, options) {
+		var rect = new Rectangle(this._size).setCenter(0, 0),
+			style = this._style,
+			strokeWidth = options.stroke && style.hasStroke()
+					&& style.getStrokeWidth();
+		if (matrix)
+			rect = matrix._transformBounds(rect);
+		return strokeWidth
+				? rect.expand(Path._getStrokePadding(strokeWidth,
+					this._getStrokeMatrix(matrix, options)))
+				: rect;
+	}
+},
+new function() {
+	function getCornerCenter(that, point, expand) {
+		var radius = that._radius;
+		if (!radius.isZero()) {
+			var halfSize = that._size.divide(2);
+			for (var i = 0; i < 4; i++) {
+				var dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),
+					corner = dir.multiply(halfSize),
+					center = corner.subtract(dir.multiply(radius)),
+					rect = new Rectangle(corner, center);
+				if ((expand ? rect.expand(expand) : rect).contains(point))
+					return center;
+			}
+		}
+	}
+
+	function isOnEllipseStroke(point, radius, padding, quadrant) {
+		var vector = point.divide(radius);
+		return (!quadrant || vector.quadrant === quadrant) &&
+				vector.subtract(vector.normalize()).multiply(radius)
+					.divide(padding).length <= 1;
+	}
+
+	return {
+		_contains: function _contains(point) {
+			if (this._type === 'rectangle') {
+				var center = getCornerCenter(this, point);
+				return center
+						? point.subtract(center).divide(this._radius)
+							.getLength() <= 1
+						: _contains.base.call(this, point);
+			} else {
+				return point.divide(this.size).getLength() <= 0.5;
+			}
+		},
+
+		_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,
+				strokeMatrix) {
+			var hit = false,
+				style = this._style,
+				hitStroke = options.stroke && style.hasStroke(),
+				hitFill = options.fill && style.hasFill();
+			if (hitStroke || hitFill) {
+				var type = this._type,
+					radius = this._radius,
+					strokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,
+					strokePadding = options._tolerancePadding.add(
+						Path._getStrokePadding(strokeRadius,
+							!style.getStrokeScaling() && strokeMatrix));
+				if (type === 'rectangle') {
+					var padding = strokePadding.multiply(2),
+						center = getCornerCenter(this, point, padding);
+					if (center) {
+						hit = isOnEllipseStroke(point.subtract(center), radius,
+								strokePadding, center.getQuadrant());
+					} else {
+						var rect = new Rectangle(this._size).setCenter(0, 0),
+							outer = rect.expand(padding),
+							inner = rect.expand(padding.negate());
+						hit = outer._containsPoint(point)
+								&& !inner._containsPoint(point);
+					}
+				} else {
+					hit = isOnEllipseStroke(point, radius, strokePadding);
+				}
+			}
+			return hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)
+					: _hitTestSelf.base.apply(this, arguments);
+		}
+	};
+}, {
+
+statics: new function() {
+	function createShape(type, point, size, radius, args) {
+		var item = new Shape(Base.getNamed(args));
+		item._type = type;
+		item._size = size;
+		item._radius = radius;
+		return item.translate(point);
+	}
+
+	return {
+		Circle: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				radius = Base.readNamed(arguments, 'radius');
+			return createShape('circle', center, new Size(radius * 2), radius,
+					arguments);
+		},
+
+		Rectangle: function() {
+			var rect = Rectangle.readNamed(arguments, 'rectangle'),
+				radius = Size.min(Size.readNamed(arguments, 'radius'),
+						rect.getSize(true).divide(2));
+			return createShape('rectangle', rect.getCenter(true),
+					rect.getSize(true), radius, arguments);
+		},
+
+		Ellipse: function() {
+			var ellipse = Shape._readEllipse(arguments),
+				radius = ellipse.radius;
+			return createShape('ellipse', ellipse.center, radius.multiply(2),
+					radius, arguments);
+		},
+
+		_readEllipse: function(args) {
+			var center,
+				radius;
+			if (Base.hasNamed(args, 'radius')) {
+				center = Point.readNamed(args, 'center');
+				radius = Size.readNamed(args, 'radius');
+			} else {
+				var rect = Rectangle.readNamed(args, 'rectangle');
+				center = rect.getCenter(true);
+				radius = rect.getSize(true).divide(2);
+			}
+			return { center: center, radius: radius };
+		}
+	};
+}});
+
+var Raster = Item.extend({
+	_class: 'Raster',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_boundsOptions: { stroke: false, handle: false },
+	_serializeFields: {
+		crossOrigin: null,
+		source: null
+	},
+
+	initialize: function Raster(object, position) {
+		if (!this._initialize(object,
+				position !== undefined && Point.read(arguments, 1))) {
+			var image = typeof object === 'string'
+					? document.getElementById(object) : object;
+			if (image) {
+				this.setImage(image);
+			} else {
+				this.setSource(object);
+			}
+		}
+		if (!this._size) {
+			this._size = new Size();
+			this._loaded = false;
+		}
+	},
+
+	_equals: function(item) {
+		return this.getSource() === item.getSource();
+	},
+
+	copyContent: function(source) {
+		var image = source._image,
+			canvas = source._canvas;
+		if (image) {
+			this._setImage(image);
+		} else if (canvas) {
+			var copyCanvas = CanvasProvider.getCanvas(source._size);
+			copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
+			this._setImage(copyCanvas);
+		}
+		this._crossOrigin = source._crossOrigin;
+	},
+
+	getSize: function() {
+		var size = this._size;
+		return new LinkedSize(size ? size.width : 0, size ? size.height : 0,
+				this, 'setSize');
+	},
+
+	setSize: function() {
+		var size = Size.read(arguments);
+		if (!size.equals(this._size)) {
+			if (size.width > 0 && size.height > 0) {
+				var element = this.getElement();
+				this._setImage(CanvasProvider.getCanvas(size));
+				if (element)
+					this.getContext(true).drawImage(element, 0, 0,
+							size.width, size.height);
+			} else {
+				if (this._canvas)
+					CanvasProvider.release(this._canvas);
+				this._size = size.clone();
+			}
+		}
+	},
+
+	getWidth: function() {
+		return this._size ? this._size.width : 0;
+	},
+
+	setWidth: function(width) {
+		this.setSize(width, this.getHeight());
+	},
+
+	getHeight: function() {
+		return this._size ? this._size.height : 0;
+	},
+
+	setHeight: function(height) {
+		this.setSize(this.getWidth(), height);
+	},
+
+	getLoaded: function() {
+		return this._loaded;
+	},
+
+	isEmpty: function() {
+		var size = this._size;
+		return !size || size.width === 0 && size.height === 0;
+	},
+
+	getResolution: function() {
+		var matrix = this._matrix,
+			orig = new Point(0, 0).transform(matrix),
+			u = new Point(1, 0).transform(matrix).subtract(orig),
+			v = new Point(0, 1).transform(matrix).subtract(orig);
+		return new Size(
+			72 / u.getLength(),
+			72 / v.getLength()
+		);
+	},
+
+	getPpi: '#getResolution',
+
+	getImage: function() {
+		return this._image;
+	},
+
+	setImage: function(image) {
+		var that = this;
+
+		function emit(event) {
+			var view = that.getView(),
+				type = event && event.type || 'load';
+			if (view && that.responds(type)) {
+				paper = view._scope;
+				that.emit(type, new Event(event));
+			}
+		}
+
+		this._setImage(image);
+		if (this._loaded) {
+			setTimeout(emit, 0);
+		} else if (image) {
+			DomEvent.add(image, {
+				load: function(event) {
+					that._setImage(image);
+					emit(event);
+				},
+				error: emit
+			});
+		}
+	},
+
+	_setImage: function(image) {
+		if (this._canvas)
+			CanvasProvider.release(this._canvas);
+		if (image && image.getContext) {
+			this._image = null;
+			this._canvas = image;
+			this._loaded = true;
+		} else {
+			this._image = image;
+			this._canvas = null;
+			this._loaded = !!(image && image.src && image.complete);
+		}
+		this._size = new Size(
+				image ? image.naturalWidth || image.width : 0,
+				image ? image.naturalHeight || image.height : 0);
+		this._context = null;
+		this._changed(521);
+	},
+
+	getCanvas: function() {
+		if (!this._canvas) {
+			var ctx = CanvasProvider.getContext(this._size);
+			try {
+				if (this._image)
+					ctx.drawImage(this._image, 0, 0);
+				this._canvas = ctx.canvas;
+			} catch (e) {
+				CanvasProvider.release(ctx);
+			}
+		}
+		return this._canvas;
+	},
+
+	setCanvas: '#setImage',
+
+	getContext: function(modify) {
+		if (!this._context)
+			this._context = this.getCanvas().getContext('2d');
+		if (modify) {
+			this._image = null;
+			this._changed(513);
+		}
+		return this._context;
+	},
+
+	setContext: function(context) {
+		this._context = context;
+	},
+
+	getSource: function() {
+		var image = this._image;
+		return image && image.src || this.toDataURL();
+	},
+
+	setSource: function(src) {
+		var image = new window.Image(),
+			crossOrigin = this._crossOrigin;
+		if (crossOrigin)
+			image.crossOrigin = crossOrigin;
+		image.src = src;
+		this.setImage(image);
+	},
+
+	getCrossOrigin: function() {
+		var image = this._image;
+		return image && image.crossOrigin || this._crossOrigin || '';
+	},
+
+	setCrossOrigin: function(crossOrigin) {
+		this._crossOrigin = crossOrigin;
+		var image = this._image;
+		if (image)
+			image.crossOrigin = crossOrigin;
+	},
+
+	getElement: function() {
+		return this._canvas || this._loaded && this._image;
+	}
+}, {
+	beans: false,
+
+	getSubCanvas: function() {
+		var rect = Rectangle.read(arguments),
+			ctx = CanvasProvider.getContext(rect.getSize());
+		ctx.drawImage(this.getCanvas(), rect.x, rect.y,
+				rect.width, rect.height, 0, 0, rect.width, rect.height);
+		return ctx.canvas;
+	},
+
+	getSubRaster: function() {
+		var rect = Rectangle.read(arguments),
+			raster = new Raster(Item.NO_INSERT);
+		raster._setImage(this.getSubCanvas(rect));
+		raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
+		raster._matrix.prepend(this._matrix);
+		raster.insertAbove(this);
+		return raster;
+	},
+
+	toDataURL: function() {
+		var image = this._image,
+			src = image && image.src;
+		if (/^data:/.test(src))
+			return src;
+		var canvas = this.getCanvas();
+		return canvas ? canvas.toDataURL.apply(canvas, arguments) : null;
+	},
+
+	drawImage: function(image ) {
+		var point = Point.read(arguments, 1);
+		this.getContext(true).drawImage(image, point.x, point.y);
+	},
+
+	getAverageColor: function(object) {
+		var bounds, path;
+		if (!object) {
+			bounds = this.getBounds();
+		} else if (object instanceof PathItem) {
+			path = object;
+			bounds = object.getBounds();
+		} else if (typeof object === 'object') {
+			if ('width' in object) {
+				bounds = new Rectangle(object);
+			} else if ('x' in object) {
+				bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
+			}
+		}
+		if (!bounds)
+			return null;
+		var sampleSize = 32,
+			width = Math.min(bounds.width, sampleSize),
+			height = Math.min(bounds.height, sampleSize);
+		var ctx = Raster._sampleContext;
+		if (!ctx) {
+			ctx = Raster._sampleContext = CanvasProvider.getContext(
+					new Size(sampleSize));
+		} else {
+			ctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);
+		}
+		ctx.save();
+		var matrix = new Matrix()
+				.scale(width / bounds.width, height / bounds.height)
+				.translate(-bounds.x, -bounds.y);
+		matrix.applyToContext(ctx);
+		if (path)
+			path.draw(ctx, new Base({ clip: true, matrices: [matrix] }));
+		this._matrix.applyToContext(ctx);
+		var element = this.getElement(),
+			size = this._size;
+		if (element)
+			ctx.drawImage(element, -size.width / 2, -size.height / 2);
+		ctx.restore();
+		var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),
+				Math.ceil(height)).data,
+			channels = [0, 0, 0],
+			total = 0;
+		for (var i = 0, l = pixels.length; i < l; i += 4) {
+			var alpha = pixels[i + 3];
+			total += alpha;
+			alpha /= 255;
+			channels[0] += pixels[i] * alpha;
+			channels[1] += pixels[i + 1] * alpha;
+			channels[2] += pixels[i + 2] * alpha;
+		}
+		for (var i = 0; i < 3; i++)
+			channels[i] /= total;
+		return total ? Color.read(channels) : null;
+	},
+
+	getPixel: function() {
+		var point = Point.read(arguments);
+		var data = this.getContext().getImageData(point.x, point.y, 1, 1).data;
+		return new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],
+				data[3] / 255);
+	},
+
+	setPixel: function() {
+		var point = Point.read(arguments),
+			color = Color.read(arguments),
+			components = color._convert('rgb'),
+			alpha = color._alpha,
+			ctx = this.getContext(true),
+			imageData = ctx.createImageData(1, 1),
+			data = imageData.data;
+		data[0] = components[0] * 255;
+		data[1] = components[1] * 255;
+		data[2] = components[2] * 255;
+		data[3] = alpha != null ? alpha * 255 : 255;
+		ctx.putImageData(imageData, point.x, point.y);
+	},
+
+	createImageData: function() {
+		var size = Size.read(arguments);
+		return this.getContext().createImageData(size.width, size.height);
+	},
+
+	getImageData: function() {
+		var rect = Rectangle.read(arguments);
+		if (rect.isEmpty())
+			rect = new Rectangle(this._size);
+		return this.getContext().getImageData(rect.x, rect.y,
+				rect.width, rect.height);
+	},
+
+	setImageData: function(data ) {
+		var point = Point.read(arguments, 1);
+		this.getContext(true).putImageData(data, point.x, point.y);
+	},
+
+	_getBounds: function(matrix, options) {
+		var rect = new Rectangle(this._size).setCenter(0, 0);
+		return matrix ? matrix._transformBounds(rect) : rect;
+	},
+
+	_hitTestSelf: function(point) {
+		if (this._contains(point)) {
+			var that = this;
+			return new HitResult('pixel', that, {
+				offset: point.add(that._size.divide(2)).round(),
+				color: {
+					get: function() {
+						return that.getPixel(this.offset);
+					}
+				}
+			});
+		}
+	},
+
+	_draw: function(ctx) {
+		var element = this.getElement();
+		if (element) {
+			ctx.globalAlpha = this._opacity;
+			ctx.drawImage(element,
+					-this._size.width / 2, -this._size.height / 2);
+		}
+	},
+
+	_canComposite: function() {
+		return true;
+	}
+});
+
+var SymbolItem = Item.extend({
+	_class: 'SymbolItem',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_boundsOptions: { stroke: true },
+	_serializeFields: {
+		symbol: null
+	},
+
+	initialize: function SymbolItem(arg0, arg1) {
+		if (!this._initialize(arg0,
+				arg1 !== undefined && Point.read(arguments, 1)))
+			this.setDefinition(arg0 instanceof SymbolDefinition ?
+					arg0 : new SymbolDefinition(arg0));
+	},
+
+	_equals: function(item) {
+		return this._definition === item._definition;
+	},
+
+	copyContent: function(source) {
+		this.setDefinition(source._definition);
+	},
+
+	getDefinition: function() {
+		return this._definition;
+	},
+
+	setDefinition: function(definition) {
+		this._definition = definition;
+		this._changed(9);
+	},
+
+	getSymbol: '#getDefinition',
+	setSymbol: '#setDefinition',
+
+	isEmpty: function() {
+		return this._definition._item.isEmpty();
+	},
+
+	_getBounds: function(matrix, options) {
+		var item = this._definition._item;
+		return item._getCachedBounds(item._matrix.prepended(matrix), options);
+	},
+
+	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
+		var res = this._definition._item._hitTest(point, options, viewMatrix);
+		if (res)
+			res.item = this;
+		return res;
+	},
+
+	_draw: function(ctx, param) {
+		this._definition._item.draw(ctx, param);
+	}
+
+});
+
+var SymbolDefinition = Base.extend({
+	_class: 'SymbolDefinition',
+
+	initialize: function SymbolDefinition(item, dontCenter) {
+		this._id = UID.get();
+		this.project = paper.project;
+		if (item)
+			this.setItem(item, dontCenter);
+	},
+
+	_serialize: function(options, dictionary) {
+		return dictionary.add(this, function() {
+			return Base.serialize([this._class, this._item],
+					options, false, dictionary);
+		});
+	},
+
+	_changed: function(flags) {
+		if (flags & 8)
+			Item._clearBoundsCache(this);
+		if (flags & 1)
+			this.project._changed(flags);
+	},
+
+	getItem: function() {
+		return this._item;
+	},
+
+	setItem: function(item, _dontCenter) {
+		if (item._symbol)
+			item = item.clone();
+		if (this._item)
+			this._item._symbol = null;
+		this._item = item;
+		item.remove();
+		item.setSelected(false);
+		if (!_dontCenter)
+			item.setPosition(new Point());
+		item._symbol = this;
+		this._changed(9);
+	},
+
+	getDefinition: '#getItem',
+	setDefinition: '#setItem',
+
+	place: function(position) {
+		return new SymbolItem(this, position);
+	},
+
+	clone: function() {
+		return new SymbolDefinition(this._item.clone(false));
+	},
+
+	equals: function(symbol) {
+		return symbol === this
+				|| symbol && this._item.equals(symbol._item)
+				|| false;
+	}
+});
+
+var HitResult = Base.extend({
+	_class: 'HitResult',
+
+	initialize: function HitResult(type, item, values) {
+		this.type = type;
+		this.item = item;
+		if (values) {
+			values.enumerable = true;
+			this.inject(values);
+		}
+	},
+
+	statics: {
+		getOptions: function(args) {
+			var options = args && Base.read(args);
+			return Base.set({
+				type: null,
+				tolerance: paper.settings.hitTolerance,
+				fill: !options,
+				stroke: !options,
+				segments: !options,
+				handles: false,
+				ends: false,
+				center: false,
+				bounds: false,
+				guides: false,
+				selected: false
+			}, options);
+		}
+	}
+});
+
+var Segment = Base.extend({
+	_class: 'Segment',
+	beans: true,
+	_selection: 0,
+
+	initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
+		var count = arguments.length,
+			point, handleIn, handleOut,
+			selection;
+		if (count === 0) {
+		} else if (count === 1) {
+			if (arg0 && 'point' in arg0) {
+				point = arg0.point;
+				handleIn = arg0.handleIn;
+				handleOut = arg0.handleOut;
+				selection = arg0.selection;
+			} else {
+				point = arg0;
+			}
+		} else if (arg0 == null || typeof arg0 === 'object') {
+			point = arg0;
+			handleIn = arg1;
+			handleOut = arg2;
+			selection = arg3;
+		} else {
+			point = arg0 !== undefined ? [ arg0, arg1 ] : null;
+			handleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;
+			handleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;
+		}
+		new SegmentPoint(point, this, '_point');
+		new SegmentPoint(handleIn, this, '_handleIn');
+		new SegmentPoint(handleOut, this, '_handleOut');
+		if (selection)
+			this.setSelection(selection);
+	},
+
+	_serialize: function(options, dictionary) {
+		var point = this._point,
+			selection = this._selection,
+			obj = selection || this.hasHandles()
+					? [point, this._handleIn, this._handleOut]
+					: point;
+		if (selection)
+			obj.push(selection);
+		return Base.serialize(obj, options, true, dictionary);
+	},
+
+	_changed: function(point) {
+		var path = this._path;
+		if (!path)
+			return;
+		var curves = path._curves,
+			index = this._index,
+			curve;
+		if (curves) {
+			if ((!point || point === this._point || point === this._handleIn)
+					&& (curve = index > 0 ? curves[index - 1] : path._closed
+						? curves[curves.length - 1] : null))
+				curve._changed();
+			if ((!point || point === this._point || point === this._handleOut)
+					&& (curve = curves[index]))
+				curve._changed();
+		}
+		path._changed(25);
+	},
+
+	getPoint: function() {
+		return this._point;
+	},
+
+	setPoint: function() {
+		var point = Point.read(arguments);
+		this._point.set(point.x, point.y);
+	},
+
+	getHandleIn: function() {
+		return this._handleIn;
+	},
+
+	setHandleIn: function() {
+		var point = Point.read(arguments);
+		this._handleIn.set(point.x, point.y);
+	},
+
+	getHandleOut: function() {
+		return this._handleOut;
+	},
+
+	setHandleOut: function() {
+		var point = Point.read(arguments);
+		this._handleOut.set(point.x, point.y);
+	},
+
+	hasHandles: function() {
+		return !this._handleIn.isZero() || !this._handleOut.isZero();
+	},
+
+	clearHandles: function() {
+		this._handleIn.set(0, 0);
+		this._handleOut.set(0, 0);
+	},
+
+	getSelection: function() {
+		return this._selection;
+	},
+
+	setSelection: function(selection) {
+		var oldSelection = this._selection,
+			path = this._path;
+		this._selection = selection = selection || 0;
+		if (path && selection !== oldSelection) {
+			path._updateSelection(this, oldSelection, selection);
+			path._changed(129);
+		}
+	},
+
+	changeSelection: function(flag, selected) {
+		var selection = this._selection;
+		this.setSelection(selected ? selection | flag : selection & ~flag);
+	},
+
+	isSelected: function() {
+		return !!(this._selection & 7);
+	},
+
+	setSelected: function(selected) {
+		this.changeSelection(7, selected);
+	},
+
+	getIndex: function() {
+		return this._index !== undefined ? this._index : null;
+	},
+
+	getPath: function() {
+		return this._path || null;
+	},
+
+	getCurve: function() {
+		var path = this._path,
+			index = this._index;
+		if (path) {
+			if (index > 0 && !path._closed
+					&& index === path._segments.length - 1)
+				index--;
+			return path.getCurves()[index] || null;
+		}
+		return null;
+	},
+
+	getLocation: function() {
+		var curve = this.getCurve();
+		return curve
+				? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)
+				: null;
+	},
+
+	getNext: function() {
+		var segments = this._path && this._path._segments;
+		return segments && (segments[this._index + 1]
+				|| this._path._closed && segments[0]) || null;
+	},
+
+	smooth: function(options, _first, _last) {
+		var opts = options || {},
+			type = opts.type,
+			factor = opts.factor,
+			prev = this.getPrevious(),
+			next = this.getNext(),
+			p0 = (prev || this)._point,
+			p1 = this._point,
+			p2 = (next || this)._point,
+			d1 = p0.getDistance(p1),
+			d2 = p1.getDistance(p2);
+		if (!type || type === 'catmull-rom') {
+			var a = factor === undefined ? 0.5 : factor,
+				d1_a = Math.pow(d1, a),
+				d1_2a = d1_a * d1_a,
+				d2_a = Math.pow(d2, a),
+				d2_2a = d2_a * d2_a;
+			if (!_first && prev) {
+				var A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,
+					N = 3 * d2_a * (d2_a + d1_a);
+				this.setHandleIn(N !== 0
+					? new Point(
+						(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,
+						(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)
+					: new Point());
+			}
+			if (!_last && next) {
+				var A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,
+					N = 3 * d1_a * (d1_a + d2_a);
+				this.setHandleOut(N !== 0
+					? new Point(
+						(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,
+						(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)
+					: new Point());
+			}
+		} else if (type === 'geometric') {
+			if (prev && next) {
+				var vector = p0.subtract(p2),
+					t = factor === undefined ? 0.4 : factor,
+					k = t * d1 / (d1 + d2);
+				if (!_first)
+					this.setHandleIn(vector.multiply(k));
+				if (!_last)
+					this.setHandleOut(vector.multiply(k - t));
+			}
+		} else {
+			throw new Error('Smoothing method \'' + type + '\' not supported.');
+		}
+	},
+
+	getPrevious: function() {
+		var segments = this._path && this._path._segments;
+		return segments && (segments[this._index - 1]
+				|| this._path._closed && segments[segments.length - 1]) || null;
+	},
+
+	isFirst: function() {
+		return this._index === 0;
+	},
+
+	isLast: function() {
+		var path = this._path;
+		return path && this._index === path._segments.length - 1 || false;
+	},
+
+	reverse: function() {
+		var handleIn = this._handleIn,
+			handleOut = this._handleOut,
+			inX = handleIn._x,
+			inY = handleIn._y;
+		handleIn.set(handleOut._x, handleOut._y);
+		handleOut.set(inX, inY);
+	},
+
+	reversed: function() {
+		return new Segment(this._point, this._handleOut, this._handleIn);
+	},
+
+	remove: function() {
+		return this._path ? !!this._path.removeSegment(this._index) : false;
+	},
+
+	clone: function() {
+		return new Segment(this._point, this._handleIn, this._handleOut);
+	},
+
+	equals: function(segment) {
+		return segment === this || segment && this._class === segment._class
+				&& this._point.equals(segment._point)
+				&& this._handleIn.equals(segment._handleIn)
+				&& this._handleOut.equals(segment._handleOut)
+				|| false;
+	},
+
+	toString: function() {
+		var parts = [ 'point: ' + this._point ];
+		if (!this._handleIn.isZero())
+			parts.push('handleIn: ' + this._handleIn);
+		if (!this._handleOut.isZero())
+			parts.push('handleOut: ' + this._handleOut);
+		return '{ ' + parts.join(', ') + ' }';
+	},
+
+	transform: function(matrix) {
+		this._transformCoordinates(matrix, new Array(6), true);
+		this._changed();
+	},
+
+	interpolate: function(from, to, factor) {
+		var u = 1 - factor,
+			v = factor,
+			point1 = from._point,
+			point2 = to._point,
+			handleIn1 = from._handleIn,
+			handleIn2 = to._handleIn,
+			handleOut2 = to._handleOut,
+			handleOut1 = from._handleOut;
+		this._point.set(
+				u * point1._x + v * point2._x,
+				u * point1._y + v * point2._y, true);
+		this._handleIn.set(
+				u * handleIn1._x + v * handleIn2._x,
+				u * handleIn1._y + v * handleIn2._y, true);
+		this._handleOut.set(
+				u * handleOut1._x + v * handleOut2._x,
+				u * handleOut1._y + v * handleOut2._y, true);
+		this._changed();
+	},
+
+	_transformCoordinates: function(matrix, coords, change) {
+		var point = this._point,
+			handleIn = !change || !this._handleIn.isZero()
+					? this._handleIn : null,
+			handleOut = !change || !this._handleOut.isZero()
+					? this._handleOut : null,
+			x = point._x,
+			y = point._y,
+			i = 2;
+		coords[0] = x;
+		coords[1] = y;
+		if (handleIn) {
+			coords[i++] = handleIn._x + x;
+			coords[i++] = handleIn._y + y;
+		}
+		if (handleOut) {
+			coords[i++] = handleOut._x + x;
+			coords[i++] = handleOut._y + y;
+		}
+		if (matrix) {
+			matrix._transformCoordinates(coords, coords, i / 2);
+			x = coords[0];
+			y = coords[1];
+			if (change) {
+				point._x = x;
+				point._y = y;
+				i = 2;
+				if (handleIn) {
+					handleIn._x = coords[i++] - x;
+					handleIn._y = coords[i++] - y;
+				}
+				if (handleOut) {
+					handleOut._x = coords[i++] - x;
+					handleOut._y = coords[i++] - y;
+				}
+			} else {
+				if (!handleIn) {
+					coords[i++] = x;
+					coords[i++] = y;
+				}
+				if (!handleOut) {
+					coords[i++] = x;
+					coords[i++] = y;
+				}
+			}
+		}
+		return coords;
+	}
+});
+
+var SegmentPoint = Point.extend({
+	initialize: function SegmentPoint(point, owner, key) {
+		var x, y,
+			selected;
+		if (!point) {
+			x = y = 0;
+		} else if ((x = point[0]) !== undefined) {
+			y = point[1];
+		} else {
+			var pt = point;
+			if ((x = pt.x) === undefined) {
+				pt = Point.read(arguments);
+				x = pt.x;
+			}
+			y = pt.y;
+			selected = pt.selected;
+		}
+		this._x = x;
+		this._y = y;
+		this._owner = owner;
+		owner[key] = this;
+		if (selected)
+			this.setSelected(true);
+	},
+
+	set: function(x, y) {
+		this._x = x;
+		this._y = y;
+		this._owner._changed(this);
+		return this;
+	},
+
+	getX: function() {
+		return this._x;
+	},
+
+	setX: function(x) {
+		this._x = x;
+		this._owner._changed(this);
+	},
+
+	getY: function() {
+		return this._y;
+	},
+
+	setY: function(y) {
+		this._y = y;
+		this._owner._changed(this);
+	},
+
+	isZero: function() {
+		return Numerical.isZero(this._x) && Numerical.isZero(this._y);
+	},
+
+	isSelected: function() {
+		return !!(this._owner._selection & this._getSelection());
+	},
+
+	setSelected: function(selected) {
+		this._owner.changeSelection(this._getSelection(), selected);
+	},
+
+	_getSelection: function() {
+		var owner = this._owner;
+		return this === owner._point ? 1
+			: this === owner._handleIn ? 2
+			: this === owner._handleOut ? 4
+			: 0;
+	}
+});
+
+var Curve = Base.extend({
+	_class: 'Curve',
+
+	initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
+		var count = arguments.length,
+			seg1, seg2,
+			point1, point2,
+			handle1, handle2;
+		if (count === 3) {
+			this._path = arg0;
+			seg1 = arg1;
+			seg2 = arg2;
+		} else if (count === 0) {
+			seg1 = new Segment();
+			seg2 = new Segment();
+		} else if (count === 1) {
+			if ('segment1' in arg0) {
+				seg1 = new Segment(arg0.segment1);
+				seg2 = new Segment(arg0.segment2);
+			} else if ('point1' in arg0) {
+				point1 = arg0.point1;
+				handle1 = arg0.handle1;
+				handle2 = arg0.handle2;
+				point2 = arg0.point2;
+			} else if (Array.isArray(arg0)) {
+				point1 = [arg0[0], arg0[1]];
+				point2 = [arg0[6], arg0[7]];
+				handle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];
+				handle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];
+			}
+		} else if (count === 2) {
+			seg1 = new Segment(arg0);
+			seg2 = new Segment(arg1);
+		} else if (count === 4) {
+			point1 = arg0;
+			handle1 = arg1;
+			handle2 = arg2;
+			point2 = arg3;
+		} else if (count === 8) {
+			point1 = [arg0, arg1];
+			point2 = [arg6, arg7];
+			handle1 = [arg2 - arg0, arg3 - arg1];
+			handle2 = [arg4 - arg6, arg5 - arg7];
+		}
+		this._segment1 = seg1 || new Segment(point1, null, handle1);
+		this._segment2 = seg2 || new Segment(point2, handle2, null);
+	},
+
+	_serialize: function(options, dictionary) {
+		return Base.serialize(this.hasHandles()
+				? [this.getPoint1(), this.getHandle1(), this.getHandle2(),
+					this.getPoint2()]
+				: [this.getPoint1(), this.getPoint2()],
+				options, true, dictionary);
+	},
+
+	_changed: function() {
+		this._length = this._bounds = undefined;
+	},
+
+	clone: function() {
+		return new Curve(this._segment1, this._segment2);
+	},
+
+	toString: function() {
+		var parts = [ 'point1: ' + this._segment1._point ];
+		if (!this._segment1._handleOut.isZero())
+			parts.push('handle1: ' + this._segment1._handleOut);
+		if (!this._segment2._handleIn.isZero())
+			parts.push('handle2: ' + this._segment2._handleIn);
+		parts.push('point2: ' + this._segment2._point);
+		return '{ ' + parts.join(', ') + ' }';
+	},
+
+	remove: function() {
+		var removed = false;
+		if (this._path) {
+			var segment2 = this._segment2,
+				handleOut = segment2._handleOut;
+			removed = segment2.remove();
+			if (removed)
+				this._segment1._handleOut.set(handleOut.x, handleOut.y);
+		}
+		return removed;
+	},
+
+	getPoint1: function() {
+		return this._segment1._point;
+	},
+
+	setPoint1: function() {
+		var point = Point.read(arguments);
+		this._segment1._point.set(point.x, point.y);
+	},
+
+	getPoint2: function() {
+		return this._segment2._point;
+	},
+
+	setPoint2: function() {
+		var point = Point.read(arguments);
+		this._segment2._point.set(point.x, point.y);
+	},
+
+	getHandle1: function() {
+		return this._segment1._handleOut;
+	},
+
+	setHandle1: function() {
+		var point = Point.read(arguments);
+		this._segment1._handleOut.set(point.x, point.y);
+	},
+
+	getHandle2: function() {
+		return this._segment2._handleIn;
+	},
+
+	setHandle2: function() {
+		var point = Point.read(arguments);
+		this._segment2._handleIn.set(point.x, point.y);
+	},
+
+	getSegment1: function() {
+		return this._segment1;
+	},
+
+	getSegment2: function() {
+		return this._segment2;
+	},
+
+	getPath: function() {
+		return this._path;
+	},
+
+	getIndex: function() {
+		return this._segment1._index;
+	},
+
+	getNext: function() {
+		var curves = this._path && this._path._curves;
+		return curves && (curves[this._segment1._index + 1]
+				|| this._path._closed && curves[0]) || null;
+	},
+
+	getPrevious: function() {
+		var curves = this._path && this._path._curves;
+		return curves && (curves[this._segment1._index - 1]
+				|| this._path._closed && curves[curves.length - 1]) || null;
+	},
+
+	isFirst: function() {
+		return this._segment1._index === 0;
+	},
+
+	isLast: function() {
+		var path = this._path;
+		return path && this._segment1._index === path._curves.length - 1
+				|| false;
+	},
+
+	isSelected: function() {
+		return this.getPoint1().isSelected()
+				&& this.getHandle2().isSelected()
+				&& this.getHandle2().isSelected()
+				&& this.getPoint2().isSelected();
+	},
+
+	setSelected: function(selected) {
+		this.getPoint1().setSelected(selected);
+		this.getHandle1().setSelected(selected);
+		this.getHandle2().setSelected(selected);
+		this.getPoint2().setSelected(selected);
+	},
+
+	getValues: function(matrix) {
+		return Curve.getValues(this._segment1, this._segment2, matrix);
+	},
+
+	getPoints: function() {
+		var coords = this.getValues(),
+			points = [];
+		for (var i = 0; i < 8; i += 2)
+			points.push(new Point(coords[i], coords[i + 1]));
+		return points;
+	},
+
+	getLength: function() {
+		if (this._length == null)
+			this._length = Curve.getLength(this.getValues(), 0, 1);
+		return this._length;
+	},
+
+	getArea: function() {
+		return Curve.getArea(this.getValues());
+	},
+
+	getLine: function() {
+		return new Line(this._segment1._point, this._segment2._point);
+	},
+
+	getPart: function(from, to) {
+		return new Curve(Curve.getPart(this.getValues(), from, to));
+	},
+
+	getPartLength: function(from, to) {
+		return Curve.getLength(this.getValues(), from, to);
+	},
+
+	getIntersections: function(curve) {
+		return Curve._getIntersections(this.getValues(),
+				curve && curve !== this ? curve.getValues() : null,
+				this, curve, [], {});
+	},
+
+	divideAt: function(location) {
+		return this.divideAtTime(location && location.curve === this
+				? location.time : location);
+	},
+
+	divideAtTime: function(time, _setHandles) {
+		var tMin = 4e-7,
+			tMax = 1 - tMin,
+			res = null;
+		if (time >= tMin && time <= tMax) {
+			var parts = Curve.subdivide(this.getValues(), time),
+				left = parts[0],
+				right = parts[1],
+				setHandles = _setHandles || this.hasHandles(),
+				segment1 = this._segment1,
+				segment2 = this._segment2,
+				path = this._path;
+			if (setHandles) {
+				segment1._handleOut.set(left[2] - left[0], left[3] - left[1]);
+				segment2._handleIn.set(right[4] - right[6],right[5] - right[7]);
+			}
+			var x = left[6], y = left[7],
+				segment = new Segment(new Point(x, y),
+						setHandles && new Point(left[4] - x, left[5] - y),
+						setHandles && new Point(right[2] - x, right[3] - y));
+			if (path) {
+				path.insert(segment1._index + 1, segment);
+				res = this.getNext();
+			} else {
+				this._segment2 = segment;
+				this._changed();
+				res = new Curve(segment, segment2);
+			}
+		}
+		return res;
+	},
+
+	splitAt: function(location) {
+		return this._path ? this._path.splitAt(location) : null;
+	},
+
+	splitAtTime: function(t) {
+		return this.splitAt(this.getLocationAtTime(t));
+	},
+
+	divide: function(offset, isTime) {
+		return this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset
+				: this.getTimeAt(offset));
+	},
+
+	split: function(offset, isTime) {
+		return this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset
+				: this.getTimeAt(offset));
+	},
+
+	reversed: function() {
+		return new Curve(this._segment2.reversed(), this._segment1.reversed());
+	},
+
+	clearHandles: function() {
+		this._segment1._handleOut.set(0, 0);
+		this._segment2._handleIn.set(0, 0);
+	},
+
+statics: {
+	getValues: function(segment1, segment2, matrix) {
+		var p1 = segment1._point,
+			h1 = segment1._handleOut,
+			h2 = segment2._handleIn,
+			p2 = segment2._point,
+			values = [
+				p1._x, p1._y,
+				p1._x + h1._x, p1._y + h1._y,
+				p2._x + h2._x, p2._y + h2._y,
+				p2._x, p2._y
+			];
+		if (matrix)
+			matrix._transformCoordinates(values, values, 4);
+		return values;
+	},
+
+	subdivide: function(v, t) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7];
+		if (t === undefined)
+			t = 0.5;
+		var u = 1 - t,
+			p3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,
+			p4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,
+			p5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,
+			p6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,
+			p7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,
+			p8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;
+		return [
+			[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],
+			[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]
+		];
+	},
+
+	solveCubic: function (v, coord, val, roots, min, max) {
+		var p1 = v[coord],
+			c1 = v[coord + 2],
+			c2 = v[coord + 4],
+			p2 = v[coord + 6],
+			res = 0;
+		if (  !(p1 < val && p2 < val && c1 < val && c2 < val ||
+				p1 > val && p2 > val && c1 > val && c2 > val)) {
+			var c = 3 * (c1 - p1),
+				b = 3 * (c2 - c1) - c,
+				a = p2 - p1 - c - b;
+			res = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
+		}
+		return res;
+	},
+
+	getTimeOf: function(v, point) {
+		var p1 = new Point(v[0], v[1]),
+			p2 = new Point(v[6], v[7]),
+			epsilon = 1e-12,
+			t = point.isClose(p1, epsilon) ? 0
+			  : point.isClose(p2, epsilon) ? 1
+			  : null;
+		if (t !== null)
+			return t;
+		var coords = [point.x, point.y],
+			roots = [],
+			geomEpsilon = 2e-7;
+		for (var c = 0; c < 2; c++) {
+			var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);
+			for (var i = 0; i < count; i++) {
+				t = roots[i];
+				if (point.isClose(Curve.getPoint(v, t), geomEpsilon))
+					return t;
+			}
+		}
+		return point.isClose(p1, geomEpsilon) ? 0
+			 : point.isClose(p2, geomEpsilon) ? 1
+			 : null;
+	},
+
+	getNearestTime: function(v, point) {
+		if (Curve.isStraight(v)) {
+			var p1x = v[0], p1y = v[1],
+				p2x = v[6], p2y = v[7],
+				vx = p2x - p1x, vy = p2y - p1y,
+				det = vx * vx + vy * vy;
+			if (det === 0)
+				return 0;
+			var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
+			return u < 1e-12 ? 0
+				 : u > 0.999999999999 ? 1
+				 : Curve.getTimeOf(v,
+					new Point(p1x + u * vx, p1y + u * vy));
+		}
+
+		var count = 100,
+			minDist = Infinity,
+			minT = 0;
+
+		function refine(t) {
+			if (t >= 0 && t <= 1) {
+				var dist = point.getDistance(Curve.getPoint(v, t), true);
+				if (dist < minDist) {
+					minDist = dist;
+					minT = t;
+					return true;
+				}
+			}
+		}
+
+		for (var i = 0; i <= count; i++)
+			refine(i / count);
+
+		var step = 1 / (count * 2);
+		while (step > 4e-7) {
+			if (!refine(minT - step) && !refine(minT + step))
+				step /= 2;
+		}
+		return minT;
+	},
+
+	getPart: function(v, from, to) {
+		var flip = from > to;
+		if (flip) {
+			var tmp = from;
+			from = to;
+			to = tmp;
+		}
+		if (from > 0)
+			v = Curve.subdivide(v, from)[1];
+		if (to < 1)
+			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
+		return flip
+				? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]
+				: v;
+	},
+
+	isFlatEnough: function(v, flatness) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7],
+			ux = 3 * c1x - 2 * p1x - p2x,
+			uy = 3 * c1y - 2 * p1y - p2y,
+			vx = 3 * c2x - 2 * p2x - p1x,
+			vy = 3 * c2y - 2 * p2y - p1y;
+		return Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)
+				<= 16 * flatness * flatness;
+	},
+
+	getArea: function(v) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7];
+		return 3 * ((p2y - p1y) * (c1x + c2x) - (p2x - p1x) * (c1y + c2y)
+				+ c1y * (p1x - c2x) - c1x * (p1y - c2y)
+				+ p2y * (c2x + p1x / 3) - p2x * (c2y + p1y / 3)) / 20;
+	},
+
+	getBounds: function(v) {
+		var min = v.slice(0, 2),
+			max = min.slice(),
+			roots = [0, 0];
+		for (var i = 0; i < 2; i++)
+			Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
+					i, 0, min, max, roots);
+		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
+	},
+
+	_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
+		function add(value, padding) {
+			var left = value - padding,
+				right = value + padding;
+			if (left < min[coord])
+				min[coord] = left;
+			if (right > max[coord])
+				max[coord] = right;
+		}
+
+		padding /= 2;
+		var minPad = min[coord] - padding,
+			maxPad = max[coord] + padding;
+		if (    v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||
+				v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
+			if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {
+				add(v0, padding);
+				add(v3, padding);
+			} else {
+				var a = 3 * (v1 - v2) - v0 + v3,
+					b = 2 * (v0 + v2) - 4 * v1,
+					c = v1 - v0,
+					count = Numerical.solveQuadratic(a, b, c, roots),
+					tMin = 4e-7,
+					tMax = 1 - tMin;
+				add(v3, 0);
+				for (var i = 0; i < count; i++) {
+					var t = roots[i],
+						u = 1 - t;
+					if (tMin < t && t < tMax)
+						add(u * u * u * v0
+							+ 3 * u * u * t * v1
+							+ 3 * u * t * t * v2
+							+ t * t * t * v3,
+							padding);
+				}
+			}
+		}
+	}
+}}, Base.each(
+	['getBounds', 'getStrokeBounds', 'getHandleBounds'],
+	function(name) {
+		this[name] = function() {
+			if (!this._bounds)
+				this._bounds = {};
+			var bounds = this._bounds[name];
+			if (!bounds) {
+				bounds = this._bounds[name] = Path[name](
+						[this._segment1, this._segment2], false, this._path);
+			}
+			return bounds.clone();
+		};
+	},
+{
+
+}), Base.each({
+	isStraight: function(l, h1, h2) {
+		if (h1.isZero() && h2.isZero()) {
+			return true;
+		} else {
+			var v = l.getVector(),
+				epsilon = 2e-7;
+			if (v.isZero()) {
+				return false;
+			} else if (l.getDistance(h1) < epsilon
+					&& l.getDistance(h2) < epsilon) {
+				var div = v.dot(v),
+					p1 = v.dot(h1) / div,
+					p2 = v.dot(h2) / div;
+				return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
+			}
+		}
+		return false;
+	},
+
+	isLinear: function(l, h1, h2) {
+		var third = l.getVector().divide(3);
+		return h1.equals(third) && h2.negate().equals(third);
+	}
+}, function(test, name) {
+	this[name] = function() {
+		var seg1 = this._segment1,
+			seg2 = this._segment2;
+		return test(new Line(seg1._point, seg2._point),
+				seg1._handleOut, seg2._handleIn);
+	};
+
+	this.statics[name] = function(v) {
+		var p1x = v[0], p1y = v[1],
+			p2x = v[6], p2y = v[7];
+		return test(new Line(p1x, p1y, p2x, p2y),
+				new Point(v[2] - p1x, v[3] - p1y),
+				new Point(v[4] - p2x, v[5] - p2y));
+	};
+}, {
+	statics: {},
+
+	hasHandles: function() {
+		return !this._segment1._handleOut.isZero()
+				|| !this._segment2._handleIn.isZero();
+	},
+
+	isCollinear: function(curve) {
+		return curve && this.isStraight() && curve.isStraight()
+				&& this.getLine().isCollinear(curve.getLine());
+	},
+
+	isHorizontal: function() {
+		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)
+				< 1e-7;
+	},
+
+	isVertical: function() {
+		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)
+				< 1e-7;
+	}
+}), {
+	beans: false,
+
+	getLocationAt: function(offset, _isTime) {
+		return this.getLocationAtTime(
+				_isTime ? offset : this.getTimeAt(offset));
+	},
+
+	getLocationAtTime: function(t) {
+		return t != null && t >= 0 && t <= 1
+				? new CurveLocation(this, t)
+				: null;
+	},
+
+	getTimeAt: function(offset, start) {
+		return Curve.getTimeAt(this.getValues(), offset, start);
+	},
+
+	getParameterAt: '#getTimeAt',
+
+	getOffsetAtTime: function(t) {
+		return this.getPartLength(0, t);
+	},
+
+	getLocationOf: function() {
+		return this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));
+	},
+
+	getOffsetOf: function() {
+		var loc = this.getLocationOf.apply(this, arguments);
+		return loc ? loc.getOffset() : null;
+	},
+
+	getTimeOf: function() {
+		return Curve.getTimeOf(this.getValues(), Point.read(arguments));
+	},
+
+	getParameterOf: '#getTimeOf',
+
+	getNearestLocation: function() {
+		var point = Point.read(arguments),
+			values = this.getValues(),
+			t = Curve.getNearestTime(values, point),
+			pt = Curve.getPoint(values, t);
+		return new CurveLocation(this, t, pt, null, point.getDistance(pt));
+	},
+
+	getNearestPoint: function() {
+		var loc = this.getNearestLocation.apply(this, arguments);
+		return loc ? loc.getPoint() : loc;
+	}
+
+},
+new function() {
+	var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
+		'getWeightedNormal', 'getCurvature'];
+	return Base.each(methods,
+		function(name) {
+			this[name + 'At'] = function(location, _isTime) {
+				var values = this.getValues();
+				return Curve[name](values, _isTime ? location
+						: Curve.getTimeAt(values, location));
+			};
+
+			this[name + 'AtTime'] = function(time) {
+				return Curve[name](this.getValues(), time);
+			};
+		}, {
+			statics: {
+				_evaluateMethods: methods
+			}
+		}
+	);
+},
+new function() {
+
+	function getLengthIntegrand(v) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7],
+
+			ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
+			bx = 6 * (p1x + c2x) - 12 * c1x,
+			cx = 3 * (c1x - p1x),
+
+			ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
+			by = 6 * (p1y + c2y) - 12 * c1y,
+			cy = 3 * (c1y - p1y);
+
+		return function(t) {
+			var dx = (ax * t + bx) * t + cx,
+				dy = (ay * t + by) * t + cy;
+			return Math.sqrt(dx * dx + dy * dy);
+		};
+	}
+
+	function getIterations(a, b) {
+		return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
+	}
+
+	function evaluate(v, t, type, normalized) {
+		if (t == null || t < 0 || t > 1)
+			return null;
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7],
+			isZero = Numerical.isZero;
+		if (isZero(c1x - p1x) && isZero(c1y - p1y)) {
+			c1x = p1x;
+			c1y = p1y;
+		}
+		if (isZero(c2x - p2x) && isZero(c2y - p2y)) {
+			c2x = p2x;
+			c2y = p2y;
+		}
+		var cx = 3 * (c1x - p1x),
+			bx = 3 * (c2x - c1x) - cx,
+			ax = p2x - p1x - cx - bx,
+			cy = 3 * (c1y - p1y),
+			by = 3 * (c2y - c1y) - cy,
+			ay = p2y - p1y - cy - by,
+			x, y;
+		if (type === 0) {
+			x = t === 0 ? p1x : t === 1 ? p2x
+					: ((ax * t + bx) * t + cx) * t + p1x;
+			y = t === 0 ? p1y : t === 1 ? p2y
+					: ((ay * t + by) * t + cy) * t + p1y;
+		} else {
+			var tMin = 4e-7,
+				tMax = 1 - tMin;
+			if (t < tMin) {
+				x = cx;
+				y = cy;
+			} else if (t > tMax) {
+				x = 3 * (p2x - c2x);
+				y = 3 * (p2y - c2y);
+			} else {
+				x = (3 * ax * t + 2 * bx) * t + cx;
+				y = (3 * ay * t + 2 * by) * t + cy;
+			}
+			if (normalized) {
+				if (x === 0 && y === 0 && (t < tMin || t > tMax)) {
+					x = c2x - c1x;
+					y = c2y - c1y;
+				}
+				var len = Math.sqrt(x * x + y * y);
+				if (len) {
+					x /= len;
+					y /= len;
+				}
+			}
+			if (type === 3) {
+				var x2 = 6 * ax * t + 2 * bx,
+					y2 = 6 * ay * t + 2 * by,
+					d = Math.pow(x * x + y * y, 3 / 2);
+				x = d !== 0 ? (x * y2 - y * x2) / d : 0;
+				y = 0;
+			}
+		}
+		return type === 2 ? new Point(y, -x) : new Point(x, y);
+	}
+
+	return { statics: {
+
+		getLength: function(v, a, b, ds) {
+			if (a === undefined)
+				a = 0;
+			if (b === undefined)
+				b = 1;
+			if (Curve.isStraight(v)) {
+				var c = v;
+				if (b < 1) {
+					c = Curve.subdivide(c, b)[0];
+					a /= b;
+				}
+				if (a > 0) {
+					c = Curve.subdivide(c, a)[1];
+				}
+				var dx = c[6] - c[0],
+					dy = c[7] - c[1];
+				return Math.sqrt(dx * dx + dy * dy);
+			}
+			return Numerical.integrate(ds || getLengthIntegrand(v), a, b,
+					getIterations(a, b));
+		},
+
+		getTimeAt: function(v, offset, start) {
+			if (start === undefined)
+				start = offset < 0 ? 1 : 0;
+			if (offset === 0)
+				return start;
+			var abs = Math.abs,
+				epsilon = 1e-12,
+				forward = offset > 0,
+				a = forward ? start : 0,
+				b = forward ? 1 : start,
+				ds = getLengthIntegrand(v),
+				rangeLength = Curve.getLength(v, a, b, ds),
+				diff = abs(offset) - rangeLength;
+			if (abs(diff) < epsilon) {
+				return forward ? b : a;
+			} else if (diff > epsilon) {
+				return null;
+			}
+			var guess = offset / rangeLength,
+				length = 0;
+			function f(t) {
+				length += Numerical.integrate(ds, start, t,
+						getIterations(start, t));
+				start = t;
+				return length - offset;
+			}
+			return Numerical.findRoot(f, ds, start + guess, a, b, 32,
+					1e-12);
+		},
+
+		getPoint: function(v, t) {
+			return evaluate(v, t, 0, false);
+		},
+
+		getTangent: function(v, t) {
+			return evaluate(v, t, 1, true);
+		},
+
+		getWeightedTangent: function(v, t) {
+			return evaluate(v, t, 1, false);
+		},
+
+		getNormal: function(v, t) {
+			return evaluate(v, t, 2, true);
+		},
+
+		getWeightedNormal: function(v, t) {
+			return evaluate(v, t, 2, false);
+		},
+
+		getCurvature: function(v, t) {
+			return evaluate(v, t, 3, false).x;
+		}
+	}};
+},
+new function() {
+
+	function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
+			overlap) {
+		var excludeStart = !overlap && param.excludeStart,
+			excludeEnd = !overlap && param.excludeEnd,
+			tMin = 4e-7,
+			tMax = 1 - tMin;
+		if (t1 == null)
+			t1 = Curve.getTimeOf(v1, p1);
+		if (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&
+			t1 <= (excludeEnd ? tMax : 1)) {
+			if (t2 == null)
+				t2 = Curve.getTimeOf(v2, p2);
+			if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
+				t2 <= (excludeStart ? tMax : 1)) {
+				var renormalize = param.renormalize;
+				if (renormalize) {
+					var res = renormalize(t1, t2);
+					t1 = res[0];
+					t2 = res[1];
+				}
+				var loc1 = new CurveLocation(c1, t1,
+						p1 || Curve.getPoint(v1, t1), overlap),
+					loc2 = new CurveLocation(c2, t2,
+						p2 || Curve.getPoint(v2, t2), overlap),
+					flip = loc1.getPath() === loc2.getPath()
+						&& loc1.getIndex() > loc2.getIndex(),
+					loc = flip ? loc2 : loc1,
+					include = param.include;
+				loc1._intersection = loc2;
+				loc2._intersection = loc1;
+				if (!include || include(loc)) {
+					CurveLocation.insert(locations, loc, true);
+				}
+			}
+		}
+	}
+
+	function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,
+			uMin, uMax, flip, recursion, calls) {
+		if (++recursion >= 48 || ++calls > 4096)
+			return calls;
+		var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
+			getSignedDistance = Line.getSignedDistance,
+			d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),
+			d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),
+			factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
+			dMin = factor * Math.min(0, d1, d2),
+			dMax = factor * Math.max(0, d1, d2),
+			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
+			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
+			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
+			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
+			hull = getConvexHull(dp0, dp1, dp2, dp3),
+			top = hull[0],
+			bottom = hull[1],
+			tMinClip,
+			tMaxClip;
+		if (d1 === 0 && d2 === 0
+				&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0
+			|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null
+			|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),
+				dMin, dMax)) == null)
+			return calls;
+		var tMinNew = tMin + (tMax - tMin) * tMinClip,
+			tMaxNew = tMin + (tMax - tMin) * tMaxClip;
+		if (Math.max(uMax - uMin, tMaxNew - tMinNew)
+				< 1e-9) {
+			var t = (tMinNew + tMaxNew) / 2,
+				u = (uMin + uMax) / 2;
+			v1 = c1.getValues();
+			v2 = c2.getValues();
+			addLocation(locations, param,
+					flip ? v2 : v1, flip ? c2 : c1, flip ? u : t, null,
+					flip ? v1 : v2, flip ? c1 : c2, flip ? t : u, null);
+		} else {
+			v1 = Curve.getPart(v1, tMinClip, tMaxClip);
+			if (tMaxClip - tMinClip > 0.8) {
+				if (tMaxNew - tMinNew > uMax - uMin) {
+					var parts = Curve.subdivide(v1, 0.5),
+						t = (tMinNew + tMaxNew) / 2;
+					calls = addCurveIntersections(
+							v2, parts[0], c2, c1, locations, param,
+							uMin, uMax, tMinNew, t, !flip, recursion, calls);
+					calls = addCurveIntersections(
+							v2, parts[1], c2, c1, locations, param,
+							uMin, uMax, t, tMaxNew, !flip, recursion, calls);
+				} else {
+					var parts = Curve.subdivide(v2, 0.5),
+						u = (uMin + uMax) / 2;
+					calls = addCurveIntersections(
+							parts[0], v1, c2, c1, locations, param,
+							uMin, u, tMinNew, tMaxNew, !flip, recursion, calls);
+					calls = addCurveIntersections(
+							parts[1], v1, c2, c1, locations, param,
+							u, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
+				}
+			} else {
+				calls = addCurveIntersections(
+						v2, v1, c2, c1, locations, param,
+						uMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
+			}
+		}
+		return calls;
+	}
+
+	function getConvexHull(dq0, dq1, dq2, dq3) {
+		var p0 = [ 0, dq0 ],
+			p1 = [ 1 / 3, dq1 ],
+			p2 = [ 2 / 3, dq2 ],
+			p3 = [ 1, dq3 ],
+			dist1 = dq1 - (2 * dq0 + dq3) / 3,
+			dist2 = dq2 - (dq0 + 2 * dq3) / 3,
+			hull;
+		if (dist1 * dist2 < 0) {
+			hull = [[p0, p1, p3], [p0, p2, p3]];
+		} else {
+			var distRatio = dist1 / dist2;
+			hull = [
+				distRatio >= 2 ? [p0, p1, p3]
+				: distRatio <= 0.5 ? [p0, p2, p3]
+				: [p0, p1, p2, p3],
+				[p0, p3]
+			];
+		}
+		return (dist1 || dist2) < 0 ? hull.reverse() : hull;
+	}
+
+	function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
+		if (hullTop[0][1] < dMin) {
+			return clipConvexHullPart(hullTop, true, dMin);
+		} else if (hullBottom[0][1] > dMax) {
+			return clipConvexHullPart(hullBottom, false, dMax);
+		} else {
+			return hullTop[0][0];
+		}
+	}
+
+	function clipConvexHullPart(part, top, threshold) {
+		var px = part[0][0],
+			py = part[0][1];
+		for (var i = 1, l = part.length; i < l; i++) {
+			var qx = part[i][0],
+				qy = part[i][1];
+			if (top ? qy >= threshold : qy <= threshold) {
+				return qy === threshold ? qx
+						: px + (threshold - py) * (qx - px) / (qy - py);
+			}
+			px = qx;
+			py = qy;
+		}
+		return null;
+	}
+
+	function addCurveLineIntersections(v1, v2, c1, c2, locations, param) {
+		var flip = Curve.isStraight(v1),
+			vc = flip ? v2 : v1,
+			vl = flip ? v1 : v2,
+			lx1 = vl[0], ly1 = vl[1],
+			lx2 = vl[6], ly2 = vl[7],
+			ldx = lx2 - lx1,
+			ldy = ly2 - ly1,
+			angle = Math.atan2(-ldy, ldx),
+			sin = Math.sin(angle),
+			cos = Math.cos(angle),
+			rvc = [];
+		for(var i = 0; i < 8; i += 2) {
+			var x = vc[i] - lx1,
+				y = vc[i + 1] - ly1;
+			rvc.push(
+				x * cos - y * sin,
+				x * sin + y * cos);
+		}
+		var roots = [],
+			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
+		for (var i = 0; i < count; i++) {
+			var tc = roots[i],
+				pc = Curve.getPoint(vc, tc),
+				tl = Curve.getTimeOf(vl, pc);
+			if (tl !== null) {
+				var pl = Curve.getPoint(vl, tl),
+					t1 = flip ? tl : tc,
+					t2 = flip ? tc : tl;
+				if (!param.excludeEnd || t2 > Numerical.CURVETIME_EPSILON) {
+					addLocation(locations, param,
+							v1, c1, t1, flip ? pl : pc,
+							v2, c2, t2, flip ? pc : pl);
+				}
+			}
+		}
+	}
+
+	function addLineIntersection(v1, v2, c1, c2, locations, param) {
+		var pt = Line.intersect(
+				v1[0], v1[1], v1[6], v1[7],
+				v2[0], v2[1], v2[6], v2[7]);
+		if (pt) {
+			addLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);
+		}
+	}
+
+	return { statics: {
+		_getIntersections: function(v1, v2, c1, c2, locations, param) {
+			if (!v2) {
+				return Curve._getSelfIntersection(v1, c1, locations, param);
+			}
+			var epsilon = 2e-7,
+				c1p1x = v1[0], c1p1y = v1[1],
+				c1p2x = v1[6], c1p2y = v1[7],
+				c2p1x = v2[0], c2p1y = v2[1],
+				c2p2x = v2[6], c2p2y = v2[7],
+				c1s1x = (3 * v1[2] + c1p1x) / 4,
+				c1s1y = (3 * v1[3] + c1p1y) / 4,
+				c1s2x = (3 * v1[4] + c1p2x) / 4,
+				c1s2y = (3 * v1[5] + c1p2y) / 4,
+				c2s1x = (3 * v2[2] + c2p1x) / 4,
+				c2s1y = (3 * v2[3] + c2p1y) / 4,
+				c2s2x = (3 * v2[4] + c2p2x) / 4,
+				c2s2y = (3 * v2[5] + c2p2y) / 4,
+				min = Math.min,
+				max = Math.max;
+			if (!(  max(c1p1x, c1s1x, c1s2x, c1p2x) + epsilon >
+					min(c2p1x, c2s1x, c2s2x, c2p2x) &&
+					min(c1p1x, c1s1x, c1s2x, c1p2x) - epsilon <
+					max(c2p1x, c2s1x, c2s2x, c2p2x) &&
+					max(c1p1y, c1s1y, c1s2y, c1p2y) + epsilon >
+					min(c2p1y, c2s1y, c2s2y, c2p2y) &&
+					min(c1p1y, c1s1y, c1s2y, c1p2y) - epsilon <
+					max(c2p1y, c2s1y, c2s2y, c2p2y)))
+				return locations;
+			var overlaps = Curve.getOverlaps(v1, v2);
+			if (overlaps) {
+				for (var i = 0; i < 2; i++) {
+					var overlap = overlaps[i];
+					addLocation(locations, param,
+						v1, c1, overlap[0], null,
+						v2, c2, overlap[1], null, true);
+				}
+				return locations;
+			}
+
+			var straight1 = Curve.isStraight(v1),
+				straight2 = Curve.isStraight(v2),
+				straight = straight1 && straight2,
+				before = locations.length;
+			(straight
+				? addLineIntersection
+				: straight1 || straight2
+					? addCurveLineIntersections
+					: addCurveIntersections)(
+						v1, v2, c1, c2, locations, param,
+						0, 1, 0, 1, 0, 0, 0);
+			if (straight && locations.length > before)
+				return locations;
+			var c1p1 = new Point(c1p1x, c1p1y),
+				c1p2 = new Point(c1p2x, c1p2y),
+				c2p1 = new Point(c2p1x, c2p1y),
+				c2p2 = new Point(c2p2x, c2p2y);
+			if (c1p1.isClose(c2p1, epsilon))
+				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);
+			if (!param.excludeStart && c1p1.isClose(c2p2, epsilon))
+				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);
+			if (!param.excludeEnd && c1p2.isClose(c2p1, epsilon))
+				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);
+			if (c1p2.isClose(c2p2, epsilon))
+				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);
+			return locations;
+		},
+
+		_getSelfIntersection: function(v1, c1, locations, param) {
+			var p1x = v1[0], p1y = v1[1],
+				h1x = v1[2], h1y = v1[3],
+				h2x = v1[4], h2y = v1[5],
+				p2x = v1[6], p2y = v1[7];
+			var line = new Line(p1x, p1y, p2x, p2y, false),
+				side1 = line.getSide(new Point(h1x, h1y), true),
+				side2 = line.getSide(new Point(h2x, h2y), true);
+			if (side1 === side2) {
+				var edgeSum = (p1x - h2x) * (h1y - p2y)
+							+ (h1x - p2x) * (h2y - p1y);
+				if (edgeSum * side1 > 0)
+					return locations;
+			}
+			var ax = p2x - 3 * h2x + 3 * h1x - p1x,
+				bx = h2x - 2 * h1x + p1x,
+				cx = h1x - p1x,
+				ay = p2y - 3 * h2y + 3 * h1y - p1y,
+				by = h2y - 2 * h1y + p1y,
+				cy = h1y - p1y,
+				ac = ay * cx - ax * cy,
+				ab = ay * bx - ax * by,
+				bc = by * cx - bx * cy;
+			if (ac * ac - 4 * ab * bc < 0) {
+				var roots = [],
+					tSplit,
+					count = Numerical.solveCubic(
+							ax * ax  + ay * ay,
+							3 * (ax * bx + ay * by),
+							2 * (bx * bx + by * by) + ax * cx + ay * cy,
+							bx * cx + by * cy,
+							roots, 0, 1);
+				if (count > 0) {
+					for (var i = 0, maxCurvature = 0; i < count; i++) {
+						var curvature = Math.abs(
+								c1.getCurvatureAtTime(roots[i]));
+						if (curvature > maxCurvature) {
+							maxCurvature = curvature;
+							tSplit = roots[i];
+						}
+					}
+					var parts = Curve.subdivide(v1, tSplit);
+					param.excludeEnd = true;
+					param.renormalize = function(t1, t2) {
+						return [t1 * tSplit, t2 * (1 - tSplit) + tSplit];
+					};
+					Curve._getIntersections(parts[0], parts[1], c1, c1,
+							locations, param);
+				}
+			}
+			return locations;
+		},
+
+		getOverlaps: function(v1, v2) {
+			var abs = Math.abs,
+				timeEpsilon = 4e-7,
+				geomEpsilon = 2e-7,
+				straight1 = Curve.isStraight(v1),
+				straight2 = Curve.isStraight(v2),
+				straightBoth = straight1 && straight2;
+
+			function getSquaredLineLength(v) {
+				var x = v[6] - v[0],
+					y = v[7] - v[1];
+				return x * x + y * y;
+			}
+
+			var flip = getSquaredLineLength(v1) < getSquaredLineLength(v2),
+				l1 = flip ? v2 : v1,
+				l2 = flip ? v1 : v2,
+				line = new Line(l1[0], l1[1], l1[6], l1[7]);
+			if (line.getDistance(new Point(l2[0], l2[1])) < geomEpsilon &&
+				line.getDistance(new Point(l2[6], l2[7])) < geomEpsilon) {
+				if (!straightBoth &&
+					line.getDistance(new Point(l1[2], l1[3])) < geomEpsilon &&
+					line.getDistance(new Point(l1[4], l1[5])) < geomEpsilon &&
+					line.getDistance(new Point(l2[2], l2[3])) < geomEpsilon &&
+					line.getDistance(new Point(l2[4], l2[5])) < geomEpsilon) {
+					straight1 = straight2 = straightBoth = true;
+				}
+			} else if (straightBoth) {
+				return null;
+			}
+			if (straight1 ^ straight2) {
+				return null;
+			}
+
+			var v = [v1, v2],
+				pairs = [];
+			for (var i = 0, t1 = 0;
+					i < 2 && pairs.length < 2;
+					i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
+				var t2 = Curve.getTimeOf(v[i ^ 1], new Point(
+						v[i][t1 === 0 ? 0 : 6],
+						v[i][t1 === 0 ? 1 : 7]));
+				if (t2 != null) {
+					var pair = i === 0 ? [t1, t2] : [t2, t1];
+					if (pairs.length === 0 ||
+						abs(pair[0] - pairs[0][0]) > timeEpsilon &&
+						abs(pair[1] - pairs[0][1]) > timeEpsilon)
+						pairs.push(pair);
+				}
+				if (i === 1 && pairs.length === 0)
+					break;
+			}
+			if (pairs.length !== 2) {
+				pairs = null;
+			} else if (!straightBoth) {
+				var o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),
+					o2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);
+				if (abs(o2[2] - o1[2]) > geomEpsilon ||
+					abs(o2[3] - o1[3]) > geomEpsilon ||
+					abs(o2[4] - o1[4]) > geomEpsilon ||
+					abs(o2[5] - o1[5]) > geomEpsilon)
+					pairs = null;
+			}
+			return pairs;
+		}
+	}};
+});
+
+var CurveLocation = Base.extend({
+	_class: 'CurveLocation',
+	beans: true,
+
+	initialize: function CurveLocation(curve, time, point, _overlap, _distance) {
+		if (time > 0.9999996) {
+			var next = curve.getNext();
+			if (next) {
+				time = 0;
+				curve = next;
+			}
+		}
+		this._setCurve(curve);
+		this._time = time;
+		this._point = point || curve.getPointAtTime(time);
+		this._overlap = _overlap;
+		this._distance = _distance;
+		this._intersection = this._next = this._previous = null;
+	},
+
+	_setCurve: function(curve) {
+		var path = curve._path;
+		this._path = path;
+		this._version = path ? path._version : 0;
+		this._curve = curve;
+		this._segment = null;
+		this._segment1 = curve._segment1;
+		this._segment2 = curve._segment2;
+	},
+
+	_setSegment: function(segment) {
+		this._setCurve(segment.getCurve());
+		this._segment = segment;
+		this._time = segment === this._segment1 ? 0 : 1;
+		this._point = segment._point.clone();
+	},
+
+	getSegment: function() {
+		var curve = this.getCurve(),
+			segment = this._segment;
+		if (!segment) {
+			var time = this.getTime();
+			if (time === 0) {
+				segment = curve._segment1;
+			} else if (time === 1) {
+				segment = curve._segment2;
+			} else if (time != null) {
+				segment = curve.getPartLength(0, time)
+					< curve.getPartLength(time, 1)
+						? curve._segment1
+						: curve._segment2;
+			}
+			this._segment = segment;
+		}
+		return segment;
+	},
+
+	getCurve: function() {
+		var path = this._path,
+			that = this;
+		if (path && path._version !== this._version) {
+			this._time = this._curve = this._offset = null;
+		}
+
+		function trySegment(segment) {
+			var curve = segment && segment.getCurve();
+			if (curve && (that._time = curve.getTimeOf(that._point))
+					!= null) {
+				that._setCurve(curve);
+				that._segment = segment;
+				return curve;
+			}
+		}
+
+		return this._curve
+			|| trySegment(this._segment)
+			|| trySegment(this._segment1)
+			|| trySegment(this._segment2.getPrevious());
+	},
+
+	getPath: function() {
+		var curve = this.getCurve();
+		return curve && curve._path;
+	},
+
+	getIndex: function() {
+		var curve = this.getCurve();
+		return curve && curve.getIndex();
+	},
+
+	getTime: function() {
+		var curve = this.getCurve(),
+			time = this._time;
+		return curve && time == null
+			? this._time = curve.getTimeOf(this._point)
+			: time;
+	},
+
+	getParameter: '#getTime',
+
+	getPoint: function() {
+		return this._point;
+	},
+
+	getOffset: function() {
+		var offset = this._offset;
+		if (offset == null) {
+			offset = 0;
+			var path = this.getPath(),
+				index = this.getIndex();
+			if (path && index != null) {
+				var curves = path.getCurves();
+				for (var i = 0; i < index; i++)
+					offset += curves[i].getLength();
+			}
+			this._offset = offset += this.getCurveOffset();
+		}
+		return offset;
+	},
+
+	getCurveOffset: function() {
+		var curve = this.getCurve(),
+			time = this.getTime();
+		return time != null && curve && curve.getPartLength(0, time);
+	},
+
+	getIntersection: function() {
+		return this._intersection;
+	},
+
+	getDistance: function() {
+		return this._distance;
+	},
+
+	divide: function() {
+		var curve = this.getCurve(),
+			res = null;
+		if (curve) {
+			res = curve.divideAtTime(this.getTime());
+			if (res)
+				this._setSegment(res._segment1);
+		}
+		return res;
+	},
+
+	split: function() {
+		var curve = this.getCurve();
+		return curve ? curve.splitAtTime(this.getTime()) : null;
+	},
+
+	equals: function(loc, _ignoreOther) {
+		var res = this === loc,
+			epsilon = 2e-7;
+		if (!res && loc instanceof CurveLocation
+				&& this.getPath() === loc.getPath()
+				&& this.getPoint().isClose(loc.getPoint(), epsilon)) {
+			var c1 = this.getCurve(),
+				c2 = loc.getCurve(),
+				abs = Math.abs,
+				diff = abs(
+					((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
+							+ this.getTime()) -
+					((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
+							+ loc.getTime()));
+			res = (diff < 4e-7
+				|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon
+					|| abs(this.getPath().getLength() - diff) < epsilon))
+				&& (_ignoreOther
+					|| (!this._intersection && !loc._intersection
+						|| this._intersection && this._intersection.equals(
+								loc._intersection, true)));
+		}
+		return res;
+	},
+
+	toString: function() {
+		var parts = [],
+			point = this.getPoint(),
+			f = Formatter.instance;
+		if (point)
+			parts.push('point: ' + point);
+		var index = this.getIndex();
+		if (index != null)
+			parts.push('index: ' + index);
+		var time = this.getTime();
+		if (time != null)
+			parts.push('time: ' + f.number(time));
+		if (this._distance != null)
+			parts.push('distance: ' + f.number(this._distance));
+		return '{ ' + parts.join(', ') + ' }';
+	},
+
+	isTouching: function() {
+		var inter = this._intersection;
+		if (inter && this.getTangent().isCollinear(inter.getTangent())) {
+			var curve1 = this.getCurve(),
+				curve2 = inter.getCurve();
+			return !(curve1.isStraight() && curve2.isStraight()
+					&& curve1.getLine().intersect(curve2.getLine()));
+		}
+		return false;
+	},
+
+	isCrossing: function() {
+		var inter = this._intersection;
+		if (!inter)
+			return false;
+		var t1 = this.getTime(),
+			t2 = inter.getTime(),
+			tMin = 4e-7,
+			tMax = 1 - tMin,
+			t1Inside = t1 > tMin && t1 < tMax,
+			t2Inside = t2 > tMin && t2 < tMax;
+		if (t1Inside && t2Inside)
+			return !this.isTouching();
+		var c2 = this.getCurve(),
+			c1 = t1 <= tMin ? c2.getPrevious() : c2,
+			c4 = inter.getCurve(),
+			c3 = t2 <= tMin ? c4.getPrevious() : c4;
+		if (t1 >= tMax)
+			c2 = c2.getNext();
+		if (t2 >= tMax)
+			c4 = c4.getNext();
+		if (!c1 || !c2 || !c3 || !c4)
+			return false;
+
+		function isInRange(angle, min, max) {
+			return min < max
+					? angle > min && angle < max
+					: angle > min || angle < max;
+		}
+
+		var lenghts = [];
+		if (!t1Inside)
+			lenghts.push(c1.getLength(), c2.getLength());
+		if (!t2Inside)
+			lenghts.push(c3.getLength(), c4.getLength());
+		var pt = this.getPoint(),
+			offset = Math.min.apply(Math, lenghts) / 64,
+			v2 = t1Inside ? c2.getTangentAtTime(t1)
+					: c2.getPointAt(offset).subtract(pt),
+			v1 = t1Inside ? v2.negate()
+					: c1.getPointAt(-offset).subtract(pt),
+			v4 = t2Inside ? c4.getTangentAtTime(t2)
+					: c4.getPointAt(offset).subtract(pt),
+			v3 = t2Inside ? v4.negate()
+					: c3.getPointAt(-offset).subtract(pt),
+			a1 = v1.getAngle(),
+			a2 = v2.getAngle(),
+			a3 = v3.getAngle(),
+			a4 = v4.getAngle();
+		return !!(t1Inside
+				? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&
+				  (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))
+				: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&
+				  (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));
+	},
+
+	hasOverlap: function() {
+		return !!this._overlap;
+	}
+}, Base.each(Curve._evaluateMethods, function(name) {
+	var get = name + 'At';
+	this[name] = function() {
+		var curve = this.getCurve(),
+			time = this.getTime();
+		return time != null && curve && curve[get](time, true);
+	};
+}, {
+	preserve: true
+}),
+new function() {
+
+	function insert(locations, loc, merge) {
+		var length = locations.length,
+			l = 0,
+			r = length - 1;
+
+		function search(index, dir) {
+			for (var i = index + dir; i >= -1 && i <= length; i += dir) {
+				var loc2 = locations[((i % length) + length) % length];
+				if (!loc.getPoint().isClose(loc2.getPoint(),
+						2e-7))
+					break;
+				if (loc.equals(loc2))
+					return loc2;
+			}
+			return null;
+		}
+
+		while (l <= r) {
+			var m = (l + r) >>> 1,
+				loc2 = locations[m],
+				found;
+			if (merge && (found = loc.equals(loc2) ? loc2
+					: (search(m, -1) || search(m, 1)))) {
+				if (loc._overlap) {
+					found._overlap = found._intersection._overlap = true;
+				}
+				return found;
+			}
+		var path1 = loc.getPath(),
+			path2 = loc2.getPath(),
+			diff = path1 === path2
+				? (loc.getIndex() + loc.getTime())
+				- (loc2.getIndex() + loc2.getTime())
+				: path1._id - path2._id;
+			if (diff < 0) {
+				r = m - 1;
+			} else {
+				l = m + 1;
+			}
+		}
+		locations.splice(l, 0, loc);
+		return loc;
+	}
+
+	return { statics: {
+		insert: insert,
+
+		expand: function(locations) {
+			var expanded = locations.slice();
+			for (var i = locations.length - 1; i >= 0; i--) {
+				insert(expanded, locations[i]._intersection, false);
+			}
+			return expanded;
+		}
+	}};
+});
+
+var PathItem = Item.extend({
+	_class: 'PathItem',
+	_selectBounds: false,
+	_canScaleStroke: true,
+
+	initialize: function PathItem() {
+	},
+
+	statics: {
+		create: function(pathData) {
+			var ctor = (pathData && pathData.match(/m/gi) || []).length > 1
+					|| /z\s*\S+/i.test(pathData) ? CompoundPath : Path;
+			return new ctor(pathData);
+		}
+	},
+
+	_asPathItem: function() {
+		return this;
+	},
+
+	setPathData: function(data) {
+
+		var parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),
+			coords,
+			relative = false,
+			previous,
+			control,
+			current = new Point(),
+			start = new Point();
+
+		function getCoord(index, coord) {
+			var val = +coords[index];
+			if (relative)
+				val += current[coord];
+			return val;
+		}
+
+		function getPoint(index) {
+			return new Point(
+				getCoord(index, 'x'),
+				getCoord(index + 1, 'y')
+			);
+		}
+
+		this.clear();
+
+		for (var i = 0, l = parts && parts.length; i < l; i++) {
+			var part = parts[i],
+				command = part[0],
+				lower = command.toLowerCase();
+			coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
+			var length = coords && coords.length;
+			relative = command === lower;
+			if (previous === 'z' && !/[mz]/.test(lower))
+				this.moveTo(current = start);
+			switch (lower) {
+			case 'm':
+			case 'l':
+				var move = lower === 'm';
+				for (var j = 0; j < length; j += 2)
+					this[j === 0 && move ? 'moveTo' : 'lineTo'](
+							current = getPoint(j));
+				control = current;
+				if (move)
+					start = current;
+				break;
+			case 'h':
+			case 'v':
+				var coord = lower === 'h' ? 'x' : 'y';
+				for (var j = 0; j < length; j++) {
+					current[coord] = getCoord(j, coord);
+					this.lineTo(current);
+				}
+				control = current;
+				break;
+			case 'c':
+				for (var j = 0; j < length; j += 6) {
+					this.cubicCurveTo(
+							getPoint(j),
+							control = getPoint(j + 2),
+							current = getPoint(j + 4));
+				}
+				break;
+			case 's':
+				for (var j = 0; j < length; j += 4) {
+					this.cubicCurveTo(
+							/[cs]/.test(previous)
+									? current.multiply(2).subtract(control)
+									: current,
+							control = getPoint(j),
+							current = getPoint(j + 2));
+					previous = lower;
+				}
+				break;
+			case 'q':
+				for (var j = 0; j < length; j += 4) {
+					this.quadraticCurveTo(
+							control = getPoint(j),
+							current = getPoint(j + 2));
+				}
+				break;
+			case 't':
+				for (var j = 0; j < length; j += 2) {
+					this.quadraticCurveTo(
+							control = (/[qt]/.test(previous)
+									? current.multiply(2).subtract(control)
+									: current),
+							current = getPoint(j));
+					previous = lower;
+				}
+				break;
+			case 'a':
+				for (var j = 0; j < length; j += 7) {
+					this.arcTo(current = getPoint(j + 5),
+							new Size(+coords[j], +coords[j + 1]),
+							+coords[j + 2], +coords[j + 4], +coords[j + 3]);
+				}
+				break;
+			case 'z':
+				this.closePath(1e-12);
+				break;
+			}
+			previous = lower;
+		}
+	},
+
+	_canComposite: function() {
+		return !(this.hasFill() && this.hasStroke());
+	},
+
+	_contains: function(point) {
+		var winding = point.isInside(
+				this.getBounds({ internal: true, handle: true }))
+					&& this._getWinding(point);
+		return !!(this.getFillRule() === 'evenodd' ? winding & 1 : winding);
+	},
+
+	getIntersections: function(path, include, _matrix, _returnFirst) {
+		var self = this === path || !path,
+			matrix1 = this._matrix._orNullIfIdentity(),
+			matrix2 = self ? matrix1
+				: (_matrix || path._matrix)._orNullIfIdentity();
+		if (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
+			return [];
+		var curves1 = this.getCurves(),
+			curves2 = self ? curves1 : path.getCurves(),
+			length1 = curves1.length,
+			length2 = self ? length1 : curves2.length,
+			values2 = [],
+			arrays = [],
+			locations,
+			path;
+		for (var i = 0; i < length2; i++)
+			values2[i] = curves2[i].getValues(matrix2);
+		for (var i = 0; i < length1; i++) {
+			var curve1 = curves1[i],
+				values1 = self ? values2[i] : curve1.getValues(matrix1),
+				path1 = curve1.getPath();
+			if (path1 !== path) {
+				path = path1;
+				locations = [];
+				arrays.push(locations);
+			}
+			if (self) {
+				Curve._getSelfIntersection(values1, curve1, locations, {
+					include: include,
+					excludeStart: length1 === 1 &&
+							curve1.getPoint1().equals(curve1.getPoint2())
+				});
+			}
+			for (var j = self ? i + 1 : 0; j < length2; j++) {
+				if (_returnFirst && locations.length)
+					return locations;
+				var curve2 = curves2[j];
+				Curve._getIntersections(
+					values1, values2[j], curve1, curve2, locations,
+					{
+						include: include,
+						excludeStart: self && curve1.getPrevious() === curve2,
+						excludeEnd: self && curve1.getNext() === curve2
+					}
+				);
+			}
+		}
+		locations = [];
+		for (var i = 0, l = arrays.length; i < l; i++) {
+			locations.push.apply(locations, arrays[i]);
+		}
+		return locations;
+	},
+
+	getCrossings: function(path) {
+		return this.getIntersections(path, function(inter) {
+			return inter._overlap || inter.isCrossing();
+		});
+	},
+
+	getNearestLocation: function() {
+		var point = Point.read(arguments),
+			curves = this.getCurves(),
+			minDist = Infinity,
+			minLoc = null;
+		for (var i = 0, l = curves.length; i < l; i++) {
+			var loc = curves[i].getNearestLocation(point);
+			if (loc._distance < minDist) {
+				minDist = loc._distance;
+				minLoc = loc;
+			}
+		}
+		return minLoc;
+	},
+
+	getNearestPoint: function() {
+		var loc = this.getNearestLocation.apply(this, arguments);
+		return loc ? loc.getPoint() : loc;
+	},
+
+	interpolate: function(from, to, factor) {
+		var isPath = !this._children,
+			name = isPath ? '_segments' : '_children',
+			itemsFrom = from[name],
+			itemsTo = to[name],
+			items = this[name];
+		if (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {
+			throw new Error('Invalid operands in interpolate() call: ' +
+					from + ', ' + to);
+		}
+		var current = items.length,
+			length = itemsTo.length;
+		if (current < length) {
+			var ctor = isPath ? Segment : Path;
+			for (var i = current; i < length; i++) {
+				this.add(new ctor());
+			}
+		} else if (current > length) {
+			this[isPath ? 'removeSegments' : 'removeChildren'](length, current);
+		}
+		for (var i = 0; i < length; i++) {
+			items[i].interpolate(itemsFrom[i], itemsTo[i], factor);
+		}
+		if (isPath) {
+			this.setClosed(from._closed);
+			this._changed(9);
+		}
+	},
+
+});
+
+var Path = PathItem.extend({
+	_class: 'Path',
+	_serializeFields: {
+		segments: [],
+		closed: false
+	},
+
+	initialize: function Path(arg) {
+		this._closed = false;
+		this._segments = [];
+		this._version = 0;
+		var segments = Array.isArray(arg)
+			? typeof arg[0] === 'object'
+				? arg
+				: arguments
+			: arg && (arg.size === undefined && (arg.x !== undefined
+					|| arg.point !== undefined))
+				? arguments
+				: null;
+		if (segments && segments.length > 0) {
+			this.setSegments(segments);
+		} else {
+			this._curves = undefined;
+			this._segmentSelection = 0;
+			if (!segments && typeof arg === 'string') {
+				this.setPathData(arg);
+				arg = null;
+			}
+		}
+		this._initialize(!segments && arg);
+	},
+
+	_equals: function(item) {
+		return this._closed === item._closed
+				&& Base.equals(this._segments, item._segments);
+	},
+
+	copyContent: function(source) {
+		this.setSegments(source._segments);
+		this._closed = source._closed;
+		var clockwise = source._clockwise;
+		if (clockwise !== undefined)
+			this._clockwise = clockwise;
+	},
+
+	_changed: function _changed(flags) {
+		_changed.base.call(this, flags);
+		if (flags & 8) {
+			this._length = this._area = this._clockwise = this._monoCurves =
+					undefined;
+			if (flags & 16) {
+				this._version++;
+			} else if (this._curves) {
+			   for (var i = 0, l = this._curves.length; i < l; i++)
+					this._curves[i]._changed();
+			}
+		} else if (flags & 32) {
+			this._bounds = undefined;
+		}
+	},
+
+	getStyle: function() {
+		var parent = this._parent;
+		return (parent instanceof CompoundPath ? parent : this)._style;
+	},
+
+	getSegments: function() {
+		return this._segments;
+	},
+
+	setSegments: function(segments) {
+		var fullySelected = this.isFullySelected();
+		this._segments.length = 0;
+		this._segmentSelection = 0;
+		this._curves = undefined;
+		if (segments && segments.length > 0)
+			this._add(Segment.readAll(segments));
+		if (fullySelected)
+			this.setFullySelected(true);
+	},
+
+	getFirstSegment: function() {
+		return this._segments[0];
+	},
+
+	getLastSegment: function() {
+		return this._segments[this._segments.length - 1];
+	},
+
+	getCurves: function() {
+		var curves = this._curves,
+			segments = this._segments;
+		if (!curves) {
+			var length = this._countCurves();
+			curves = this._curves = new Array(length);
+			for (var i = 0; i < length; i++)
+				curves[i] = new Curve(this, segments[i],
+					segments[i + 1] || segments[0]);
+		}
+		return curves;
+	},
+
+	getFirstCurve: function() {
+		return this.getCurves()[0];
+	},
+
+	getLastCurve: function() {
+		var curves = this.getCurves();
+		return curves[curves.length - 1];
+	},
+
+	isClosed: function() {
+		return this._closed;
+	},
+
+	setClosed: function(closed) {
+		if (this._closed != (closed = !!closed)) {
+			this._closed = closed;
+			if (this._curves) {
+				var length = this._curves.length = this._countCurves();
+				if (closed)
+					this._curves[length - 1] = new Curve(this,
+						this._segments[length - 1], this._segments[0]);
+			}
+			this._changed(25);
+		}
+	}
+}, {
+	beans: true,
+
+	getPathData: function(_matrix, _precision) {
+		var segments = this._segments,
+			length = segments.length,
+			f = new Formatter(_precision),
+			coords = new Array(6),
+			first = true,
+			curX, curY,
+			prevX, prevY,
+			inX, inY,
+			outX, outY,
+			parts = [];
+
+		function addSegment(segment, skipLine) {
+			segment._transformCoordinates(_matrix, coords);
+			curX = coords[0];
+			curY = coords[1];
+			if (first) {
+				parts.push('M' + f.pair(curX, curY));
+				first = false;
+			} else {
+				inX = coords[2];
+				inY = coords[3];
+				if (inX === curX && inY === curY
+						&& outX === prevX && outY === prevY) {
+					if (!skipLine)
+						parts.push('l' + f.pair(curX - prevX, curY - prevY));
+				} else {
+					parts.push('c' + f.pair(outX - prevX, outY - prevY)
+							+ ' ' + f.pair(inX - prevX, inY - prevY)
+							+ ' ' + f.pair(curX - prevX, curY - prevY));
+				}
+			}
+			prevX = curX;
+			prevY = curY;
+			outX = coords[4];
+			outY = coords[5];
+		}
+
+		if (length === 0)
+			return '';
+
+		for (var i = 0; i < length; i++)
+			addSegment(segments[i]);
+		if (this._closed && length > 0) {
+			addSegment(segments[0], true);
+			parts.push('z');
+		}
+		return parts.join('');
+	},
+
+	isEmpty: function() {
+		return this._segments.length === 0;
+	},
+
+	_transformContent: function(matrix) {
+		var segments = this._segments,
+			coords = new Array(6);
+		for (var i = 0, l = segments.length; i < l; i++)
+			segments[i]._transformCoordinates(matrix, coords, true);
+		return true;
+	},
+
+	_add: function(segs, index) {
+		var segments = this._segments,
+			curves = this._curves,
+			amount = segs.length,
+			append = index == null,
+			index = append ? segments.length : index;
+		for (var i = 0; i < amount; i++) {
+			var segment = segs[i];
+			if (segment._path)
+				segment = segs[i] = segment.clone();
+			segment._path = this;
+			segment._index = index + i;
+			if (segment._selection)
+				this._updateSelection(segment, 0, segment._selection);
+		}
+		if (append) {
+			segments.push.apply(segments, segs);
+		} else {
+			segments.splice.apply(segments, [index, 0].concat(segs));
+			for (var i = index + amount, l = segments.length; i < l; i++)
+				segments[i]._index = i;
+		}
+		if (curves) {
+			var total = this._countCurves(),
+				start = index > 0 && index + amount - 1 === total ? index - 1
+					: index,
+				insert = start,
+				end = Math.min(start + amount, total);
+			if (segs._curves) {
+				curves.splice.apply(curves, [start, 0].concat(segs._curves));
+				insert += segs._curves.length;
+			}
+			for (var i = insert; i < end; i++)
+				curves.splice(i, 0, new Curve(this, null, null));
+			this._adjustCurves(start, end);
+		}
+		this._changed(25);
+		return segs;
+	},
+
+	_adjustCurves: function(start, end) {
+		var segments = this._segments,
+			curves = this._curves,
+			curve;
+		for (var i = start; i < end; i++) {
+			curve = curves[i];
+			curve._path = this;
+			curve._segment1 = segments[i];
+			curve._segment2 = segments[i + 1] || segments[0];
+			curve._changed();
+		}
+		if (curve = curves[this._closed && start === 0 ? segments.length - 1
+				: start - 1]) {
+			curve._segment2 = segments[start] || segments[0];
+			curve._changed();
+		}
+		if (curve = curves[end]) {
+			curve._segment1 = segments[end];
+			curve._changed();
+		}
+	},
+
+	_countCurves: function() {
+		var length = this._segments.length;
+		return !this._closed && length > 0 ? length - 1 : length;
+	},
+
+	add: function(segment1 ) {
+		return arguments.length > 1 && typeof segment1 !== 'number'
+			? this._add(Segment.readAll(arguments))
+			: this._add([ Segment.read(arguments) ])[0];
+	},
+
+	insert: function(index, segment1 ) {
+		return arguments.length > 2 && typeof segment1 !== 'number'
+			? this._add(Segment.readAll(arguments, 1), index)
+			: this._add([ Segment.read(arguments, 1) ], index)[0];
+	},
+
+	addSegment: function() {
+		return this._add([ Segment.read(arguments) ])[0];
+	},
+
+	insertSegment: function(index ) {
+		return this._add([ Segment.read(arguments, 1) ], index)[0];
+	},
+
+	addSegments: function(segments) {
+		return this._add(Segment.readAll(segments));
+	},
+
+	insertSegments: function(index, segments) {
+		return this._add(Segment.readAll(segments), index);
+	},
+
+	removeSegment: function(index) {
+		return this.removeSegments(index, index + 1)[0] || null;
+	},
+
+	removeSegments: function(start, end, _includeCurves) {
+		start = start || 0;
+		end = Base.pick(end, this._segments.length);
+		var segments = this._segments,
+			curves = this._curves,
+			count = segments.length,
+			removed = segments.splice(start, end - start),
+			amount = removed.length;
+		if (!amount)
+			return removed;
+		for (var i = 0; i < amount; i++) {
+			var segment = removed[i];
+			if (segment._selection)
+				this._updateSelection(segment, segment._selection, 0);
+			segment._index = segment._path = null;
+		}
+		for (var i = start, l = segments.length; i < l; i++)
+			segments[i]._index = i;
+		if (curves) {
+			var index = start > 0 && end === count + (this._closed ? 1 : 0)
+					? start - 1
+					: start,
+				curves = curves.splice(index, amount);
+			for (var i = curves.length - 1; i >= 0; i--)
+				curves[i]._path = null;
+			if (_includeCurves)
+				removed._curves = curves.slice(1);
+			this._adjustCurves(index, index);
+		}
+		this._changed(25);
+		return removed;
+	},
+
+	clear: '#removeSegments',
+
+	hasHandles: function() {
+		var segments = this._segments;
+		for (var i = 0, l = segments.length; i < l; i++) {
+			if (segments[i].hasHandles())
+				return true;
+		}
+		return false;
+	},
+
+	clearHandles: function() {
+		var segments = this._segments;
+		for (var i = 0, l = segments.length; i < l; i++)
+			segments[i].clearHandles();
+	},
+
+	getLength: function() {
+		if (this._length == null) {
+			var curves = this.getCurves(),
+				length = 0;
+			for (var i = 0, l = curves.length; i < l; i++)
+				length += curves[i].getLength();
+			this._length = length;
+		}
+		return this._length;
+	},
+
+	getArea: function(_closed) {
+		var cached = _closed === undefined,
+			area = this._area;
+		if (!cached || area == null) {
+			var segments = this._segments,
+				count = segments.length,
+				closed = cached ? this._closed : _closed,
+				last = count - 1;
+			area = 0;
+			for (var i = 0, l = closed ? count : last; i < l; i++) {
+				area += Curve.getArea(Curve.getValues(
+						segments[i], segments[i < last ? i + 1 : 0]));
+			}
+			if (cached)
+				this._area = area;
+		}
+		return area;
+	},
+
+	isClockwise: function() {
+		if (this._clockwise !== undefined)
+			return this._clockwise;
+		return this.getArea() >= 0;
+	},
+
+	setClockwise: function(clockwise) {
+		if (this.isClockwise() != (clockwise = !!clockwise))
+			this.reverse();
+		this._clockwise = clockwise;
+	},
+
+	isFullySelected: function() {
+		var length = this._segments.length;
+		return this.isSelected() && length > 0 && this._segmentSelection
+				=== length * 7;
+	},
+
+	setFullySelected: function(selected) {
+		if (selected)
+			this._selectSegments(true);
+		this.setSelected(selected);
+	},
+
+	setSelection: function setSelection(selection) {
+		if (!(selection & 1))
+			this._selectSegments(false);
+		setSelection.base.call(this, selection);
+	},
+
+	_selectSegments: function(selected) {
+		var segments = this._segments,
+			length = segments.length,
+			selection = selected ? 7 : 0;
+		this._segmentSelection = selection * length;
+		for (var i = 0; i < length; i++)
+			segments[i]._selection = selection;
+	},
+
+	_updateSelection: function(segment, oldSelection, newSelection) {
+		segment._selection = newSelection;
+		var selection = this._segmentSelection += newSelection - oldSelection;
+		if (selection > 0)
+			this.setSelected(true);
+	},
+
+	splitAt: function(location) {
+		var loc = typeof location === 'number'
+				? this.getLocationAt(location) : location,
+			index = loc && loc.index,
+			time = loc && loc.time,
+			tMin = 4e-7,
+			tMax = 1 - tMin;
+		if (time >= tMax) {
+			index++;
+			time = 0;
+		}
+		var curves = this.getCurves();
+		if (index >= 0 && index < curves.length) {
+			if (time >= tMin) {
+				curves[index++].divideAtTime(time);
+			}
+			var segs = this.removeSegments(index, this._segments.length, true),
+				path;
+			if (this._closed) {
+				this.setClosed(false);
+				path = this;
+			} else {
+				path = new Path(Item.NO_INSERT);
+				path.insertAbove(this, true);
+				path.copyAttributes(this);
+			}
+			path._add(segs, 0);
+			this.addSegment(segs[0]);
+			return path;
+		}
+		return null;
+	},
+
+	split: function(index, time) {
+		var curve,
+			location = time === undefined ? index
+				: (curve = this.getCurves()[index])
+					&& curve.getLocationAtTime(time);
+		return location != null ? this.splitAt(location) : null;
+	},
+
+	join: function(path, tolerance) {
+		var epsilon = tolerance || 0;
+		if (path && path !== this) {
+			var segments = path._segments,
+				last1 = this.getLastSegment(),
+				last2 = path.getLastSegment();
+			if (!last2)
+				return this;
+			if (last1 && last1._point.isClose(last2._point, epsilon))
+				path.reverse();
+			var first2 = path.getFirstSegment();
+			if (last1 && last1._point.isClose(first2._point, epsilon)) {
+				last1.setHandleOut(first2._handleOut);
+				this._add(segments.slice(1));
+			} else {
+				var first1 = this.getFirstSegment();
+				if (first1 && first1._point.isClose(first2._point, epsilon))
+					path.reverse();
+				last2 = path.getLastSegment();
+				if (first1 && first1._point.isClose(last2._point, epsilon)) {
+					first1.setHandleIn(last2._handleIn);
+					this._add(segments.slice(0, segments.length - 1), 0);
+				} else {
+					this._add(segments.slice());
+				}
+			}
+			if (path._closed)
+				this._add([segments[0]]);
+			path.remove();
+		}
+		var first = this.getFirstSegment(),
+			last = this.getLastSegment();
+		if (first !== last && first._point.isClose(last._point, epsilon)) {
+			first.setHandleIn(last._handleIn);
+			last.remove();
+			this.setClosed(true);
+		}
+		return this;
+	},
+
+	reduce: function(options) {
+		var curves = this.getCurves(),
+			simplify = options && options.simplify,
+			tolerance = simplify ? 2e-7 : 0;
+		for (var i = curves.length - 1; i >= 0; i--) {
+			var curve = curves[i];
+			if (!curve.hasHandles() && (curve.getLength() < tolerance
+					|| simplify && curve.isCollinear(curve.getNext())))
+				curve.remove();
+		}
+		return this;
+	},
+
+	reverse: function() {
+		this._segments.reverse();
+		for (var i = 0, l = this._segments.length; i < l; i++) {
+			var segment = this._segments[i];
+			var handleIn = segment._handleIn;
+			segment._handleIn = segment._handleOut;
+			segment._handleOut = handleIn;
+			segment._index = i;
+		}
+		this._curves = null;
+		if (this._clockwise !== undefined)
+			this._clockwise = !this._clockwise;
+		this._changed(9);
+	},
+
+	flatten: function(flatness) {
+		var iterator = new PathIterator(this, flatness || 0.25, 256, true),
+			parts = iterator.parts,
+			length = parts.length,
+			segments = [];
+		for (var i = 0; i < length; i++) {
+			segments.push(new Segment(parts[i].curve.slice(0, 2)));
+		}
+		if (!this._closed && length > 0) {
+			segments.push(new Segment(parts[length - 1].curve.slice(6)));
+		}
+		this.setSegments(segments);
+	},
+
+	simplify: function(tolerance) {
+		var segments = new PathFitter(this).fit(tolerance || 2.5);
+		if (segments)
+			this.setSegments(segments);
+		return !!segments;
+	},
+
+	smooth: function(options) {
+		var that = this,
+			opts = options || {},
+			type = opts.type || 'asymmetric',
+			segments = this._segments,
+			length = segments.length,
+			closed = this._closed;
+
+		function getIndex(value, _default) {
+			var index = value && value.index;
+			if (index != null) {
+				var path = value.path;
+				if (path && path !== that)
+					throw new Error(value._class + ' ' + index + ' of ' + path
+							+ ' is not part of ' + that);
+				if (_default && value instanceof Curve)
+					index++;
+			} else {
+				index = typeof value === 'number' ? value : _default;
+			}
+			return Math.min(index < 0 && closed
+					? index % length
+					: index < 0 ? index + length : index, length - 1);
+		}
+
+		var loop = closed && opts.from === undefined && opts.to === undefined,
+			from = getIndex(opts.from, 0),
+			to = getIndex(opts.to, length - 1);
+
+		if (from > to) {
+			if (closed) {
+				from -= length;
+			} else {
+				var tmp = from;
+				from = to;
+				to = tmp;
+			}
+		}
+		if (/^(?:asymmetric|continuous)$/.test(type)) {
+			var asymmetric = type === 'asymmetric',
+				min = Math.min,
+				amount = to - from + 1,
+				n = amount - 1,
+				padding = loop ? min(amount, 4) : 1,
+				paddingLeft = padding,
+				paddingRight = padding,
+				knots = [];
+			if (!closed) {
+				paddingLeft = min(1, from);
+				paddingRight = min(1, length - to - 1);
+			}
+			n += paddingLeft + paddingRight;
+			if (n <= 1)
+				return;
+			for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
+				knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
+			}
+
+			var x = knots[0]._x + 2 * knots[1]._x,
+				y = knots[0]._y + 2 * knots[1]._y,
+				f = 2,
+				n_1 = n - 1,
+				rx = [x],
+				ry = [y],
+				rf = [f],
+				px = [],
+				py = [];
+			for (var i = 1; i < n; i++) {
+				var internal = i < n_1,
+					a = internal ? 1 : asymmetric ? 1 : 2,
+					b = internal ? 4 : asymmetric ? 2 : 7,
+					u = internal ? 4 : asymmetric ? 3 : 8,
+					v = internal ? 2 : asymmetric ? 0 : 1,
+					m = a / f;
+				f = rf[i] = b - m;
+				x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
+				y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
+			}
+
+			px[n_1] = rx[n_1] / rf[n_1];
+			py[n_1] = ry[n_1] / rf[n_1];
+			for (var i = n - 2; i >= 0; i--) {
+				px[i] = (rx[i] - px[i + 1]) / rf[i];
+				py[i] = (ry[i] - py[i + 1]) / rf[i];
+			}
+			px[n] = (3 * knots[n]._x - px[n_1]) / 2;
+			py[n] = (3 * knots[n]._y - py[n_1]) / 2;
+
+			for (var i = paddingLeft, max = n - paddingRight, j = from;
+					i <= max; i++, j++) {
+				var segment = segments[j < 0 ? j + length : j],
+					pt = segment._point,
+					hx = px[i] - pt._x,
+					hy = py[i] - pt._y;
+				if (loop || i < max)
+					segment.setHandleOut(hx, hy);
+				if (loop || i > paddingLeft)
+					segment.setHandleIn(-hx, -hy);
+			}
+		} else {
+			for (var i = from; i <= to; i++) {
+				segments[i < 0 ? i + length : i].smooth(opts,
+						!loop && i === from, !loop && i === to);
+			}
+		}
+	},
+
+	toShape: function(insert) {
+		if (!this._closed)
+			return null;
+
+		var segments = this._segments,
+			type,
+			size,
+			radius,
+			topCenter;
+
+		function isCollinear(i, j) {
+			var seg1 = segments[i],
+				seg2 = seg1.getNext(),
+				seg3 = segments[j],
+				seg4 = seg3.getNext();
+			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+					&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
+					&& seg2._point.subtract(seg1._point).isCollinear(
+						seg4._point.subtract(seg3._point));
+		}
+
+		function isOrthogonal(i) {
+			var seg2 = segments[i],
+				seg1 = seg2.getPrevious(),
+				seg3 = seg2.getNext();
+			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+					&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
+					&& seg2._point.subtract(seg1._point).isOrthogonal(
+						seg3._point.subtract(seg2._point));
+		}
+
+		function isArc(i) {
+			var seg1 = segments[i],
+				seg2 = seg1.getNext(),
+				handle1 = seg1._handleOut,
+				handle2 = seg2._handleIn,
+				kappa = 0.5522847498307936;
+			if (handle1.isOrthogonal(handle2)) {
+				var pt1 = seg1._point,
+					pt2 = seg2._point,
+					corner = new Line(pt1, handle1, true).intersect(
+							new Line(pt2, handle2, true), true);
+				return corner && Numerical.isZero(handle1.getLength() /
+						corner.subtract(pt1).getLength() - kappa)
+					&& Numerical.isZero(handle2.getLength() /
+						corner.subtract(pt2).getLength() - kappa);
+			}
+			return false;
+		}
+
+		function getDistance(i, j) {
+			return segments[i]._point.getDistance(segments[j]._point);
+		}
+
+		if (!this.hasHandles() && segments.length === 4
+				&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {
+			type = Shape.Rectangle;
+			size = new Size(getDistance(0, 3), getDistance(0, 1));
+			topCenter = segments[1]._point.add(segments[2]._point).divide(2);
+		} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
+				&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {
+			type = Shape.Rectangle;
+			size = new Size(getDistance(1, 6), getDistance(0, 3));
+			radius = size.subtract(new Size(getDistance(0, 7),
+					getDistance(1, 2))).divide(2);
+			topCenter = segments[3]._point.add(segments[4]._point).divide(2);
+		} else if (segments.length === 4
+				&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
+			if (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {
+				type = Shape.Circle;
+				radius = getDistance(0, 2) / 2;
+			} else {
+				type = Shape.Ellipse;
+				radius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);
+			}
+			topCenter = segments[1]._point;
+		}
+
+		if (type) {
+			var center = this.getPosition(true),
+				shape = new type({
+					center: center,
+					size: size,
+					radius: radius,
+					insert: false
+				});
+			shape.copyAttributes(this, true);
+			shape._matrix.prepend(this._matrix);
+			shape.rotate(topCenter.subtract(center).getAngle() + 90);
+			if (insert === undefined || insert)
+				shape.insertAbove(this);
+			return shape;
+		}
+		return null;
+	},
+
+	toPath: '#clone',
+
+	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
+		var that = this,
+			style = this.getStyle(),
+			segments = this._segments,
+			numSegments = segments.length,
+			closed = this._closed,
+			tolerancePadding = options._tolerancePadding,
+			strokePadding = tolerancePadding,
+			join, cap, miterLimit,
+			area, loc, res,
+			hitStroke = options.stroke && style.hasStroke(),
+			hitFill = options.fill && style.hasFill(),
+			hitCurves = options.curves,
+			strokeRadius = hitStroke
+					? style.getStrokeWidth() / 2
+					: hitFill && options.tolerance > 0 || hitCurves
+						? 0 : null;
+		if (strokeRadius !== null) {
+			if (strokeRadius > 0) {
+				join = style.getStrokeJoin();
+				cap = style.getStrokeCap();
+				miterLimit = strokeRadius * style.getMiterLimit();
+				strokePadding = strokePadding.add(
+					Path._getStrokePadding(strokeRadius, strokeMatrix));
+			} else {
+				join = cap = 'round';
+			}
+		}
+
+		function isCloseEnough(pt, padding) {
+			return point.subtract(pt).divide(padding).length <= 1;
+		}
+
+		function checkSegmentPoint(seg, pt, name) {
+			if (!options.selected || pt.isSelected()) {
+				var anchor = seg._point;
+				if (pt !== anchor)
+					pt = pt.add(anchor);
+				if (isCloseEnough(pt, strokePadding)) {
+					return new HitResult(name, that, {
+						segment: seg,
+						point: pt
+					});
+				}
+			}
+		}
+
+		function checkSegmentPoints(seg, ends) {
+			return (ends || options.segments)
+				&& checkSegmentPoint(seg, seg._point, 'segment')
+				|| (!ends && options.handles) && (
+					checkSegmentPoint(seg, seg._handleIn, 'handle-in') ||
+					checkSegmentPoint(seg, seg._handleOut, 'handle-out'));
+		}
+
+		function addToArea(point) {
+			area.add(point);
+		}
+
+		function checkSegmentStroke(segment) {
+			if (join !== 'round' || cap !== 'round') {
+				area = new Path({ internal: true, closed: true });
+				if (closed || segment._index > 0
+						&& segment._index < numSegments - 1) {
+					if (join !== 'round' && (segment._handleIn.isZero()
+							|| segment._handleOut.isZero()))
+						Path._addBevelJoin(segment, join, strokeRadius,
+							   miterLimit, null, strokeMatrix, addToArea, true);
+				} else if (cap !== 'round') {
+					Path._addSquareCap(segment, cap, strokeRadius, null,
+							strokeMatrix, addToArea, true);
+				}
+				if (!area.isEmpty()) {
+					var loc;
+					return area.contains(point)
+						|| (loc = area.getNearestLocation(point))
+							&& isCloseEnough(loc.getPoint(), tolerancePadding);
+				}
+			}
+			return isCloseEnough(segment._point, strokePadding);
+		}
+
+		if (options.ends && !options.segments && !closed) {
+			if (res = checkSegmentPoints(segments[0], true)
+					|| checkSegmentPoints(segments[numSegments - 1], true))
+				return res;
+		} else if (options.segments || options.handles) {
+			for (var i = 0; i < numSegments; i++)
+				if (res = checkSegmentPoints(segments[i]))
+					return res;
+		}
+		if (strokeRadius !== null) {
+			loc = this.getNearestLocation(point);
+			if (loc) {
+				var time = loc.getTime();
+				if (time === 0 || time === 1 && numSegments > 1) {
+					if (!checkSegmentStroke(loc.getSegment()))
+						loc = null;
+				} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
+					loc = null;
+				}
+			}
+			if (!loc && join === 'miter' && numSegments > 1) {
+				for (var i = 0; i < numSegments; i++) {
+					var segment = segments[i];
+					if (point.getDistance(segment._point) <= miterLimit
+							&& checkSegmentStroke(segment)) {
+						loc = segment.getLocation();
+						break;
+					}
+				}
+			}
+		}
+		return !loc && hitFill && this._contains(point)
+				|| loc && !hitStroke && !hitCurves
+					? new HitResult('fill', this)
+					: loc
+						? new HitResult(hitStroke ? 'stroke' : 'curve', this, {
+							location: loc,
+							point: loc.getPoint()
+						})
+						: null;
+	}
+
+}, Base.each(Curve._evaluateMethods,
+	function(name) {
+		this[name + 'At'] = function(offset) {
+			var loc = this.getLocationAt(offset);
+			return loc && loc[name]();
+		};
+	},
+{
+	beans: false,
+
+	getLocationOf: function() {
+		var point = Point.read(arguments),
+			curves = this.getCurves();
+		for (var i = 0, l = curves.length; i < l; i++) {
+			var loc = curves[i].getLocationOf(point);
+			if (loc)
+				return loc;
+		}
+		return null;
+	},
+
+	getOffsetOf: function() {
+		var loc = this.getLocationOf.apply(this, arguments);
+		return loc ? loc.getOffset() : null;
+	},
+
+	getLocationAt: function(offset) {
+		var curves = this.getCurves(),
+			length = 0;
+		for (var i = 0, l = curves.length; i < l; i++) {
+			var start = length,
+				curve = curves[i];
+			length += curve.getLength();
+			if (length > offset) {
+				return curve.getLocationAt(offset - start);
+			}
+		}
+		if (curves.length > 0 && offset <= this.getLength())
+			return new CurveLocation(curves[curves.length - 1], 1);
+		return null;
+	}
+
+}),
+new function() {
+
+	function drawHandles(ctx, segments, matrix, size) {
+		var half = size / 2,
+			coords = new Array(6),
+			pX, pY;
+
+		function drawHandle(index) {
+			var hX = coords[index],
+				hY = coords[index + 1];
+			if (pX != hX || pY != hY) {
+				ctx.beginPath();
+				ctx.moveTo(pX, pY);
+				ctx.lineTo(hX, hY);
+				ctx.stroke();
+				ctx.beginPath();
+				ctx.arc(hX, hY, half, 0, Math.PI * 2, true);
+				ctx.fill();
+			}
+		}
+
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var segment = segments[i],
+				selection = segment._selection;
+			segment._transformCoordinates(matrix, coords);
+			pX = coords[0];
+			pY = coords[1];
+			if (selection & 2)
+				drawHandle(2);
+			if (selection & 4)
+				drawHandle(4);
+			ctx.fillRect(pX - half, pY - half, size, size);
+			if (!(selection & 1)) {
+				var fillStyle = ctx.fillStyle;
+				ctx.fillStyle = '#ffffff';
+				ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);
+				ctx.fillStyle = fillStyle;
+			}
+		}
+	}
+
+	function drawSegments(ctx, path, matrix) {
+		var segments = path._segments,
+			length = segments.length,
+			coords = new Array(6),
+			first = true,
+			curX, curY,
+			prevX, prevY,
+			inX, inY,
+			outX, outY;
+
+		function drawSegment(segment) {
+			if (matrix) {
+				segment._transformCoordinates(matrix, coords);
+				curX = coords[0];
+				curY = coords[1];
+			} else {
+				var point = segment._point;
+				curX = point._x;
+				curY = point._y;
+			}
+			if (first) {
+				ctx.moveTo(curX, curY);
+				first = false;
+			} else {
+				if (matrix) {
+					inX = coords[2];
+					inY = coords[3];
+				} else {
+					var handle = segment._handleIn;
+					inX = curX + handle._x;
+					inY = curY + handle._y;
+				}
+				if (inX === curX && inY === curY
+						&& outX === prevX && outY === prevY) {
+					ctx.lineTo(curX, curY);
+				} else {
+					ctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);
+				}
+			}
+			prevX = curX;
+			prevY = curY;
+			if (matrix) {
+				outX = coords[4];
+				outY = coords[5];
+			} else {
+				var handle = segment._handleOut;
+				outX = prevX + handle._x;
+				outY = prevY + handle._y;
+			}
+		}
+
+		for (var i = 0; i < length; i++)
+			drawSegment(segments[i]);
+		if (path._closed && length > 0)
+			drawSegment(segments[0]);
+	}
+
+	return {
+		_draw: function(ctx, param, viewMatrix, strokeMatrix) {
+			var dontStart = param.dontStart,
+				dontPaint = param.dontFinish || param.clip,
+				style = this.getStyle(),
+				hasFill = style.hasFill(),
+				hasStroke = style.hasStroke(),
+				dashArray = style.getDashArray(),
+				dashLength = !paper.support.nativeDash && hasStroke
+						&& dashArray && dashArray.length;
+
+			if (!dontStart)
+				ctx.beginPath();
+
+			if (hasFill || hasStroke && !dashLength || dontPaint) {
+				drawSegments(ctx, this, strokeMatrix);
+				if (this._closed)
+					ctx.closePath();
+			}
+
+			function getOffset(i) {
+				return dashArray[((i % dashLength) + dashLength) % dashLength];
+			}
+
+			if (!dontPaint && (hasFill || hasStroke)) {
+				this._setStyles(ctx, param, viewMatrix);
+				if (hasFill) {
+					ctx.fill(style.getFillRule());
+					ctx.shadowColor = 'rgba(0,0,0,0)';
+				}
+				if (hasStroke) {
+					if (dashLength) {
+						if (!dontStart)
+							ctx.beginPath();
+						var iterator = new PathIterator(this, 0.25, 32, false,
+								strokeMatrix),
+							length = iterator.length,
+							from = -style.getDashOffset(), to,
+							i = 0;
+						from = from % length;
+						while (from > 0) {
+							from -= getOffset(i--) + getOffset(i--);
+						}
+						while (from < length) {
+							to = from + getOffset(i++);
+							if (from > 0 || to > 0)
+								iterator.drawPart(ctx,
+										Math.max(from, 0), Math.max(to, 0));
+							from = to + getOffset(i++);
+						}
+					}
+					ctx.stroke();
+				}
+			}
+		},
+
+		_drawSelected: function(ctx, matrix) {
+			ctx.beginPath();
+			drawSegments(ctx, this, matrix);
+			ctx.stroke();
+			drawHandles(ctx, this._segments, matrix, paper.settings.handleSize);
+		}
+	};
+},
+new function() {
+	function getCurrentSegment(that) {
+		var segments = that._segments;
+		if (segments.length === 0)
+			throw new Error('Use a moveTo() command first');
+		return segments[segments.length - 1];
+	}
+
+	return {
+		moveTo: function() {
+			var segments = this._segments;
+			if (segments.length === 1)
+				this.removeSegment(0);
+			if (!segments.length)
+				this._add([ new Segment(Point.read(arguments)) ]);
+		},
+
+		moveBy: function() {
+			throw new Error('moveBy() is unsupported on Path items.');
+		},
+
+		lineTo: function() {
+			this._add([ new Segment(Point.read(arguments)) ]);
+		},
+
+		cubicCurveTo: function() {
+			var handle1 = Point.read(arguments),
+				handle2 = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this);
+			current.setHandleOut(handle1.subtract(current._point));
+			this._add([ new Segment(to, handle2.subtract(to)) ]);
+		},
+
+		quadraticCurveTo: function() {
+			var handle = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.cubicCurveTo(
+				handle.add(current.subtract(handle).multiply(1 / 3)),
+				handle.add(to.subtract(handle).multiply(1 / 3)),
+				to
+			);
+		},
+
+		curveTo: function() {
+			var through = Point.read(arguments),
+				to = Point.read(arguments),
+				t = Base.pick(Base.read(arguments), 0.5),
+				t1 = 1 - t,
+				current = getCurrentSegment(this)._point,
+				handle = through.subtract(current.multiply(t1 * t1))
+					.subtract(to.multiply(t * t)).divide(2 * t * t1);
+			if (handle.isNaN())
+				throw new Error(
+					'Cannot put a curve through points with parameter = ' + t);
+			this.quadraticCurveTo(handle, to);
+		},
+
+		arcTo: function() {
+			var current = getCurrentSegment(this),
+				from = current._point,
+				to = Point.read(arguments),
+				through,
+				peek = Base.peek(arguments),
+				clockwise = Base.pick(peek, true),
+				center, extent, vector, matrix;
+			if (typeof clockwise === 'boolean') {
+				var middle = from.add(to).divide(2),
+				through = middle.add(middle.subtract(from).rotate(
+						clockwise ? -90 : 90));
+			} else if (Base.remain(arguments) <= 2) {
+				through = to;
+				to = Point.read(arguments);
+			} else {
+				var radius = Size.read(arguments),
+					isZero = Numerical.isZero;
+				if (isZero(radius.width) || isZero(radius.height))
+					return this.lineTo(to);
+				var rotation = Base.read(arguments),
+					clockwise = !!Base.read(arguments),
+					large = !!Base.read(arguments),
+					middle = from.add(to).divide(2),
+					pt = from.subtract(middle).rotate(-rotation),
+					x = pt.x,
+					y = pt.y,
+					abs = Math.abs,
+					rx = abs(radius.width),
+					ry = abs(radius.height),
+					rxSq = rx * rx,
+					rySq = ry * ry,
+					xSq = x * x,
+					ySq = y * y;
+				var factor = Math.sqrt(xSq / rxSq + ySq / rySq);
+				if (factor > 1) {
+					rx *= factor;
+					ry *= factor;
+					rxSq = rx * rx;
+					rySq = ry * ry;
+				}
+				factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
+						(rxSq * ySq + rySq * xSq);
+				if (abs(factor) < 1e-12)
+					factor = 0;
+				if (factor < 0)
+					throw new Error(
+							'Cannot create an arc with the given arguments');
+				center = new Point(rx * y / ry, -ry * x / rx)
+						.multiply((large === clockwise ? -1 : 1)
+							* Math.sqrt(factor))
+						.rotate(rotation).add(middle);
+				matrix = new Matrix().translate(center).rotate(rotation)
+						.scale(rx, ry);
+				vector = matrix._inverseTransform(from);
+				extent = vector.getDirectedAngle(matrix._inverseTransform(to));
+				if (!clockwise && extent > 0)
+					extent -= 360;
+				else if (clockwise && extent < 0)
+					extent += 360;
+			}
+			if (through) {
+				var l1 = new Line(from.add(through).divide(2),
+							through.subtract(from).rotate(90), true),
+					l2 = new Line(through.add(to).divide(2),
+							to.subtract(through).rotate(90), true),
+					line = new Line(from, to),
+					throughSide = line.getSide(through);
+				center = l1.intersect(l2, true);
+				if (!center) {
+					if (!throughSide)
+						return this.lineTo(to);
+					throw new Error(
+							'Cannot create an arc with the given arguments');
+				}
+				vector = from.subtract(center);
+				extent = vector.getDirectedAngle(to.subtract(center));
+				var centerSide = line.getSide(center);
+				if (centerSide === 0) {
+					extent = throughSide * Math.abs(extent);
+				} else if (throughSide === centerSide) {
+					extent += extent < 0 ? 360 : -360;
+				}
+			}
+			var ext = Math.abs(extent),
+				count = ext >= 360 ? 4 : Math.ceil(ext / 90),
+				inc = extent / count,
+				half = inc * Math.PI / 360,
+				z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),
+				segments = [];
+			for (var i = 0; i <= count; i++) {
+				var pt = to,
+					out = null;
+				if (i < count) {
+					out = vector.rotate(90).multiply(z);
+					if (matrix) {
+						pt = matrix._transformPoint(vector);
+						out = matrix._transformPoint(vector.add(out))
+								.subtract(pt);
+					} else {
+						pt = center.add(vector);
+					}
+				}
+				if (i === 0) {
+					current.setHandleOut(out);
+				} else {
+					var _in = vector.rotate(-90).multiply(z);
+					if (matrix) {
+						_in = matrix._transformPoint(vector.add(_in))
+								.subtract(pt);
+					}
+					segments.push(new Segment(pt, _in, out));
+				}
+				vector = vector.rotate(inc);
+			}
+			this._add(segments);
+		},
+
+		lineBy: function() {
+			var to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.lineTo(current.add(to));
+		},
+
+		curveBy: function() {
+			var through = Point.read(arguments),
+				to = Point.read(arguments),
+				parameter = Base.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.curveTo(current.add(through), current.add(to), parameter);
+		},
+
+		cubicCurveBy: function() {
+			var handle1 = Point.read(arguments),
+				handle2 = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.cubicCurveTo(current.add(handle1), current.add(handle2),
+					current.add(to));
+		},
+
+		quadraticCurveBy: function() {
+			var handle = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.quadraticCurveTo(current.add(handle), current.add(to));
+		},
+
+		arcBy: function() {
+			var current = getCurrentSegment(this)._point,
+				point = current.add(Point.read(arguments)),
+				clockwise = Base.pick(Base.peek(arguments), true);
+			if (typeof clockwise === 'boolean') {
+				this.arcTo(point, clockwise);
+			} else {
+				this.arcTo(point, current.add(Point.read(arguments)));
+			}
+		},
+
+		closePath: function(tolerance) {
+			this.setClosed(true);
+			this.join(this, tolerance);
+		}
+	};
+}, {
+
+	_getBounds: function(matrix, options) {
+		var method = options.handle
+				? 'getHandleBounds'
+				: options.stroke
+				? 'getStrokeBounds'
+				: 'getBounds';
+		return Path[method](this._segments, this._closed, this, matrix, options);
+	},
+
+statics: {
+	getBounds: function(segments, closed, path, matrix, options, strokePadding) {
+		var first = segments[0];
+		if (!first)
+			return new Rectangle();
+		var coords = new Array(6),
+			prevCoords = first._transformCoordinates(matrix, new Array(6)),
+			min = prevCoords.slice(0, 2),
+			max = min.slice(),
+			roots = new Array(2);
+
+		function processSegment(segment) {
+			segment._transformCoordinates(matrix, coords);
+			for (var i = 0; i < 2; i++) {
+				Curve._addBounds(
+					prevCoords[i],
+					prevCoords[i + 4],
+					coords[i + 2],
+					coords[i],
+					i, strokePadding ? strokePadding[i] : 0, min, max, roots);
+			}
+			var tmp = prevCoords;
+			prevCoords = coords;
+			coords = tmp;
+		}
+
+		for (var i = 1, l = segments.length; i < l; i++)
+			processSegment(segments[i]);
+		if (closed)
+			processSegment(first);
+		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
+	},
+
+	getStrokeBounds: function(segments, closed, path, matrix, options) {
+		var style = path.getStyle(),
+			stroke = style.hasStroke(),
+			strokeWidth = style.getStrokeWidth(),
+			strokeMatrix = stroke && path._getStrokeMatrix(matrix, options),
+			strokePadding = stroke && Path._getStrokePadding(strokeWidth,
+				strokeMatrix),
+			bounds = Path.getBounds(segments, closed, path, matrix, options,
+				strokePadding);
+		if (!stroke)
+			return bounds;
+		var strokeRadius = strokeWidth / 2,
+			join = style.getStrokeJoin(),
+			cap = style.getStrokeCap(),
+			miterLimit = strokeRadius * style.getMiterLimit(),
+			joinBounds = new Rectangle(new Size(strokePadding));
+
+		function addPoint(point) {
+			bounds = bounds.include(point);
+		}
+
+		function addRound(segment) {
+			bounds = bounds.unite(
+					joinBounds.setCenter(segment._point.transform(matrix)));
+		}
+
+		function addJoin(segment, join) {
+			var handleIn = segment._handleIn,
+				handleOut = segment._handleOut;
+			if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
+					&& handleIn.isCollinear(handleOut)) {
+				addRound(segment);
+			} else {
+				Path._addBevelJoin(segment, join, strokeRadius, miterLimit,
+						matrix, strokeMatrix, addPoint);
+			}
+		}
+
+		function addCap(segment, cap) {
+			if (cap === 'round') {
+				addRound(segment);
+			} else {
+				Path._addSquareCap(segment, cap, strokeRadius, matrix,
+						strokeMatrix, addPoint);
+			}
+		}
+
+		var length = segments.length - (closed ? 0 : 1);
+		for (var i = 1; i < length; i++)
+			addJoin(segments[i], join);
+		if (closed) {
+			addJoin(segments[0], join);
+		} else if (length > 0) {
+			addCap(segments[0], cap);
+			addCap(segments[segments.length - 1], cap);
+		}
+		return bounds;
+	},
+
+	_getStrokePadding: function(radius, matrix) {
+		if (!matrix)
+			return [radius, radius];
+		var hor = new Point(radius, 0).transform(matrix),
+			ver = new Point(0, radius).transform(matrix),
+			phi = hor.getAngleInRadians(),
+			a = hor.getLength(),
+			b = ver.getLength();
+		var sin = Math.sin(phi),
+			cos = Math.cos(phi),
+			tan = Math.tan(phi),
+			tx = Math.atan2(b * tan, a),
+			ty = Math.atan2(b, tan * a);
+		return [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),
+				Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];
+	},
+
+	_addBevelJoin: function(segment, join, radius, miterLimit, matrix,
+			strokeMatrix, addPoint, isArea) {
+		var curve2 = segment.getCurve(),
+			curve1 = curve2.getPrevious(),
+			point = curve2.getPointAtTime(0),
+			normal1 = curve1.getNormalAtTime(1),
+			normal2 = curve2.getNormalAtTime(0),
+			step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
+		normal1.setLength(step);
+		normal2.setLength(step);
+		if (matrix)
+			matrix._transformPoint(point, point);
+		if (strokeMatrix) {
+			strokeMatrix._transformPoint(normal1, normal1);
+			strokeMatrix._transformPoint(normal2, normal2);
+		}
+		if (isArea) {
+			addPoint(point);
+			addPoint(point.add(normal1));
+		}
+		if (join === 'miter') {
+			var corner = new Line(point.add(normal1),
+					new Point(-normal1.y, normal1.x), true
+				).intersect(new Line(point.add(normal2),
+					new Point(-normal2.y, normal2.x), true
+				), true);
+			if (corner && point.getDistance(corner) <= miterLimit) {
+				addPoint(corner);
+				if (!isArea)
+					return;
+			}
+		}
+		if (!isArea)
+			addPoint(point.add(normal1));
+		addPoint(point.add(normal2));
+	},
+
+	_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,
+			addPoint, isArea) {
+		var point = segment._point,
+			loc = segment.getLocation(),
+			normal = loc.getNormal().multiply(radius);
+		if (matrix)
+			matrix._transformPoint(point, point);
+		if (strokeMatrix)
+			strokeMatrix._transformPoint(normal, normal);
+		if (isArea) {
+			addPoint(point.subtract(normal));
+			addPoint(point.add(normal));
+		}
+		if (cap === 'square') {
+			point = point.add(normal.rotate(
+					loc.getTime() === 0 ? -90 : 90));
+		}
+		addPoint(point.add(normal));
+		addPoint(point.subtract(normal));
+	},
+
+	getHandleBounds: function(segments, closed, path, matrix, options) {
+		var style = path.getStyle(),
+			stroke = options.stroke && style.hasStroke(),
+			strokePadding,
+			joinPadding;
+		if (stroke) {
+			var strokeMatrix = path._getStrokeMatrix(matrix, options),
+				strokeRadius = style.getStrokeWidth() / 2,
+				joinRadius = strokeRadius;
+			if (style.getStrokeJoin() === 'miter')
+				joinRadius = strokeRadius * style.getMiterLimit();
+			if (style.getStrokeCap() === 'square')
+				joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
+			strokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);
+			joinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);
+		}
+		var coords = new Array(6),
+			x1 = Infinity,
+			x2 = -x1,
+			y1 = x1,
+			y2 = x2;
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var segment = segments[i];
+			segment._transformCoordinates(matrix, coords);
+			for (var j = 0; j < 6; j += 2) {
+				var padding = j === 0 ? joinPadding : strokePadding,
+					paddingX = padding ? padding[0] : 0,
+					paddingY = padding ? padding[1] : 0,
+					x = coords[j],
+					y = coords[j + 1],
+					xn = x - paddingX,
+					xx = x + paddingX,
+					yn = y - paddingY,
+					yx = y + paddingY;
+				if (xn < x1) x1 = xn;
+				if (xx > x2) x2 = xx;
+				if (yn < y1) y1 = yn;
+				if (yx > y2) y2 = yx;
+			}
+		}
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	}
+}});
+
+Path.inject({ statics: new function() {
+
+	var kappa = 0.5522847498307936,
+		ellipseSegments = [
+			new Segment([-1, 0], [0, kappa ], [0, -kappa]),
+			new Segment([0, -1], [-kappa, 0], [kappa, 0 ]),
+			new Segment([1, 0], [0, -kappa], [0, kappa ]),
+			new Segment([0, 1], [kappa, 0 ], [-kappa, 0])
+		];
+
+	function createPath(segments, closed, args) {
+		var props = Base.getNamed(args),
+			path = new Path(props && props.insert === false && Item.NO_INSERT);
+		path._add(segments);
+		path._closed = closed;
+		return path.set(props);
+	}
+
+	function createEllipse(center, radius, args) {
+		var segments = new Array(4);
+		for (var i = 0; i < 4; i++) {
+			var segment = ellipseSegments[i];
+			segments[i] = new Segment(
+				segment._point.multiply(radius).add(center),
+				segment._handleIn.multiply(radius),
+				segment._handleOut.multiply(radius)
+			);
+		}
+		return createPath(segments, true, args);
+	}
+
+	return {
+		Line: function() {
+			return createPath([
+				new Segment(Point.readNamed(arguments, 'from')),
+				new Segment(Point.readNamed(arguments, 'to'))
+			], false, arguments);
+		},
+
+		Circle: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				radius = Base.readNamed(arguments, 'radius');
+			return createEllipse(center, new Size(radius), arguments);
+		},
+
+		Rectangle: function() {
+			var rect = Rectangle.readNamed(arguments, 'rectangle'),
+				radius = Size.readNamed(arguments, 'radius', 0,
+						{ readNull: true }),
+				bl = rect.getBottomLeft(true),
+				tl = rect.getTopLeft(true),
+				tr = rect.getTopRight(true),
+				br = rect.getBottomRight(true),
+				segments;
+			if (!radius || radius.isZero()) {
+				segments = [
+					new Segment(bl),
+					new Segment(tl),
+					new Segment(tr),
+					new Segment(br)
+				];
+			} else {
+				radius = Size.min(radius, rect.getSize(true).divide(2));
+				var rx = radius.width,
+					ry = radius.height,
+					hx = rx * kappa,
+					hy = ry * kappa;
+				segments = [
+					new Segment(bl.add(rx, 0), null, [-hx, 0]),
+					new Segment(bl.subtract(0, ry), [0, hy]),
+					new Segment(tl.add(0, ry), null, [0, -hy]),
+					new Segment(tl.add(rx, 0), [-hx, 0], null),
+					new Segment(tr.subtract(rx, 0), null, [hx, 0]),
+					new Segment(tr.add(0, ry), [0, -hy], null),
+					new Segment(br.subtract(0, ry), null, [0, hy]),
+					new Segment(br.subtract(rx, 0), [hx, 0])
+				];
+			}
+			return createPath(segments, true, arguments);
+		},
+
+		RoundRectangle: '#Rectangle',
+
+		Ellipse: function() {
+			var ellipse = Shape._readEllipse(arguments);
+			return createEllipse(ellipse.center, ellipse.radius, arguments);
+		},
+
+		Oval: '#Ellipse',
+
+		Arc: function() {
+			var from = Point.readNamed(arguments, 'from'),
+				through = Point.readNamed(arguments, 'through'),
+				to = Point.readNamed(arguments, 'to'),
+				props = Base.getNamed(arguments),
+				path = new Path(props && props.insert === false
+						&& Item.NO_INSERT);
+			path.moveTo(from);
+			path.arcTo(through, to);
+			return path.set(props);
+		},
+
+		RegularPolygon: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				sides = Base.readNamed(arguments, 'sides'),
+				radius = Base.readNamed(arguments, 'radius'),
+				step = 360 / sides,
+				three = sides % 3 === 0,
+				vector = new Point(0, three ? -radius : radius),
+				offset = three ? -1 : 0.5,
+				segments = new Array(sides);
+			for (var i = 0; i < sides; i++)
+				segments[i] = new Segment(center.add(
+					vector.rotate((i + offset) * step)));
+			return createPath(segments, true, arguments);
+		},
+
+		Star: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				points = Base.readNamed(arguments, 'points') * 2,
+				radius1 = Base.readNamed(arguments, 'radius1'),
+				radius2 = Base.readNamed(arguments, 'radius2'),
+				step = 360 / points,
+				vector = new Point(0, -1),
+				segments = new Array(points);
+			for (var i = 0; i < points; i++)
+				segments[i] = new Segment(center.add(vector.rotate(step * i)
+						.multiply(i % 2 ? radius2 : radius1)));
+			return createPath(segments, true, arguments);
+		}
+	};
+}});
+
+var CompoundPath = PathItem.extend({
+	_class: 'CompoundPath',
+	_serializeFields: {
+		children: []
+	},
+
+	initialize: function CompoundPath(arg) {
+		this._children = [];
+		this._namedChildren = {};
+		if (!this._initialize(arg)) {
+			if (typeof arg === 'string') {
+				this.setPathData(arg);
+			} else {
+				this.addChildren(Array.isArray(arg) ? arg : arguments);
+			}
+		}
+	},
+
+	insertChildren: function insertChildren(index, items, _preserve) {
+		for (var i = items.length - 1; i >= 0; i--) {
+			var item = items[i];
+			if (item instanceof CompoundPath) {
+				items = items.slice();
+				items.splice.apply(items, [i, 1].concat(item.removeChildren()));
+				item.remove();
+			}
+		}
+		items = insertChildren.base.call(this, index, items, _preserve, Path);
+		for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
+			var item = items[i];
+			if (item._clockwise === undefined)
+				item.setClockwise(item._index === 0);
+		}
+		return items;
+	},
+
+	reduce: function reduce(options) {
+		var children = this._children;
+		for (var i = children.length - 1; i >= 0; i--) {
+			var path = children[i].reduce(options);
+			if (path.isEmpty())
+				path.remove();
+		}
+		if (children.length === 0) {
+			var path = new Path(Item.NO_INSERT);
+			path.copyAttributes(this);
+			path.insertAbove(this);
+			this.remove();
+			return path;
+		}
+		return reduce.base.call(this);
+	},
+
+	isClockwise: function() {
+		var child = this.getFirstChild();
+		return child && child.isClockwise();
+	},
+
+	setClockwise: function(clockwise) {
+		if (this.isClockwise() ^ !!clockwise)
+			this.reverse();
+	},
+
+	getFirstSegment: function() {
+		var first = this.getFirstChild();
+		return first && first.getFirstSegment();
+	},
+
+	getLastSegment: function() {
+		var last = this.getLastChild();
+		return last && last.getLastSegment();
+	},
+
+	getCurves: function() {
+		var children = this._children,
+			curves = [];
+		for (var i = 0, l = children.length; i < l; i++)
+			curves.push.apply(curves, children[i].getCurves());
+		return curves;
+	},
+
+	getFirstCurve: function() {
+		var first = this.getFirstChild();
+		return first && first.getFirstCurve();
+	},
+
+	getLastCurve: function() {
+		var last = this.getLastChild();
+		return last && last.getFirstCurve();
+	},
+
+	getArea: function() {
+		var children = this._children,
+			area = 0;
+		for (var i = 0, l = children.length; i < l; i++)
+			area += children[i].getArea();
+		return area;
+	}
+}, {
+	beans: true,
+
+	getPathData: function(_matrix, _precision) {
+		var children = this._children,
+			paths = [];
+		for (var i = 0, l = children.length; i < l; i++) {
+			var child = children[i],
+				mx = child._matrix;
+			paths.push(child.getPathData(_matrix && !mx.isIdentity()
+					? _matrix.appended(mx) : _matrix, _precision));
+		}
+		return paths.join(' ');
+	}
+}, {
+	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
+		return _hitTestChildren.base.call(this, point,
+				options.class === Path || options.type === 'path' ? options
+					: Base.set({}, options, { fill: false }),
+				viewMatrix);
+	},
+
+	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
+		var children = this._children;
+		if (children.length === 0)
+			return;
+
+		param = param.extend({ dontStart: true, dontFinish: true });
+		ctx.beginPath();
+		for (var i = 0, l = children.length; i < l; i++)
+			children[i].draw(ctx, param, strokeMatrix);
+
+		if (!param.clip) {
+			this._setStyles(ctx, param, viewMatrix);
+			var style = this._style;
+			if (style.hasFill()) {
+				ctx.fill(style.getFillRule());
+				ctx.shadowColor = 'rgba(0,0,0,0)';
+			}
+			if (style.hasStroke())
+				ctx.stroke();
+		}
+	},
+
+	_drawSelected: function(ctx, matrix, selectionItems) {
+		var children = this._children;
+		for (var i = 0, l = children.length; i < l; i++) {
+			var child = children[i],
+				mx = child._matrix;
+			if (!selectionItems[child._id]) {
+				child._drawSelected(ctx, mx.isIdentity() ? matrix
+						: matrix.appended(mx));
+			}
+		}
+	}
+},
+new function() {
+	function getCurrentPath(that, check) {
+		var children = that._children;
+		if (check && children.length === 0)
+			throw new Error('Use a moveTo() command first');
+		return children[children.length - 1];
+	}
+
+	return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
+			'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
+			'arcBy'],
+		function(key) {
+			this[key] = function() {
+				var path = getCurrentPath(this, true);
+				path[key].apply(path, arguments);
+			};
+		}, {
+			moveTo: function() {
+				var current = getCurrentPath(this),
+					path = current && current.isEmpty() ? current
+							: new Path(Item.NO_INSERT);
+				if (path !== current)
+					this.addChild(path);
+				path.moveTo.apply(path, arguments);
+			},
+
+			moveBy: function() {
+				var current = getCurrentPath(this, true),
+					last = current && current.getLastSegment(),
+					point = Point.read(arguments);
+				this.moveTo(last ? point.add(last._point) : point);
+			},
+
+			closePath: function(tolerance) {
+				getCurrentPath(this, true).closePath(tolerance);
+			}
+		}
+	);
+}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
+	this[key] = function(param) {
+		var children = this._children,
+			res;
+		for (var i = 0, l = children.length; i < l; i++) {
+			res = children[i][key](param) || res;
+		}
+		return res;
+	};
+}, {}));
+
+PathItem.inject(new function() {
+	var operators = {
+		unite:     { 1: true },
+		intersect: { 2: true },
+		subtract:  { 1: true },
+		exclude:   { 1: true }
+	};
+
+	function preparePath(path, resolve) {
+		var res = path.clone(false).reduce({ simplify: true })
+				.transform(null, true, true);
+		return resolve ? res.resolveCrossings() : res;
+	}
+
+	function createResult(ctor, paths, reduce, path1, path2) {
+		var result = new ctor(Item.NO_INSERT);
+		result.addChildren(paths, true);
+		if (reduce)
+			result = result.reduce({ simplify: true });
+		result.insertAbove(path2 && path1.isSibling(path2)
+				&& path1.getIndex() < path2.getIndex() ? path2 : path1);
+		result.copyAttributes(path1, true);
+		return result;
+	}
+
+	function computeBoolean(path1, path2, operation) {
+		var operator = operators[operation];
+		operator[operation] = true;
+		if (!path1._children && !path1._closed)
+			return computeOpenBoolean(path1, path2, operator);
+		var _path1 = preparePath(path1, true),
+			_path2 = path2 && path1 !== path2 && preparePath(path2, true);
+		if (_path2 && (operator.subtract || operator.exclude)
+				^ (_path2.isClockwise() ^ _path1.isClockwise()))
+			_path2.reverse();
+		var crossings = divideLocations(
+				CurveLocation.expand(_path1.getCrossings(_path2))),
+			segments = [],
+			monoCurves = [];
+
+		function collect(paths) {
+			for (var i = 0, l = paths.length; i < l; i++) {
+				var path = paths[i];
+				segments.push.apply(segments, path._segments);
+				monoCurves.push.apply(monoCurves, path._getMonoCurves());
+				path._overlapsOnly = path._validOverlapsOnly = true;
+			}
+		}
+
+		collect(_path1._children || [_path1]);
+		if (_path2)
+			collect(_path2._children || [_path2]);
+		for (var i = 0, l = crossings.length; i < l; i++) {
+			propagateWinding(crossings[i]._segment, _path1, _path2, monoCurves,
+					operator);
+		}
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var segment = segments[i],
+				inter = segment._intersection;
+			if (segment._winding == null) {
+				propagateWinding(segment, _path1, _path2, monoCurves, operator);
+			}
+			if (!(inter && inter._overlap)) {
+				var path = segment._path;
+				path._overlapsOnly = false;
+				if (operator[segment._winding])
+					path._validOverlapsOnly = false;
+			}
+		}
+		return createResult(CompoundPath, tracePaths(segments, operator), true,
+					path1, path2);
+	}
+
+	function computeOpenBoolean(path1, path2, operator) {
+		if (!path2 || !path2._children && !path2._closed
+				|| !operator.subtract && !operator.intersect)
+			return null;
+		var _path1 = preparePath(path1, false),
+			_path2 = preparePath(path2, false),
+			crossings = _path1.getCrossings(_path2),
+			sub = operator.subtract,
+			paths = [];
+
+		function addPath(path) {
+			if (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {
+				paths.unshift(path);
+				return true;
+			}
+		}
+
+		for (var i = crossings.length - 1; i >= 0; i--) {
+			var path = crossings[i].split();
+			if (path) {
+				if (addPath(path))
+					path.getFirstSegment().setHandleIn(0, 0);
+				_path1.getLastSegment().setHandleOut(0, 0);
+			}
+		}
+		addPath(_path1);
+		return createResult(Group, paths, false, path1, path2);
+	}
+
+	function linkIntersections(from, to) {
+		var prev = from;
+		while (prev) {
+			if (prev === to)
+				return;
+			prev = prev._previous;
+		}
+		while (from._next && from._next !== to)
+			from = from._next;
+		if (!from._next) {
+			while (to._previous)
+				to = to._previous;
+			from._next = to;
+			to._previous = from;
+		}
+	}
+
+	function divideLocations(locations, include) {
+		var results = include && [],
+			tMin = 4e-7,
+			tMax = 1 - tMin,
+			noHandles = false,
+			clearCurves = [],
+			prevCurve,
+			prevTime;
+
+		for (var i = locations.length - 1; i >= 0; i--) {
+			var loc = locations[i];
+			if (include) {
+				if (!include(loc))
+					continue;
+				results.unshift(loc);
+			}
+			var curve = loc._curve,
+				time = loc._time,
+				origTime = time,
+				segment;
+			if (curve !== prevCurve) {
+				noHandles = !curve.hasHandles();
+			} else if (prevTime >= tMin && prevTime <= tMax ) {
+				time /= prevTime;
+			}
+			if (time < tMin) {
+				segment = curve._segment1;
+			} else if (time > tMax) {
+				segment = curve._segment2;
+			} else {
+				var newCurve = curve.divideAtTime(time, true);
+				if (noHandles)
+					clearCurves.push(curve, newCurve);
+				segment = newCurve._segment1;
+			}
+			loc._setSegment(segment);
+			var inter = segment._intersection,
+				dest = loc._intersection;
+			if (inter) {
+				linkIntersections(inter, dest);
+				var other = inter;
+				while (other) {
+					linkIntersections(other._intersection, inter);
+					other = other._next;
+				}
+			} else {
+				segment._intersection = dest;
+			}
+			prevCurve = curve;
+			prevTime = origTime;
+		}
+		for (var i = 0, l = clearCurves.length; i < l; i++) {
+			clearCurves[i].clearHandles();
+		}
+		return results || locations;
+	}
+
+	function getWinding(point, curves, horizontal) {
+		var epsilon = 2e-7,
+			px = point.x,
+			py = point.y,
+			windLeft = 0,
+			windRight = 0,
+			length = curves.length,
+			roots = [],
+			abs = Math.abs;
+		if (horizontal) {
+			var yTop = -Infinity,
+				yBottom = Infinity,
+				yBefore = py - epsilon,
+				yAfter = py + epsilon;
+			for (var i = 0; i < length; i++) {
+				var values = curves[i].values,
+					count = Curve.solveCubic(values, 0, px, roots, 0, 1);
+				for (var j = count - 1; j >= 0; j--) {
+					var y = Curve.getPoint(values, roots[j]).y;
+					if (y < yBefore && y > yTop) {
+						yTop = y;
+					} else if (y > yAfter && y < yBottom) {
+						yBottom = y;
+					}
+				}
+			}
+			yTop = (yTop + py) / 2;
+			yBottom = (yBottom + py) / 2;
+			if (yTop > -Infinity)
+				windLeft = getWinding(new Point(px, yTop), curves).winding;
+			if (yBottom < Infinity)
+				windRight = getWinding(new Point(px, yBottom), curves).winding;
+		} else {
+			var xBefore = px - epsilon,
+				xAfter = px + epsilon,
+				prevWinding,
+				prevXEnd,
+				windLeftOnCurve = 0,
+				windRightOnCurve = 0,
+				isOnCurve = false;
+			for (var i = 0; i < length; i++) {
+				var curve = curves[i],
+					winding = curve.winding,
+					values = curve.values,
+					yStart = values[1],
+					yEnd = values[7];
+				if (curve.last) {
+					prevWinding = curve.last.winding;
+					prevXEnd = curve.last.values[6];
+					isOnCurve = false;
+				}
+				if (py >= yStart && py <= yEnd || py >= yEnd && py <= yStart) {
+					if (winding) {
+						var x = py === yStart ? values[0]
+							: py === yEnd ? values[6]
+							: Curve.solveCubic(values, 1, py, roots, 0, 1) === 1
+							? Curve.getPoint(values, roots[0]).x
+							: null;
+						if (x != null) {
+							if (x >= xBefore && x <= xAfter) {
+								isOnCurve = true;
+							} else if (
+								(py !== yStart || winding !== prevWinding)
+								&& !(py === yStart
+									&& (px - x) * (px - prevXEnd) < 0)) {
+								if (x < xBefore) {
+									windLeft += winding;
+								} else if (x > xAfter) {
+									windRight += winding;
+								}
+							}
+						}
+						prevWinding = winding;
+						prevXEnd = values[6];
+					} else if ((px - values[0]) * (px - values[6]) <= 0) {
+						isOnCurve = true;
+					}
+				}
+				if (isOnCurve && (i >= length - 1 || curves[i + 1].last)) {
+					windLeftOnCurve += 1;
+					windRightOnCurve -= 1;
+				}
+			}
+			if (windLeft === 0 && windRight === 0) {
+				windLeft = windLeftOnCurve;
+				windRight = windRightOnCurve;
+			}
+		}
+		return {
+			winding: Math.max(abs(windLeft), abs(windRight)),
+			contour: !windLeft ^ !windRight
+		};
+	}
+
+	function propagateWinding(segment, path1, path2, monoCurves, operator) {
+		var chain = [],
+			start = segment,
+			totalLength = 0,
+			winding;
+		do {
+			var curve = segment.getCurve(),
+				length = curve.getLength();
+			chain.push({ segment: segment, curve: curve, length: length });
+			totalLength += length;
+			segment = segment.getNext();
+		} while (segment && !segment._intersection && segment !== start);
+		var length = totalLength / 2;
+		for (var j = 0, l = chain.length; j < l; j++) {
+			var entry = chain[j],
+				curveLength = entry.length;
+			if (length <= curveLength) {
+				var curve = entry.curve,
+					path = curve._path,
+					parent = path._parent,
+					t = curve.getTimeAt(length),
+					pt = curve.getPointAtTime(t),
+					hor = Math.abs(curve.getTangentAtTime(t).y)
+							< 1e-7;
+				if (parent instanceof CompoundPath)
+					path = parent;
+				winding = !(operator.subtract && path2 && (
+						path === path1 &&  path2._getWinding(pt, hor) ||
+						path === path2 && !path1._getWinding(pt, hor)))
+							? getWinding(pt, monoCurves, hor)
+							: { winding: 0 };
+				 break;
+			}
+			length -= curveLength;
+		}
+		for (var j = chain.length - 1; j >= 0; j--) {
+			var seg = chain[j].segment;
+			seg._winding = winding.winding;
+			seg._contour = winding.contour;
+		}
+	}
+
+	function tracePaths(segments, operator) {
+		var paths = [],
+			start,
+			otherStart;
+
+		function isValid(seg, excludeContour) {
+			return !!(seg && !seg._visited && (!operator
+					|| operator[seg._winding]
+					|| !excludeContour && operator.unite && seg._contour));
+		}
+
+		function isStart(seg) {
+			return seg === start || seg === otherStart;
+		}
+
+		function findBestIntersection(inter, exclude) {
+			if (!inter._next)
+				return inter;
+			while (inter) {
+				var seg = inter._segment,
+					nextSeg = seg.getNext(),
+					nextInter = nextSeg && nextSeg._intersection;
+				if (seg !== exclude && (isStart(seg) || isStart(nextSeg)
+					|| !seg._visited && !nextSeg._visited
+					&& (!operator || isValid(seg) && (isValid(nextSeg)
+						|| nextInter && isValid(nextInter._segment)))
+					))
+					return inter;
+				inter = inter._next;
+			}
+			return null;
+		}
+
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var path = null,
+				finished = false,
+				seg = segments[i],
+				inter = seg._intersection,
+				handleIn;
+			if (!seg._visited && seg._path._overlapsOnly) {
+				var path1 = seg._path,
+					path2 = inter._segment._path,
+					segments1 = path1._segments,
+					segments2 = path2._segments;
+				if (Base.equals(segments1, segments2)) {
+					if ((operator.unite || operator.intersect)
+							&& path1.getArea()) {
+						paths.push(path1.clone(false));
+					}
+					for (var j = 0, k = segments1.length; j < k; j++) {
+						segments1[j]._visited = segments2[j]._visited = true;
+					}
+				}
+			}
+			if (!isValid(seg, true)
+					|| !seg._path._validOverlapsOnly && inter && inter._overlap)
+				continue;
+			start = otherStart = null;
+			while (true) {
+				inter = inter && findBestIntersection(inter, seg) || inter;
+				var other = inter && inter._segment;
+				if (isStart(seg)) {
+					finished = true;
+				} else if (other) {
+					if (isStart(other)) {
+						finished = true;
+						seg = other;
+					} else if (isValid(other, isValid(seg, true))) {
+						if (operator
+								&& (operator.intersect || operator.subtract)) {
+							seg._visited = true;
+						}
+						seg = other;
+					}
+				}
+				if (finished || seg._visited) {
+					seg._visited = true;
+					break;
+				}
+				if (seg._path._validOverlapsOnly && !isValid(seg))
+					break;
+				if (!path) {
+					path = new Path(Item.NO_INSERT);
+					start = seg;
+					otherStart = other;
+				}
+				var next = seg.getNext();
+				path.add(new Segment(seg._point, handleIn,
+						next && seg._handleOut));
+				seg._visited = true;
+				seg = next || seg._path.getFirstSegment();
+				handleIn = next && next._handleIn;
+				inter = seg._intersection;
+			}
+			if (finished) {
+				path.firstSegment.setHandleIn(handleIn);
+				path.setClosed(true);
+			} else if (path) {
+				var area = path.getArea(true);
+				if (Math.abs(area) >= 2e-7) {
+					console.error('Boolean operation resulted in open path',
+							'segments =', path._segments.length,
+							'length =', path.getLength(),
+							'area=', area);
+				}
+				path = null;
+			}
+			if (path && (path._segments.length > 8
+					|| !Numerical.isZero(path.getArea()))) {
+				paths.push(path);
+				path = null;
+			}
+		}
+		return paths;
+	}
+
+	return {
+		_getWinding: function(point, horizontal) {
+			return getWinding(point, this._getMonoCurves(), horizontal).winding;
+		},
+
+		unite: function(path) {
+			return computeBoolean(this, path, 'unite');
+		},
+
+		intersect: function(path) {
+			return computeBoolean(this, path, 'intersect');
+		},
+
+		subtract: function(path) {
+			return computeBoolean(this, path, 'subtract');
+		},
+
+		exclude: function(path) {
+			return computeBoolean(this, path, 'exclude');
+		},
+
+		divide: function(path) {
+			return createResult(Group, [this.subtract(path),
+					this.intersect(path)], true, this, path);
+		},
+
+		resolveCrossings: function() {
+			var children = this._children,
+				paths = children || [this];
+
+			function hasOverlap(seg) {
+				var inter = seg && seg._intersection;
+				return inter && inter._overlap;
+			}
+
+			var hasOverlaps = false,
+				hasCrossings = false,
+				intersections = this.getIntersections(null, function(inter) {
+					return inter._overlap && (hasOverlaps = true)
+							|| inter.isCrossing() && (hasCrossings = true);
+				});
+			intersections = CurveLocation.expand(intersections);
+			if (hasOverlaps) {
+				var overlaps = divideLocations(intersections, function(inter) {
+					return inter._overlap;
+				});
+				for (var i = overlaps.length - 1; i >= 0; i--) {
+					var seg = overlaps[i]._segment,
+						prev = seg.getPrevious(),
+						next = seg.getNext();
+					if (seg._path && hasOverlap(prev) && hasOverlap(next)) {
+						seg.remove();
+						prev._handleOut.set(0, 0);
+						next._handleIn.set(0, 0);
+						var curve = prev.getCurve();
+						if (curve.isStraight() && curve.getLength() === 0)
+							prev.remove();
+					}
+				}
+			}
+			if (hasCrossings) {
+				divideLocations(intersections, hasOverlaps && function(inter) {
+					var curve1 = inter.getCurve(),
+						curve2 = inter._intersection._curve,
+						seg = inter._segment;
+					if (curve1 && curve2 && curve1._path && curve2._path) {
+						return true;
+					} else if (seg) {
+						seg._intersection = null;
+					}
+				});
+				paths = tracePaths(Base.each(paths, function(path) {
+					this.push.apply(this, path._segments);
+				}, []));
+			}
+			var length = paths.length,
+				item;
+			if (length > 1) {
+				paths = paths.slice().sort(function (a, b) {
+					return b.getBounds().getArea() - a.getBounds().getArea();
+				});
+				var first = paths[0],
+					items = [first],
+					excluded = {},
+					isNonZero = this.getFillRule() === 'nonzero',
+					windings = isNonZero && Base.each(paths, function(path) {
+						this.push(path.isClockwise() ? 1 : -1);
+					}, []);
+				for (var i = 1; i < length; i++) {
+					var path = paths[i],
+						point = path.getInteriorPoint(),
+						isContained = false,
+						container = null,
+						exclude = false;
+					for (var j = i - 1; j >= 0 && !container; j--) {
+						if (paths[j].contains(point)) {
+							if (isNonZero && !isContained) {
+								windings[i] += windings[j];
+								if (windings[i] && windings[j]) {
+									exclude = excluded[i] = true;
+									break;
+								}
+							}
+							isContained = true;
+							container = !excluded[j] && paths[j];
+						}
+					}
+					if (!exclude) {
+						path.setClockwise(container ? !container.isClockwise()
+								: first.isClockwise());
+						items.push(path);
+					}
+				}
+				paths = items;
+				length = items.length;
+			}
+			if (length > 1 && children) {
+				if (paths !== children) {
+					this.setChildren(paths, true);
+				}
+				item = this;
+			} else if (length === 1 && !children) {
+				if (paths[0] !== this)
+					this.setSegments(paths[0].removeSegments());
+				item = this;
+			}
+			if (!item) {
+				item = new CompoundPath(Item.NO_INSERT);
+				item.addChildren(paths, true);
+				item = item.reduce();
+				item.copyAttributes(this);
+				this.replaceWith(item);
+			}
+			return item;
+		}
+	};
+});
+
+Path.inject({
+	_getMonoCurves: function() {
+		var monoCurves = this._monoCurves,
+			last;
+
+		function insertCurve(v) {
+			var y0 = v[1],
+				y1 = v[7],
+				winding = Math.abs((y0 - y1) / (v[0] - v[6]))
+						< 2e-7
+					? 0
+					: y0 > y1
+						? -1
+						: 1,
+				curve = { values: v, winding: winding };
+			monoCurves.push(curve);
+			if (winding)
+				last = curve;
+		}
+
+		function handleCurve(v) {
+			if (Curve.getLength(v) === 0)
+				return;
+			var y0 = v[1],
+				y1 = v[3],
+				y2 = v[5],
+				y3 = v[7];
+			if (Curve.isStraight(v)
+					|| y0 >= y1 === y1 >= y2 && y1 >= y2 === y2 >= y3) {
+				insertCurve(v);
+			} else {
+				var a = 3 * (y1 - y2) - y0 + y3,
+					b = 2 * (y0 + y2) - 4 * y1,
+					c = y1 - y0,
+					tMin = 4e-7,
+					tMax = 1 - tMin,
+					roots = [],
+					n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
+				if (n < 1) {
+					insertCurve(v);
+				} else {
+					roots.sort();
+					var t = roots[0],
+						parts = Curve.subdivide(v, t);
+					insertCurve(parts[0]);
+					if (n > 1) {
+						t = (roots[1] - t) / (1 - t);
+						parts = Curve.subdivide(parts[1], t);
+						insertCurve(parts[0]);
+					}
+					insertCurve(parts[1]);
+				}
+			}
+		}
+
+		if (!monoCurves) {
+			monoCurves = this._monoCurves = [];
+			var curves = this.getCurves(),
+				segments = this._segments;
+			for (var i = 0, l = curves.length; i < l; i++)
+				handleCurve(curves[i].getValues());
+			if (!this._closed && segments.length > 1) {
+				var p1 = segments[segments.length - 1]._point,
+					p2 = segments[0]._point,
+					p1x = p1._x, p1y = p1._y,
+					p2x = p2._x, p2y = p2._y;
+				handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
+			}
+			if (monoCurves.length > 0) {
+				monoCurves[0].last = last;
+			}
+		}
+		return monoCurves;
+	},
+
+	getInteriorPoint: function() {
+		var bounds = this.getBounds(),
+			point = bounds.getCenter(true);
+		if (!this.contains(point)) {
+			var curves = this._getMonoCurves(),
+				roots = [],
+				y = point.y,
+				intercepts = [];
+			for (var i = 0, l = curves.length; i < l; i++) {
+				var values = curves[i].values;
+				if (curves[i].winding === 1
+						&& y > values[1] && y <= values[7]
+						|| y >= values[7] && y < values[1]) {
+					var count = Curve.solveCubic(values, 1, y, roots, 0, 1);
+					for (var j = count - 1; j >= 0; j--) {
+						intercepts.push(Curve.getPoint(values, roots[j]).x);
+					}
+				}
+			}
+			intercepts.sort(function(a, b) { return a - b; });
+			point.x = (intercepts[0] + intercepts[1]) / 2;
+		}
+		return point;
+	}
+});
+
+CompoundPath.inject({
+	_getMonoCurves: function() {
+		var children = this._children,
+			monoCurves = [];
+		for (var i = 0, l = children.length; i < l; i++)
+			monoCurves.push.apply(monoCurves, children[i]._getMonoCurves());
+		return monoCurves;
+	}
+});
+
+var PathIterator = Base.extend({
+	_class: 'PathIterator',
+
+	initialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {
+		var curves = [],
+			parts = [],
+			length = 0,
+			minSpan = 1 / (maxRecursion || 32),
+			segments = path._segments,
+			segment1 = segments[0],
+			segment2;
+
+		function addCurve(segment1, segment2) {
+			var curve = Curve.getValues(segment1, segment2, matrix);
+			curves.push(curve);
+			computeParts(curve, segment1._index, 0, 1);
+		}
+
+		function computeParts(curve, index, t1, t2) {
+			if ((t2 - t1) > minSpan
+					&& !(ignoreStraight && Curve.isStraight(curve))
+					&& !Curve.isFlatEnough(curve, flatness || 0.25)) {
+				var halves = Curve.subdivide(curve, 0.5),
+					tMid = (t1 + t2) / 2;
+				computeParts(halves[0], index, t1, tMid);
+				computeParts(halves[1], index, tMid, t2);
+			} else {
+				var dx = curve[6] - curve[0],
+					dy = curve[7] - curve[1],
+					dist = Math.sqrt(dx * dx + dy * dy);
+				if (dist > 0) {
+					length += dist;
+					parts.push({
+						offset: length,
+						curve: curve,
+						index: index,
+						time: t2,
+					});
+				}
+			}
+		}
+
+		for (var i = 1, l = segments.length; i < l; i++) {
+			segment2 = segments[i];
+			addCurve(segment1, segment2);
+			segment1 = segment2;
+		}
+		if (path._closed)
+			addCurve(segment2, segments[0]);
+		this.curves = curves;
+		this.parts = parts;
+		this.length = length;
+		this.index = 0;
+	},
+
+	_get: function(offset) {
+		var i, j = this.index;
+		for (;;) {
+			i = j;
+			if (j === 0 || this.parts[--j].offset < offset)
+				break;
+		}
+		for (var l = this.parts.length; i < l; i++) {
+			var part = this.parts[i];
+			if (part.offset >= offset) {
+				this.index = i;
+				var prev = this.parts[i - 1];
+				var prevTime = prev && prev.index === part.index ? prev.time : 0,
+					prevOffset = prev ? prev.offset : 0;
+				return {
+					index: part.index,
+					time: prevTime + (part.time - prevTime)
+						* (offset - prevOffset) / (part.offset - prevOffset)
+				};
+			}
+		}
+		var part = this.parts[this.parts.length - 1];
+		return {
+			index: part.index,
+			time: 1
+		};
+	},
+
+	drawPart: function(ctx, from, to) {
+		var start = this._get(from),
+			end = this._get(to);
+		for (var i = start.index, l = end.index; i <= l; i++) {
+			var curve = Curve.getPart(this.curves[i],
+					i === start.index ? start.time : 0,
+					i === end.index ? end.time : 1);
+			if (i === start.index)
+				ctx.moveTo(curve[0], curve[1]);
+			ctx.bezierCurveTo.apply(ctx, curve.slice(2));
+		}
+	}
+}, Base.each(Curve._evaluateMethods,
+	function(name) {
+		this[name + 'At'] = function(offset) {
+			var param = this._get(offset);
+			return Curve[name](this.curves[param.index], param.time);
+		};
+	}, {})
+);
+
+var PathFitter = Base.extend({
+	initialize: function(path) {
+		var points = this.points = [],
+			segments = path._segments,
+			closed = path._closed;
+		for (var i = 0, prev, l = segments.length; i < l; i++) {
+			var point = segments[i].point;
+			if (!prev || !prev.equals(point)) {
+				points.push(prev = point.clone());
+			}
+		}
+		if (closed) {
+			points.unshift(points[points.length - 1]);
+			points.push(points[1]);
+		}
+		this.closed = closed;
+	},
+
+	fit: function(error) {
+		var points = this.points,
+			length = points.length,
+			segments = null;
+		if (length > 0) {
+			segments = [new Segment(points[0])];
+			if (length > 1) {
+				this.fitCubic(segments, error, 0, length - 1,
+						points[1].subtract(points[0]),
+						points[length - 2].subtract(points[length - 1]));
+				if (this.closed) {
+					segments.shift();
+					segments.pop();
+				}
+			}
+		}
+		return segments;
+	},
+
+	fitCubic: function(segments, error, first, last, tan1, tan2) {
+		var points = this.points;
+		if (last - first === 1) {
+			var pt1 = points[first],
+				pt2 = points[last],
+				dist = pt1.getDistance(pt2) / 3;
+			this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
+					pt2.add(tan2.normalize(dist)), pt2]);
+			return;
+		}
+		var uPrime = this.chordLengthParameterize(first, last),
+			maxError = Math.max(error, error * error),
+			split,
+			parametersInOrder = true;
+		for (var i = 0; i <= 4; i++) {
+			var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
+			var max = this.findMaxError(first, last, curve, uPrime);
+			if (max.error < error && parametersInOrder) {
+				this.addCurve(segments, curve);
+				return;
+			}
+			split = max.index;
+			if (max.error >= maxError)
+				break;
+			parametersInOrder = this.reparameterize(first, last, uPrime, curve);
+			maxError = max.error;
+		}
+		var tanCenter = points[split - 1].subtract(points[split + 1]);
+		this.fitCubic(segments, error, first, split, tan1, tanCenter);
+		this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
+	},
+
+	addCurve: function(segments, curve) {
+		var prev = segments[segments.length - 1];
+		prev.setHandleOut(curve[1].subtract(curve[0]));
+		segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
+	},
+
+	generateBezier: function(first, last, uPrime, tan1, tan2) {
+		var epsilon = 1e-12,
+			abs = Math.abs,
+			points = this.points,
+			pt1 = points[first],
+			pt2 = points[last],
+			C = [[0, 0], [0, 0]],
+			X = [0, 0];
+
+		for (var i = 0, l = last - first + 1; i < l; i++) {
+			var u = uPrime[i],
+				t = 1 - u,
+				b = 3 * u * t,
+				b0 = t * t * t,
+				b1 = b * t,
+				b2 = b * u,
+				b3 = u * u * u,
+				a1 = tan1.normalize(b1),
+				a2 = tan2.normalize(b2),
+				tmp = points[first + i]
+					.subtract(pt1.multiply(b0 + b1))
+					.subtract(pt2.multiply(b2 + b3));
+			C[0][0] += a1.dot(a1);
+			C[0][1] += a1.dot(a2);
+			C[1][0] = C[0][1];
+			C[1][1] += a2.dot(a2);
+			X[0] += a1.dot(tmp);
+			X[1] += a2.dot(tmp);
+		}
+
+		var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
+			alpha1, alpha2;
+		if (abs(detC0C1) > epsilon) {
+			var detC0X = C[0][0] * X[1]    - C[1][0] * X[0],
+				detXC1 = X[0]    * C[1][1] - X[1]    * C[0][1];
+			alpha1 = detXC1 / detC0C1;
+			alpha2 = detC0X / detC0C1;
+		} else {
+			var c0 = C[0][0] + C[0][1],
+				c1 = C[1][0] + C[1][1];
+			if (abs(c0) > epsilon) {
+				alpha1 = alpha2 = X[0] / c0;
+			} else if (abs(c1) > epsilon) {
+				alpha1 = alpha2 = X[1] / c1;
+			} else {
+				alpha1 = alpha2 = 0;
+			}
+		}
+
+		var segLength = pt2.getDistance(pt1),
+			eps = epsilon * segLength,
+			handle1,
+			handle2;
+		if (alpha1 < eps || alpha2 < eps) {
+			alpha1 = alpha2 = segLength / 3;
+		} else {
+			var line = pt2.subtract(pt1);
+			handle1 = tan1.normalize(alpha1);
+			handle2 = tan2.normalize(alpha2);
+			if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
+				alpha1 = alpha2 = segLength / 3;
+				handle1 = handle2 = null;
+			}
+		}
+
+		return [pt1,
+				pt1.add(handle1 || tan1.normalize(alpha1)),
+				pt2.add(handle2 || tan2.normalize(alpha2)),
+				pt2];
+	},
+
+	reparameterize: function(first, last, u, curve) {
+		for (var i = first; i <= last; i++) {
+			u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
+		}
+		for (var i = 1, l = u.length; i < l; i++) {
+			if (u[i] <= u[i - 1])
+				return false;
+		}
+		return true;
+	},
+
+	findRoot: function(curve, point, u) {
+		var curve1 = [],
+			curve2 = [];
+		for (var i = 0; i <= 2; i++) {
+			curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);
+		}
+		for (var i = 0; i <= 1; i++) {
+			curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);
+		}
+		var pt = this.evaluate(3, curve, u),
+			pt1 = this.evaluate(2, curve1, u),
+			pt2 = this.evaluate(1, curve2, u),
+			diff = pt.subtract(point),
+			df = pt1.dot(pt1) + diff.dot(pt2);
+		if (Math.abs(df) < 1e-6)
+			return u;
+		return u - diff.dot(pt1) / df;
+	},
+
+	evaluate: function(degree, curve, t) {
+		var tmp = curve.slice();
+		for (var i = 1; i <= degree; i++) {
+			for (var j = 0; j <= degree - i; j++) {
+				tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));
+			}
+		}
+		return tmp[0];
+	},
+
+	chordLengthParameterize: function(first, last) {
+		var u = [0];
+		for (var i = first + 1; i <= last; i++) {
+			u[i - first] = u[i - first - 1]
+					+ this.points[i].getDistance(this.points[i - 1]);
+		}
+		for (var i = 1, m = last - first; i <= m; i++) {
+			u[i] /= u[m];
+		}
+		return u;
+	},
+
+	findMaxError: function(first, last, curve, u) {
+		var index = Math.floor((last - first + 1) / 2),
+			maxDist = 0;
+		for (var i = first + 1; i < last; i++) {
+			var P = this.evaluate(3, curve, u[i - first]);
+			var v = P.subtract(this.points[i]);
+			var dist = v.x * v.x + v.y * v.y;
+			if (dist >= maxDist) {
+				maxDist = dist;
+				index = i;
+			}
+		}
+		return {
+			error: maxDist,
+			index: index
+		};
+	}
+});
+
+var TextItem = Item.extend({
+	_class: 'TextItem',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_serializeFields: {
+		content: null
+	},
+	_boundsOptions: { stroke: false, handle: false },
+
+	initialize: function TextItem(arg) {
+		this._content = '';
+		this._lines = [];
+		var hasProps = arg && Base.isPlainObject(arg)
+				&& arg.x === undefined && arg.y === undefined;
+		this._initialize(hasProps && arg, !hasProps && Point.read(arguments));
+	},
+
+	_equals: function(item) {
+		return this._content === item._content;
+	},
+
+	copyContent: function(source) {
+		this.setContent(source._content);
+	},
+
+	getContent: function() {
+		return this._content;
+	},
+
+	setContent: function(content) {
+		this._content = '' + content;
+		this._lines = this._content.split(/\r\n|\n|\r/mg);
+		this._changed(265);
+	},
+
+	isEmpty: function() {
+		return !this._content;
+	},
+
+	getCharacterStyle: '#getStyle',
+	setCharacterStyle: '#setStyle',
+
+	getParagraphStyle: '#getStyle',
+	setParagraphStyle: '#setStyle'
+});
+
+var PointText = TextItem.extend({
+	_class: 'PointText',
+
+	initialize: function PointText() {
+		TextItem.apply(this, arguments);
+	},
+
+	getPoint: function() {
+		var point = this._matrix.getTranslation();
+		return new LinkedPoint(point.x, point.y, this, 'setPoint');
+	},
+
+	setPoint: function() {
+		var point = Point.read(arguments);
+		this.translate(point.subtract(this._matrix.getTranslation()));
+	},
+
+	_draw: function(ctx, param, viewMatrix) {
+		if (!this._content)
+			return;
+		this._setStyles(ctx, param, viewMatrix);
+		var lines = this._lines,
+			style = this._style,
+			hasFill = style.hasFill(),
+			hasStroke = style.hasStroke(),
+			leading = style.getLeading(),
+			shadowColor = ctx.shadowColor;
+		ctx.font = style.getFontStyle();
+		ctx.textAlign = style.getJustification();
+		for (var i = 0, l = lines.length; i < l; i++) {
+			ctx.shadowColor = shadowColor;
+			var line = lines[i];
+			if (hasFill) {
+				ctx.fillText(line, 0, 0);
+				ctx.shadowColor = 'rgba(0,0,0,0)';
+			}
+			if (hasStroke)
+				ctx.strokeText(line, 0, 0);
+			ctx.translate(0, leading);
+		}
+	},
+
+	_getBounds: function(matrix, options) {
+		var style = this._style,
+			lines = this._lines,
+			numLines = lines.length,
+			justification = style.getJustification(),
+			leading = style.getLeading(),
+			width = this.getView().getTextWidth(style.getFontStyle(), lines),
+			x = 0;
+		if (justification !== 'left')
+			x -= width / (justification === 'center' ? 2: 1);
+		var bounds = new Rectangle(x,
+					numLines ? - 0.75 * leading : 0,
+					width, numLines * leading);
+		return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
+	}
+});
+
+var Color = Base.extend(new function() {
+	var types = {
+		gray: ['gray'],
+		rgb: ['red', 'green', 'blue'],
+		hsb: ['hue', 'saturation', 'brightness'],
+		hsl: ['hue', 'saturation', 'lightness'],
+		gradient: ['gradient', 'origin', 'destination', 'highlight']
+	};
+
+	var componentParsers = {},
+		colorCache = {},
+		colorCtx;
+
+	function fromCSS(string) {
+		var match = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/),
+			components;
+		if (match) {
+			components = [0, 0, 0];
+			for (var i = 0; i < 3; i++) {
+				var value = match[i + 1];
+				components[i] = parseInt(value.length == 1
+						? value + value : value, 16) / 255;
+			}
+		} else if (match = string.match(/^rgba?\((.*)\)$/)) {
+			components = match[1].split(',');
+			for (var i = 0, l = components.length; i < l; i++) {
+				var value = +components[i];
+				components[i] = i < 3 ? value / 255 : value;
+			}
+		} else if (window) {
+			var cached = colorCache[string];
+			if (!cached) {
+				if (!colorCtx) {
+					colorCtx = CanvasProvider.getContext(1, 1);
+					colorCtx.globalCompositeOperation = 'copy';
+				}
+				colorCtx.fillStyle = 'rgba(0,0,0,0)';
+				colorCtx.fillStyle = string;
+				colorCtx.fillRect(0, 0, 1, 1);
+				var data = colorCtx.getImageData(0, 0, 1, 1).data;
+				cached = colorCache[string] = [
+					data[0] / 255,
+					data[1] / 255,
+					data[2] / 255
+				];
+			}
+			components = cached.slice();
+		} else {
+			components = [0, 0, 0];
+		}
+		return components;
+	}
+
+	var hsbIndices = [
+		[0, 3, 1],
+		[2, 0, 1],
+		[1, 0, 3],
+		[1, 2, 0],
+		[3, 1, 0],
+		[0, 1, 2]
+	];
+
+	var converters = {
+		'rgb-hsb': function(r, g, b) {
+			var max = Math.max(r, g, b),
+				min = Math.min(r, g, b),
+				delta = max - min,
+				h = delta === 0 ? 0
+					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
+						: max == g ? (b - r) / delta + 2
+						:            (r - g) / delta + 4) * 60;
+			return [h, max === 0 ? 0 : delta / max, max];
+		},
+
+		'hsb-rgb': function(h, s, b) {
+			h = (((h / 60) % 6) + 6) % 6;
+			var i = Math.floor(h),
+				f = h - i,
+				i = hsbIndices[i],
+				v = [
+					b,
+					b * (1 - s),
+					b * (1 - s * f),
+					b * (1 - s * (1 - f))
+				];
+			return [v[i[0]], v[i[1]], v[i[2]]];
+		},
+
+		'rgb-hsl': function(r, g, b) {
+			var max = Math.max(r, g, b),
+				min = Math.min(r, g, b),
+				delta = max - min,
+				achromatic = delta === 0,
+				h = achromatic ? 0
+					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
+						: max == g ? (b - r) / delta + 2
+						:            (r - g) / delta + 4) * 60,
+				l = (max + min) / 2,
+				s = achromatic ? 0 : l < 0.5
+						? delta / (max + min)
+						: delta / (2 - max - min);
+			return [h, s, l];
+		},
+
+		'hsl-rgb': function(h, s, l) {
+			h = (((h / 360) % 1) + 1) % 1;
+			if (s === 0)
+				return [l, l, l];
+			var t3s = [ h + 1 / 3, h, h - 1 / 3 ],
+				t2 = l < 0.5 ? l * (1 + s) : l + s - l * s,
+				t1 = 2 * l - t2,
+				c = [];
+			for (var i = 0; i < 3; i++) {
+				var t3 = t3s[i];
+				if (t3 < 0) t3 += 1;
+				if (t3 > 1) t3 -= 1;
+				c[i] = 6 * t3 < 1
+					? t1 + (t2 - t1) * 6 * t3
+					: 2 * t3 < 1
+						? t2
+						: 3 * t3 < 2
+							? t1 + (t2 - t1) * ((2 / 3) - t3) * 6
+							: t1;
+			}
+			return c;
+		},
+
+		'rgb-gray': function(r, g, b) {
+			return [r * 0.2989 + g * 0.587 + b * 0.114];
+		},
+
+		'gray-rgb': function(g) {
+			return [g, g, g];
+		},
+
+		'gray-hsb': function(g) {
+			return [0, 0, g];
+		},
+
+		'gray-hsl': function(g) {
+			return [0, 0, g];
+		},
+
+		'gradient-rgb': function() {
+			return [];
+		},
+
+		'rgb-gradient': function() {
+			return [];
+		}
+
+	};
+
+	return Base.each(types, function(properties, type) {
+		componentParsers[type] = [];
+		Base.each(properties, function(name, index) {
+			var part = Base.capitalize(name),
+				hasOverlap = /^(hue|saturation)$/.test(name),
+				parser = componentParsers[type][index] = name === 'gradient'
+					? function(value) {
+						var current = this._components[0];
+						value = Gradient.read(Array.isArray(value) ? value
+								: arguments, 0, { readNull: true });
+						if (current !== value) {
+							if (current)
+								current._removeOwner(this);
+							if (value)
+								value._addOwner(this);
+						}
+						return value;
+					}
+					: type === 'gradient'
+						? function() {
+							return Point.read(arguments, 0, {
+									readNull: name === 'highlight',
+									clone: true
+							});
+						}
+						: function(value) {
+							return value == null || isNaN(value) ? 0 : value;
+						};
+
+			this['get' + part] = function() {
+				return this._type === type
+					|| hasOverlap && /^hs[bl]$/.test(this._type)
+						? this._components[index]
+						: this._convert(type)[index];
+			};
+
+			this['set' + part] = function(value) {
+				if (this._type !== type
+						&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {
+					this._components = this._convert(type);
+					this._properties = types[type];
+					this._type = type;
+				}
+				this._components[index] = parser.call(this, value);
+				this._changed();
+			};
+		}, this);
+	}, {
+		_class: 'Color',
+		_readIndex: true,
+
+		initialize: function Color(arg) {
+			var slice = Array.prototype.slice,
+				args = arguments,
+				reading = this.__read,
+				read = 0,
+				type,
+				components,
+				alpha,
+				values;
+			if (Array.isArray(arg)) {
+				args = arg;
+				arg = args[0];
+			}
+			var argType = arg != null && typeof arg;
+			if (argType === 'string' && arg in types) {
+				type = arg;
+				arg = args[1];
+				if (Array.isArray(arg)) {
+					components = arg;
+					alpha = args[2];
+				} else {
+					if (reading)
+						read = 1;
+					args = slice.call(args, 1);
+					argType = typeof arg;
+				}
+			}
+			if (!components) {
+				values = argType === 'number'
+						? args
+						: argType === 'object' && arg.length != null
+							? arg
+							: null;
+				if (values) {
+					if (!type)
+						type = values.length >= 3
+								? 'rgb'
+								: 'gray';
+					var length = types[type].length;
+					alpha = values[length];
+					if (reading) {
+						read += values === arguments
+							? length + (alpha != null ? 1 : 0)
+							: 1;
+					}
+					if (values.length > length)
+						values = slice.call(values, 0, length);
+				} else if (argType === 'string') {
+					type = 'rgb';
+					components = fromCSS(arg);
+					if (components.length === 4) {
+						alpha = components[3];
+						components.length--;
+					}
+				} else if (argType === 'object') {
+					if (arg.constructor === Color) {
+						type = arg._type;
+						components = arg._components.slice();
+						alpha = arg._alpha;
+						if (type === 'gradient') {
+							for (var i = 1, l = components.length; i < l; i++) {
+								var point = components[i];
+								if (point)
+									components[i] = point.clone();
+							}
+						}
+					} else if (arg.constructor === Gradient) {
+						type = 'gradient';
+						values = args;
+					} else {
+						type = 'hue' in arg
+							? 'lightness' in arg
+								? 'hsl'
+								: 'hsb'
+							: 'gradient' in arg || 'stops' in arg
+									|| 'radial' in arg
+								? 'gradient'
+								: 'gray' in arg
+									? 'gray'
+									: 'rgb';
+						var properties = types[type],
+							parsers = componentParsers[type];
+						this._components = components = [];
+						for (var i = 0, l = properties.length; i < l; i++) {
+							var value = arg[properties[i]];
+							if (value == null && i === 0 && type === 'gradient'
+									&& 'stops' in arg) {
+								value = {
+									stops: arg.stops,
+									radial: arg.radial
+								};
+							}
+							value = parsers[i].call(this, value);
+							if (value != null)
+								components[i] = value;
+						}
+						alpha = arg.alpha;
+					}
+				}
+				if (reading && type)
+					read = 1;
+			}
+			this._type = type || 'rgb';
+			if (!components) {
+				this._components = components = [];
+				var parsers = componentParsers[this._type];
+				for (var i = 0, l = parsers.length; i < l; i++) {
+					var value = parsers[i].call(this, values && values[i]);
+					if (value != null)
+						components[i] = value;
+				}
+			}
+			this._components = components;
+			this._properties = types[this._type];
+			this._alpha = alpha;
+			if (reading)
+				this.__read = read;
+		},
+
+		_set: '#initialize',
+
+		_serialize: function(options, dictionary) {
+			var components = this.getComponents();
+			return Base.serialize(
+					/^(gray|rgb)$/.test(this._type)
+						? components
+						: [this._type].concat(components),
+					options, true, dictionary);
+		},
+
+		_changed: function() {
+			this._canvasStyle = null;
+			if (this._owner)
+				this._owner._changed(65);
+		},
+
+		_convert: function(type) {
+			var converter;
+			return this._type === type
+					? this._components.slice()
+					: (converter = converters[this._type + '-' + type])
+						? converter.apply(this, this._components)
+						: converters['rgb-' + type].apply(this,
+							converters[this._type + '-rgb'].apply(this,
+								this._components));
+		},
+
+		convert: function(type) {
+			return new Color(type, this._convert(type), this._alpha);
+		},
+
+		getType: function() {
+			return this._type;
+		},
+
+		setType: function(type) {
+			this._components = this._convert(type);
+			this._properties = types[type];
+			this._type = type;
+		},
+
+		getComponents: function() {
+			var components = this._components.slice();
+			if (this._alpha != null)
+				components.push(this._alpha);
+			return components;
+		},
+
+		getAlpha: function() {
+			return this._alpha != null ? this._alpha : 1;
+		},
+
+		setAlpha: function(alpha) {
+			this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);
+			this._changed();
+		},
+
+		hasAlpha: function() {
+			return this._alpha != null;
+		},
+
+		equals: function(color) {
+			var col = Base.isPlainValue(color, true)
+					? Color.read(arguments)
+					: color;
+			return col === this || col && this._class === col._class
+					&& this._type === col._type
+					&& this._alpha === col._alpha
+					&& Base.equals(this._components, col._components)
+					|| false;
+		},
+
+		toString: function() {
+			var properties = this._properties,
+				parts = [],
+				isGradient = this._type === 'gradient',
+				f = Formatter.instance;
+			for (var i = 0, l = properties.length; i < l; i++) {
+				var value = this._components[i];
+				if (value != null)
+					parts.push(properties[i] + ': '
+							+ (isGradient ? value : f.number(value)));
+			}
+			if (this._alpha != null)
+				parts.push('alpha: ' + f.number(this._alpha));
+			return '{ ' + parts.join(', ') + ' }';
+		},
+
+		toCSS: function(hex) {
+			var components = this._convert('rgb'),
+				alpha = hex || this._alpha == null ? 1 : this._alpha;
+			function convert(val) {
+				return Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);
+			}
+			components = [
+				convert(components[0]),
+				convert(components[1]),
+				convert(components[2])
+			];
+			if (alpha < 1)
+				components.push(alpha < 0 ? 0 : alpha);
+			return hex
+					? '#' + ((1 << 24) + (components[0] << 16)
+						+ (components[1] << 8)
+						+ components[2]).toString(16).slice(1)
+					: (components.length == 4 ? 'rgba(' : 'rgb(')
+						+ components.join(',') + ')';
+		},
+
+		toCanvasStyle: function(ctx) {
+			if (this._canvasStyle)
+				return this._canvasStyle;
+			if (this._type !== 'gradient')
+				return this._canvasStyle = this.toCSS();
+			var components = this._components,
+				gradient = components[0],
+				stops = gradient._stops,
+				origin = components[1],
+				destination = components[2],
+				canvasGradient;
+			if (gradient._radial) {
+				var radius = destination.getDistance(origin),
+					highlight = components[3];
+				if (highlight) {
+					var vector = highlight.subtract(origin);
+					if (vector.getLength() > radius)
+						highlight = origin.add(vector.normalize(radius - 0.1));
+				}
+				var start = highlight || origin;
+				canvasGradient = ctx.createRadialGradient(start.x, start.y,
+						0, origin.x, origin.y, radius);
+			} else {
+				canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
+						destination.x, destination.y);
+			}
+			for (var i = 0, l = stops.length; i < l; i++) {
+				var stop = stops[i];
+				canvasGradient.addColorStop(stop._offset || i / (l - 1),
+						stop._color.toCanvasStyle());
+			}
+			return this._canvasStyle = canvasGradient;
+		},
+
+		transform: function(matrix) {
+			if (this._type === 'gradient') {
+				var components = this._components;
+				for (var i = 1, l = components.length; i < l; i++) {
+					var point = components[i];
+					matrix._transformPoint(point, point, true);
+				}
+				this._changed();
+			}
+		},
+
+		statics: {
+			_types: types,
+
+			random: function() {
+				var random = Math.random;
+				return new Color(random(), random(), random());
+			}
+		}
+	});
+},
+new function() {
+	var operators = {
+		add: function(a, b) {
+			return a + b;
+		},
+
+		subtract: function(a, b) {
+			return a - b;
+		},
+
+		multiply: function(a, b) {
+			return a * b;
+		},
+
+		divide: function(a, b) {
+			return a / b;
+		}
+	};
+
+	return Base.each(operators, function(operator, name) {
+		this[name] = function(color) {
+			color = Color.read(arguments);
+			var type = this._type,
+				components1 = this._components,
+				components2 = color._convert(type);
+			for (var i = 0, l = components1.length; i < l; i++)
+				components2[i] = operator(components1[i], components2[i]);
+			return new Color(type, components2,
+					this._alpha != null
+							? operator(this._alpha, color.getAlpha())
+							: null);
+		};
+	}, {
+	});
+});
+
+var Gradient = Base.extend({
+	_class: 'Gradient',
+
+	initialize: function Gradient(stops, radial) {
+		this._id = UID.get();
+		if (stops && this._set(stops))
+			stops = radial = null;
+		if (!this._stops)
+			this.setStops(stops || ['white', 'black']);
+		if (this._radial == null) {
+			this.setRadial(typeof radial === 'string' && radial === 'radial'
+					|| radial || false);
+		}
+	},
+
+	_serialize: function(options, dictionary) {
+		return dictionary.add(this, function() {
+			return Base.serialize([this._stops, this._radial],
+					options, true, dictionary);
+		});
+	},
+
+	_changed: function() {
+		for (var i = 0, l = this._owners && this._owners.length; i < l; i++) {
+			this._owners[i]._changed();
+		}
+	},
+
+	_addOwner: function(color) {
+		if (!this._owners)
+			this._owners = [];
+		this._owners.push(color);
+	},
+
+	_removeOwner: function(color) {
+		var index = this._owners ? this._owners.indexOf(color) : -1;
+		if (index != -1) {
+			this._owners.splice(index, 1);
+			if (this._owners.length === 0)
+				this._owners = undefined;
+		}
+	},
+
+	clone: function() {
+		var stops = [];
+		for (var i = 0, l = this._stops.length; i < l; i++) {
+			stops[i] = this._stops[i].clone();
+		}
+		return new Gradient(stops, this._radial);
+	},
+
+	getStops: function() {
+		return this._stops;
+	},
+
+	setStops: function(stops) {
+		if (stops.length < 2) {
+			throw new Error(
+					'Gradient stop list needs to contain at least two stops.');
+		}
+		var _stops = this._stops;
+		if (_stops) {
+			for (var i = 0, l = _stops.length; i < l; i++)
+				_stops[i]._owner = undefined;
+		}
+		_stops = this._stops = GradientStop.readAll(stops, 0, { clone: true });
+		for (var i = 0, l = _stops.length; i < l; i++)
+			_stops[i]._owner = this;
+		this._changed();
+	},
+
+	getRadial: function() {
+		return this._radial;
+	},
+
+	setRadial: function(radial) {
+		this._radial = radial;
+		this._changed();
+	},
+
+	equals: function(gradient) {
+		if (gradient === this)
+			return true;
+		if (gradient && this._class === gradient._class) {
+			var stops1 = this._stops,
+				stops2 = gradient._stops,
+				length = stops1.length;
+			if (length === stops2.length) {
+				for (var i = 0; i < length; i++) {
+					if (!stops1[i].equals(stops2[i]))
+						return false;
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+});
+
+var GradientStop = Base.extend({
+	_class: 'GradientStop',
+
+	initialize: function GradientStop(arg0, arg1) {
+		var color = arg0,
+			offset = arg1;
+		if (typeof arg0 === 'object' && arg1 === undefined) {
+			if (Array.isArray(arg0) && typeof arg0[0] !== 'number') {
+				color = arg0[0];
+				offset = arg0[1];
+			} else if ('color' in arg0 || 'offset' in arg0
+					|| 'rampPoint' in arg0) {
+				color = arg0.color;
+				offset = arg0.offset || arg0.rampPoint || 0;
+			}
+		}
+		this.setColor(color);
+		this.setOffset(offset);
+	},
+
+	clone: function() {
+		return new GradientStop(this._color.clone(), this._offset);
+	},
+
+	_serialize: function(options, dictionary) {
+		var color = this._color,
+			offset = this._offset;
+		return Base.serialize(offset == null ? [color] : [color, offset],
+				options, true, dictionary);
+	},
+
+	_changed: function() {
+		if (this._owner)
+			this._owner._changed(65);
+	},
+
+	getOffset: function() {
+		return this._offset;
+	},
+
+	setOffset: function(offset) {
+		this._offset = offset;
+		this._changed();
+	},
+
+	getRampPoint: '#getOffset',
+	setRampPoint: '#setOffset',
+
+	getColor: function() {
+		return this._color;
+	},
+
+	setColor: function() {
+		var color = Color.read(arguments, 0, { clone: true });
+		if (color)
+			color._owner = this;
+		this._color = color;
+		this._changed();
+	},
+
+	equals: function(stop) {
+		return stop === this || stop && this._class === stop._class
+				&& this._color.equals(stop._color)
+				&& this._offset == stop._offset
+				|| false;
+	}
+});
+
+var Style = Base.extend(new function() {
+	var itemDefaults = {
+		fillColor: null,
+		fillRule: 'nonzero',
+		strokeColor: null,
+		strokeWidth: 1,
+		strokeCap: 'butt',
+		strokeJoin: 'miter',
+		strokeScaling: true,
+		miterLimit: 10,
+		dashOffset: 0,
+		dashArray: [],
+		shadowColor: null,
+		shadowBlur: 0,
+		shadowOffset: new Point(),
+		selectedColor: null
+	},
+	groupDefaults = Base.set({}, itemDefaults, {
+		fontFamily: 'sans-serif',
+		fontWeight: 'normal',
+		fontSize: 12,
+		leading: null,
+		justification: 'left'
+	}),
+	textDefaults = Base.set({}, groupDefaults, {
+		fillColor: new Color()
+	}),
+	flags = {
+		strokeWidth: 97,
+		strokeCap: 97,
+		strokeJoin: 97,
+		strokeScaling: 105,
+		miterLimit: 97,
+		fontFamily: 9,
+		fontWeight: 9,
+		fontSize: 9,
+		font: 9,
+		leading: 9,
+		justification: 9
+	},
+	item = {
+		beans: true
+	},
+	fields = {
+		_class: 'Style',
+		beans: true,
+
+		initialize: function Style(style, owner, project) {
+			this._values = {};
+			this._owner = owner;
+			this._project = owner && owner._project || project || paper.project;
+			this._defaults = !owner || owner instanceof Group ? groupDefaults
+					: owner instanceof TextItem ? textDefaults
+					: itemDefaults;
+			if (style)
+				this.set(style);
+		}
+	};
+
+	Base.each(groupDefaults, function(value, key) {
+		var isColor = /Color$/.test(key),
+			isPoint = key === 'shadowOffset',
+			part = Base.capitalize(key),
+			flag = flags[key],
+			set = 'set' + part,
+			get = 'get' + part;
+
+		fields[set] = function(value) {
+			var owner = this._owner,
+				children = owner && owner._children;
+			if (children && children.length > 0
+					&& !(owner instanceof CompoundPath)) {
+				for (var i = 0, l = children.length; i < l; i++)
+					children[i]._style[set](value);
+			} else if (key in this._defaults) {
+				var old = this._values[key];
+				if (old !== value) {
+					if (isColor) {
+						if (old && old._owner !== undefined)
+							old._owner = undefined;
+						if (value && value.constructor === Color) {
+							if (value._owner)
+								value = value.clone();
+							value._owner = owner;
+						}
+					}
+					this._values[key] = value;
+					if (owner)
+						owner._changed(flag || 65);
+				}
+			}
+		};
+
+		fields[get] = function(_dontMerge) {
+			var owner = this._owner,
+				children = owner && owner._children,
+				value;
+			if (key in this._defaults && (!children || children.length === 0
+					|| _dontMerge || owner instanceof CompoundPath)) {
+				var value = this._values[key];
+				if (value === undefined) {
+					value = this._defaults[key];
+					if (value && value.clone)
+						value = value.clone();
+				} else {
+					var ctor = isColor ? Color : isPoint ? Point : null;
+					if (ctor && !(value && value.constructor === ctor)) {
+						this._values[key] = value = ctor.read([value], 0,
+								{ readNull: true, clone: true });
+						if (value && isColor)
+							value._owner = owner;
+					}
+				}
+			} else if (children) {
+				for (var i = 0, l = children.length; i < l; i++) {
+					var childValue = children[i]._style[get]();
+					if (i === 0) {
+						value = childValue;
+					} else if (!Base.equals(value, childValue)) {
+						return undefined;
+					}
+				}
+			}
+			return value;
+		};
+
+		item[get] = function(_dontMerge) {
+			return this._style[get](_dontMerge);
+		};
+
+		item[set] = function(value) {
+			this._style[set](value);
+		};
+	});
+
+	Base.each({
+		Font: 'FontFamily',
+		WindingRule: 'FillRule'
+	}, function(value, key) {
+		var get = 'get' + key,
+			set = 'set' + key;
+		fields[get] = item[get] = '#get' + value;
+		fields[set] = item[set] = '#set' + value;
+	});
+
+	Item.inject(item);
+	return fields;
+}, {
+	set: function(style) {
+		var isStyle = style instanceof Style,
+			values = isStyle ? style._values : style;
+		if (values) {
+			for (var key in values) {
+				if (key in this._defaults) {
+					var value = values[key];
+					this[key] = value && isStyle && value.clone
+							? value.clone() : value;
+				}
+			}
+		}
+	},
+
+	equals: function(style) {
+		return style === this || style && this._class === style._class
+				&& Base.equals(this._values, style._values)
+				|| false;
+	},
+
+	hasFill: function() {
+		var color = this.getFillColor();
+		return !!color && color.alpha > 0;
+	},
+
+	hasStroke: function() {
+		var color = this.getStrokeColor();
+		return !!color && color.alpha > 0 && this.getStrokeWidth() > 0;
+	},
+
+	hasShadow: function() {
+		var color = this.getShadowColor();
+		return !!color && color.alpha > 0 && (this.getShadowBlur() > 0
+				|| !this.getShadowOffset().isZero());
+	},
+
+	getView: function() {
+		return this._project._view;
+	},
+
+	getFontStyle: function() {
+		var fontSize = this.getFontSize();
+		return this.getFontWeight()
+				+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')
+				+ this.getFontFamily();
+	},
+
+	getFont: '#getFontFamily',
+	setFont: '#setFontFamily',
+
+	getLeading: function getLeading() {
+		var leading = getLeading.base.call(this),
+			fontSize = this.getFontSize();
+		if (/pt|em|%|px/.test(fontSize))
+			fontSize = this.getView().getPixelSize(fontSize);
+		return leading != null ? leading : fontSize * 1.2;
+	}
+
+});
+
+var DomElement = new function() {
+	function handlePrefix(el, name, set, value) {
+		var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],
+			suffix = name[0].toUpperCase() + name.substring(1);
+		for (var i = 0; i < 6; i++) {
+			var prefix = prefixes[i],
+				key = prefix ? prefix + suffix : name;
+			if (key in el) {
+				if (set) {
+					el[key] = value;
+				} else {
+					return el[key];
+				}
+				break;
+			}
+		}
+	}
+
+	return {
+		getStyles: function(el) {
+			var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
+				view = doc && doc.defaultView;
+			return view && view.getComputedStyle(el, '');
+		},
+
+		getBounds: function(el, viewport) {
+			var doc = el.ownerDocument,
+				body = doc.body,
+				html = doc.documentElement,
+				rect;
+			try {
+				rect = el.getBoundingClientRect();
+			} catch (e) {
+				rect = { left: 0, top: 0, width: 0, height: 0 };
+			}
+			var x = rect.left - (html.clientLeft || body.clientLeft || 0),
+				y = rect.top - (html.clientTop || body.clientTop || 0);
+			if (!viewport) {
+				var view = doc.defaultView;
+				x += view.pageXOffset || html.scrollLeft || body.scrollLeft;
+				y += view.pageYOffset || html.scrollTop || body.scrollTop;
+			}
+			return new Rectangle(x, y, rect.width, rect.height);
+		},
+
+		getViewportBounds: function(el) {
+			var doc = el.ownerDocument,
+				view = doc.defaultView,
+				html = doc.documentElement;
+			return new Rectangle(0, 0,
+				view.innerWidth || html.clientWidth,
+				view.innerHeight || html.clientHeight
+			);
+		},
+
+		getOffset: function(el, viewport) {
+			return DomElement.getBounds(el, viewport).getPoint();
+		},
+
+		getSize: function(el) {
+			return DomElement.getBounds(el, true).getSize();
+		},
+
+		isInvisible: function(el) {
+			return DomElement.getSize(el).equals(new Size(0, 0));
+		},
+
+		isInView: function(el) {
+			return !DomElement.isInvisible(el)
+					&& DomElement.getViewportBounds(el).intersects(
+						DomElement.getBounds(el, true));
+		},
+
+		isInserted: function(el) {
+			return document.body.contains(el);
+		},
+
+		getPrefixed: function(el, name) {
+			return el && handlePrefix(el, name);
+		},
+
+		setPrefixed: function(el, name, value) {
+			if (typeof name === 'object') {
+				for (var key in name)
+					handlePrefix(el, key, true, name[key]);
+			} else {
+				handlePrefix(el, name, true, value);
+			}
+		}
+	};
+};
+
+var DomEvent = {
+	add: function(el, events) {
+		if (el) {
+			for (var type in events) {
+				var func = events[type],
+					parts = type.split(/[\s,]+/g);
+				for (var i = 0, l = parts.length; i < l; i++)
+					el.addEventListener(parts[i], func, false);
+			}
+		}
+	},
+
+	remove: function(el, events) {
+		if (el) {
+			for (var type in events) {
+				var func = events[type],
+					parts = type.split(/[\s,]+/g);
+				for (var i = 0, l = parts.length; i < l; i++)
+					el.removeEventListener(parts[i], func, false);
+			}
+		}
+	},
+
+	getPoint: function(event) {
+		var pos = event.targetTouches
+				? event.targetTouches.length
+					? event.targetTouches[0]
+					: event.changedTouches[0]
+				: event;
+		return new Point(
+			pos.pageX || pos.clientX + document.documentElement.scrollLeft,
+			pos.pageY || pos.clientY + document.documentElement.scrollTop
+		);
+	},
+
+	getTarget: function(event) {
+		return event.target || event.srcElement;
+	},
+
+	getRelatedTarget: function(event) {
+		return event.relatedTarget || event.toElement;
+	},
+
+	getOffset: function(event, target) {
+		return DomEvent.getPoint(event).subtract(DomElement.getOffset(
+				target || DomEvent.getTarget(event)));
+	}
+};
+
+DomEvent.requestAnimationFrame = new function() {
+	var nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),
+		requested = false,
+		callbacks = [],
+		timer;
+
+	function handleCallbacks() {
+		var functions = callbacks;
+		callbacks = [];
+		for (var i = 0, l = functions.length; i < l; i++)
+			functions[i]();
+		requested = nativeRequest && callbacks.length;
+		if (requested)
+			nativeRequest(handleCallbacks);
+	}
+
+	return function(callback) {
+		callbacks.push(callback);
+		if (nativeRequest) {
+			if (!requested) {
+				nativeRequest(handleCallbacks);
+				requested = true;
+			}
+		} else if (!timer) {
+			timer = setInterval(handleCallbacks, 1000 / 60);
+		}
+	};
+};
+
+var View = Base.extend(Emitter, {
+	_class: 'View',
+
+	initialize: function View(project, element) {
+
+		function getSize(name) {
+			return element[name] || parseInt(element.getAttribute(name), 10);
+		}
+
+		function getCanvasSize() {
+			var size = DomElement.getSize(element);
+			return size.isNaN() || size.isZero()
+					? new Size(getSize('width'), getSize('height'))
+					: size;
+		}
+
+		var size;
+		if (window && element) {
+			this._id = element.getAttribute('id');
+			if (this._id == null)
+				element.setAttribute('id', this._id = 'view-' + View._id++);
+			DomEvent.add(element, this._viewEvents);
+			var none = 'none';
+			DomElement.setPrefixed(element.style, {
+				userDrag: none,
+				userSelect: none,
+				touchCallout: none,
+				contentZooming: none,
+				tapHighlightColor: 'rgba(0,0,0,0)'
+			});
+
+			if (PaperScope.hasAttribute(element, 'resize')) {
+				var that = this;
+				DomEvent.add(window, this._windowEvents = {
+					resize: function() {
+						that.setViewSize(getCanvasSize());
+					}
+				});
+			}
+
+			size = getCanvasSize();
+
+			if (PaperScope.hasAttribute(element, 'stats')
+					&& typeof Stats !== 'undefined') {
+				this._stats = new Stats();
+				var stats = this._stats.domElement,
+					style = stats.style,
+					offset = DomElement.getOffset(element);
+				style.position = 'absolute';
+				style.left = offset.x + 'px';
+				style.top = offset.y + 'px';
+				document.body.appendChild(stats);
+			}
+		} else {
+			size = new Size(element);
+			element = null;
+		}
+		this._project = project;
+		this._scope = project._scope;
+		this._element = element;
+		if (!this._pixelRatio)
+			this._pixelRatio = window && window.devicePixelRatio || 1;
+		this._setElementSize(size.width, size.height);
+		this._viewSize = size;
+		View._views.push(this);
+		View._viewsById[this._id] = this;
+		(this._matrix = new Matrix())._owner = this;
+		this._zoom = 1;
+		if (!View._focused)
+			View._focused = this;
+		this._frameItems = {};
+		this._frameItemCount = 0;
+		this._itemEvents = { native: {}, virtual: {} };
+		this._autoUpdate = !paper.agent.node;
+		this._needsUpdate = false;
+	},
+
+	remove: function() {
+		if (!this._project)
+			return false;
+		if (View._focused === this)
+			View._focused = null;
+		View._views.splice(View._views.indexOf(this), 1);
+		delete View._viewsById[this._id];
+		var project = this._project;
+		if (project._view === this)
+			project._view = null;
+		DomEvent.remove(this._element, this._viewEvents);
+		DomEvent.remove(window, this._windowEvents);
+		this._element = this._project = null;
+		this.off('frame');
+		this._animate = false;
+		this._frameItems = {};
+		return true;
+	},
+
+	_events: Base.each(
+		Item._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),
+		function(name) {
+			this[name] = {};
+		}, {
+			onFrame: {
+				install: function() {
+					this.play();
+				},
+
+				uninstall: function() {
+					this.pause();
+				}
+			}
+		}
+	),
+
+	_animate: false,
+	_time: 0,
+	_count: 0,
+
+	getAutoUpdate: function() {
+		return this._autoUpdate;
+	},
+
+	setAutoUpdate: function(autoUpdate) {
+		this._autoUpdate = autoUpdate;
+		if (autoUpdate)
+			this.requestUpdate();
+	},
+
+	update: function() {
+	},
+
+	draw: function() {
+		this.update();
+	},
+
+	requestUpdate: function() {
+		if (!this._requested) {
+			var that = this;
+			DomEvent.requestAnimationFrame(function() {
+				that._requested = false;
+				if (that._animate) {
+					that.requestUpdate();
+					var element = that._element;
+					if ((!DomElement.getPrefixed(document, 'hidden')
+							|| PaperScope.getAttribute(element, 'keepalive')
+								=== 'true') && DomElement.isInView(element)) {
+						that._handleFrame();
+					}
+				}
+				if (that._autoUpdate)
+					that.update();
+			});
+			this._requested = true;
+		}
+	},
+
+	play: function() {
+		this._animate = true;
+		this.requestUpdate();
+	},
+
+	pause: function() {
+		this._animate = false;
+	},
+
+	_handleFrame: function() {
+		paper = this._scope;
+		var now = Date.now() / 1000,
+			delta = this._last ? now - this._last : 0;
+		this._last = now;
+		this.emit('frame', new Base({
+			delta: delta,
+			time: this._time += delta,
+			count: this._count++
+		}));
+		if (this._stats)
+			this._stats.update();
+	},
+
+	_animateItem: function(item, animate) {
+		var items = this._frameItems;
+		if (animate) {
+			items[item._id] = {
+				item: item,
+				time: 0,
+				count: 0
+			};
+			if (++this._frameItemCount === 1)
+				this.on('frame', this._handleFrameItems);
+		} else {
+			delete items[item._id];
+			if (--this._frameItemCount === 0) {
+				this.off('frame', this._handleFrameItems);
+			}
+		}
+	},
+
+	_handleFrameItems: function(event) {
+		for (var i in this._frameItems) {
+			var entry = this._frameItems[i];
+			entry.item.emit('frame', new Base(event, {
+				time: entry.time += event.delta,
+				count: entry.count++
+			}));
+		}
+	},
+
+	_changed: function() {
+		this._project._changed(2049);
+		this._bounds = null;
+	},
+
+	getElement: function() {
+		return this._element;
+	},
+
+	getPixelRatio: function() {
+		return this._pixelRatio;
+	},
+
+	getResolution: function() {
+		return this._pixelRatio * 72;
+	},
+
+	getViewSize: function() {
+		var size = this._viewSize;
+		return new LinkedSize(size.width, size.height, this, 'setViewSize');
+	},
+
+	setViewSize: function() {
+		var size = Size.read(arguments),
+			width = size.width,
+			height = size.height,
+			delta = size.subtract(this._viewSize);
+		if (delta.isZero())
+			return;
+		this._setElementSize(width, height);
+		this._viewSize.set(width, height);
+		this.emit('resize', {
+			size: size,
+			delta: delta
+		});
+		this._changed();
+		if (this._autoUpdate)
+			this.requestUpdate();
+	},
+
+	_setElementSize: function(width, height) {
+		var element = this._element;
+		if (element) {
+			if (element.width !== width)
+				element.width = width;
+			if (element.height !== height)
+				element.height = height;
+		}
+	},
+
+	getBounds: function() {
+		if (!this._bounds)
+			this._bounds = this._matrix.inverted()._transformBounds(
+					new Rectangle(new Point(), this._viewSize));
+		return this._bounds;
+	},
+
+	getSize: function() {
+		return this.getBounds().getSize();
+	},
+
+	getCenter: function() {
+		return this.getBounds().getCenter();
+	},
+
+	setCenter: function() {
+		var center = Point.read(arguments);
+		this.translate(this.getCenter().subtract(center));
+	},
+
+	getZoom: function() {
+		return this._zoom;
+	},
+
+	setZoom: function(zoom) {
+		this.transform(new Matrix().scale(zoom / this._zoom,
+			this.getCenter()));
+		this._zoom = zoom;
+	},
+
+	getMatrix: function() {
+		return this._matrix;
+	},
+
+	setMatrix: function() {
+		var matrix = this._matrix;
+		matrix.initialize.apply(matrix, arguments);
+	},
+
+	isVisible: function() {
+		return DomElement.isInView(this._element);
+	},
+
+	isInserted: function() {
+		return DomElement.isInserted(this._element);
+	},
+
+	getPixelSize: function(size) {
+		var element = this._element,
+			pixels;
+		if (element) {
+			var parent = element.parentNode,
+				temp = document.createElement('div');
+			temp.style.fontSize = size;
+			parent.appendChild(temp);
+			pixels = parseFloat(DomElement.getStyles(temp).fontSize);
+			parent.removeChild(temp);
+		} else {
+			pixels = parseFloat(pixels);
+		}
+		return pixels;
+	},
+
+	getTextWidth: function(font, lines) {
+		return 0;
+	}
+}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
+	var rotate = key === 'rotate';
+	this[key] = function() {
+		var value = (rotate ? Base : Point).read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		return this.transform(new Matrix()[key](value,
+				center || this.getCenter(true)));
+	};
+}, {
+	translate: function() {
+		var mx = new Matrix();
+		return this.transform(mx.translate.apply(mx, arguments));
+	},
+
+	transform: function(matrix) {
+		this._matrix.append(matrix);
+	},
+
+	scrollBy: function() {
+		this.translate(Point.read(arguments).negate());
+	}
+}), {
+
+	projectToView: function() {
+		return this._matrix._transformPoint(Point.read(arguments));
+	},
+
+	viewToProject: function() {
+		return this._matrix._inverseTransform(Point.read(arguments));
+	},
+
+	getEventPoint: function(event) {
+		return this.viewToProject(DomEvent.getOffset(event, this._element));
+	},
+
+}, {
+	statics: {
+		_views: [],
+		_viewsById: {},
+		_id: 0,
+
+		create: function(project, element) {
+			if (document && typeof element === 'string')
+				element = document.getElementById(element);
+			var ctor = window ? CanvasView : View;
+			return new ctor(project, element);
+		}
+	}
+},
+new function() {
+	if (!window)
+		return;
+	var prevFocus,
+		tempFocus,
+		dragging = false,
+		mouseDown = false;
+
+	function getView(event) {
+		var target = DomEvent.getTarget(event);
+		return target.getAttribute && View._viewsById[
+				target.getAttribute('id')];
+	}
+
+	function updateFocus() {
+		var view = View._focused;
+		if (!view || !view.isVisible()) {
+			for (var i = 0, l = View._views.length; i < l; i++) {
+				if ((view = View._views[i]).isVisible()) {
+					View._focused = tempFocus = view;
+					break;
+				}
+			}
+		}
+	}
+
+	function handleMouseMove(view, event, point) {
+		view._handleMouseEvent('mousemove', event, point);
+	}
+
+	var navigator = window.navigator,
+		mousedown, mousemove, mouseup;
+	if (navigator.pointerEnabled || navigator.msPointerEnabled) {
+		mousedown = 'pointerdown MSPointerDown';
+		mousemove = 'pointermove MSPointerMove';
+		mouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';
+	} else {
+		mousedown = 'touchstart';
+		mousemove = 'touchmove';
+		mouseup = 'touchend touchcancel';
+		if (!('ontouchstart' in window && navigator.userAgent.match(
+				/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {
+			mousedown += ' mousedown';
+			mousemove += ' mousemove';
+			mouseup += ' mouseup';
+		}
+	}
+
+	var viewEvents = {},
+		docEvents = {
+			mouseout: function(event) {
+				var view = View._focused,
+					target = DomEvent.getRelatedTarget(event);
+				if (view && (!target || target.nodeName === 'HTML')) {
+					var offset = DomEvent.getOffset(event, view._element),
+						x = offset.x,
+						abs = Math.abs,
+						ax = abs(x),
+						max = 1 << 25,
+						diff = ax - max;
+					offset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;
+					handleMouseMove(view, event, view.viewToProject(offset));
+				}
+			},
+
+			scroll: updateFocus
+		};
+
+	viewEvents[mousedown] = function(event) {
+		var view = View._focused = getView(event);
+		if (!dragging) {
+			dragging = true;
+			view._handleMouseEvent('mousedown', event);
+		}
+	};
+
+	docEvents[mousemove] = function(event) {
+		var view = View._focused;
+		if (!mouseDown) {
+			var target = getView(event);
+			if (target) {
+				if (view !== target) {
+					if (view)
+						handleMouseMove(view, event);
+					if (!prevFocus)
+						prevFocus = view;
+					view = View._focused = tempFocus = target;
+				}
+			} else if (tempFocus && tempFocus === view) {
+				if (prevFocus && !prevFocus.isInserted())
+					prevFocus = null;
+				view = View._focused = prevFocus;
+				prevFocus = null;
+				updateFocus();
+			}
+		}
+		if (view)
+			handleMouseMove(view, event);
+	};
+
+	docEvents[mousedown] = function() {
+		mouseDown = true;
+	};
+
+	docEvents[mouseup] = function(event) {
+		var view = View._focused;
+		if (view && dragging)
+			view._handleMouseEvent('mouseup', event);
+		mouseDown = dragging = false;
+	};
+
+	DomEvent.add(document, docEvents);
+
+	DomEvent.add(window, {
+		load: updateFocus
+	});
+
+	var called = false,
+		prevented = false,
+		fallbacks = {
+			doubleclick: 'click',
+			mousedrag: 'mousemove'
+		},
+		wasInView = false,
+		overView,
+		downPoint,
+		lastPoint,
+		downItem,
+		overItem,
+		dragItem,
+		clickItem,
+		clickTime,
+		dblClick;
+
+	function emitMouseEvent(obj, target, type, event, point, prevPoint,
+			stopItem) {
+		var stopped = false,
+			mouseEvent;
+
+		function emit(obj, type) {
+			if (obj.responds(type)) {
+				if (!mouseEvent) {
+					mouseEvent = new MouseEvent(type, event, point,
+							target || obj,
+							prevPoint ? point.subtract(prevPoint) : null);
+				}
+				if (obj.emit(type, mouseEvent)) {
+					called = true;
+					if (mouseEvent.prevented)
+						prevented = true;
+					if (mouseEvent.stopped)
+						return stopped = true;
+				}
+			} else {
+				var fallback = fallbacks[type];
+				if (fallback)
+					return emit(obj, fallback);
+			}
+		}
+
+		while (obj && obj !== stopItem) {
+			if (emit(obj, type))
+				break;
+			obj = obj._parent;
+		}
+		return stopped;
+	}
+
+	function emitMouseEvents(view, hitItem, type, event, point, prevPoint) {
+		view._project.removeOn(type);
+		prevented = called = false;
+		return (dragItem && emitMouseEvent(dragItem, null, type, event,
+					point, prevPoint)
+			|| hitItem && hitItem !== dragItem
+				&& !hitItem.isDescendant(dragItem)
+				&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
+					point, prevPoint, dragItem)
+			|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
+					point, prevPoint));
+	}
+
+	var itemEventsMap = {
+		mousedown: {
+			mousedown: 1,
+			mousedrag: 1,
+			click: 1,
+			doubleclick: 1
+		},
+		mouseup: {
+			mouseup: 1,
+			mousedrag: 1,
+			click: 1,
+			doubleclick: 1
+		},
+		mousemove: {
+			mousedrag: 1,
+			mousemove: 1,
+			mouseenter: 1,
+			mouseleave: 1
+		}
+	};
+
+	return {
+		_viewEvents: viewEvents,
+
+		_handleMouseEvent: function(type, event, point) {
+			var itemEvents = this._itemEvents,
+				hitItems = itemEvents.native[type],
+				nativeMove = type === 'mousemove',
+				tool = this._scope.tool,
+				view = this;
+
+			function responds(type) {
+				return itemEvents.virtual[type] || view.responds(type)
+						|| tool && tool.responds(type);
+			}
+
+			if (nativeMove && dragging && responds('mousedrag'))
+				type = 'mousedrag';
+			if (!point)
+				point = this.getEventPoint(event);
+
+			var inView = this.getBounds().contains(point),
+				hit = hitItems && inView && view._project.hitTest(point, {
+					tolerance: 0,
+					fill: true,
+					stroke: true
+				}),
+				hitItem = hit && hit.item || null,
+				handle = false,
+				mouse = {};
+			mouse[type.substr(5)] = true;
+
+			if (hitItems && hitItem !== overItem) {
+				if (overItem) {
+					emitMouseEvent(overItem, null, 'mouseleave', event, point);
+				}
+				if (hitItem) {
+					emitMouseEvent(hitItem, null, 'mouseenter', event, point);
+				}
+				overItem = hitItem;
+			}
+			if (wasInView ^ inView) {
+				emitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',
+						event, point);
+				overView = inView ? this : null;
+				handle = true;
+			}
+			if ((inView || mouse.drag) && !point.equals(lastPoint)) {
+				emitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',
+						event, point, lastPoint);
+				handle = true;
+			}
+			wasInView = inView;
+			if (mouse.down && inView || mouse.up && downPoint) {
+				emitMouseEvents(this, hitItem, type, event, point, downPoint);
+				if (mouse.down) {
+					dblClick = hitItem === clickItem
+						&& (Date.now() - clickTime < 300);
+					downItem = clickItem = hitItem;
+					dragItem = !prevented && hitItem;
+					downPoint = point;
+				} else if (mouse.up) {
+					if (!prevented && hitItem === downItem) {
+						clickTime = Date.now();
+						emitMouseEvents(this, hitItem, dblClick ? 'doubleclick'
+								: 'click', event, point, downPoint);
+						dblClick = false;
+					}
+					downItem = dragItem = null;
+				}
+				wasInView = false;
+				handle = true;
+			}
+			lastPoint = point;
+			if (handle && tool) {
+				called = tool._handleMouseEvent(type, event, point, mouse)
+					|| called;
+			}
+
+			if (called && !mouse.move || mouse.down && responds('mouseup'))
+				event.preventDefault();
+		},
+
+		_handleKeyEvent: function(type, event, key, character) {
+			var scope = this._scope,
+				tool = scope.tool,
+				keyEvent;
+
+			function emit(obj) {
+				if (obj.responds(type)) {
+					paper = scope;
+					obj.emit(type, keyEvent = keyEvent
+							|| new KeyEvent(type, event, key, character));
+				}
+			}
+
+			if (this.isVisible()) {
+				emit(this);
+				if (tool && tool.responds(type))
+					emit(tool);
+			}
+		},
+
+		_countItemEvent: function(type, sign) {
+			var itemEvents = this._itemEvents,
+				native = itemEvents.native,
+				virtual = itemEvents.virtual;
+			for (var key in itemEventsMap) {
+				native[key] = (native[key] || 0)
+						+ (itemEventsMap[key][type] || 0) * sign;
+			}
+			virtual[type] = (virtual[type] || 0) + sign;
+		},
+
+		statics: {
+			updateFocus: updateFocus
+		}
+	};
+});
+
+var CanvasView = View.extend({
+	_class: 'CanvasView',
+
+	initialize: function CanvasView(project, canvas) {
+		if (!(canvas instanceof window.HTMLCanvasElement)) {
+			var size = Size.read(arguments, 1);
+			if (size.isZero())
+				throw new Error(
+						'Cannot create CanvasView with the provided argument: '
+						+ [].slice.call(arguments, 1));
+			canvas = CanvasProvider.getCanvas(size);
+		}
+		var ctx = this._context = canvas.getContext('2d');
+		ctx.save();
+		this._pixelRatio = 1;
+		if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {
+			var deviceRatio = window.devicePixelRatio || 1,
+				backingStoreRatio = DomElement.getPrefixed(ctx,
+						'backingStorePixelRatio') || 1;
+			this._pixelRatio = deviceRatio / backingStoreRatio;
+		}
+		View.call(this, project, canvas);
+		this._needsUpdate = true;
+	},
+
+	remove: function remove() {
+		this._context.restore();
+		return remove.base.call(this);
+	},
+
+	_setElementSize: function _setElementSize(width, height) {
+		var pixelRatio = this._pixelRatio;
+		_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);
+		if (pixelRatio !== 1) {
+			var element = this._element,
+				ctx = this._context;
+			if (!PaperScope.hasAttribute(element, 'resize')) {
+				var style = element.style;
+				style.width = width + 'px';
+				style.height = height + 'px';
+			}
+			ctx.restore();
+			ctx.save();
+			ctx.scale(pixelRatio, pixelRatio);
+		}
+	},
+
+	getPixelSize: function getPixelSize(size) {
+		var agent = paper.agent,
+			pixels;
+		if (agent && agent.firefox) {
+			pixels = getPixelSize.base.call(this, size);
+		} else {
+			var ctx = this._context,
+				prevFont = ctx.font;
+			ctx.font = size + ' serif';
+			pixels = parseFloat(ctx.font);
+			ctx.font = prevFont;
+		}
+		return pixels;
+	},
+
+	getTextWidth: function(font, lines) {
+		var ctx = this._context,
+			prevFont = ctx.font,
+			width = 0;
+		ctx.font = font;
+		for (var i = 0, l = lines.length; i < l; i++)
+			width = Math.max(width, ctx.measureText(lines[i]).width);
+		ctx.font = prevFont;
+		return width;
+	},
+
+	update: function() {
+		if (!this._needsUpdate)
+			return false;
+		var project = this._project,
+			ctx = this._context,
+			size = this._viewSize;
+		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
+		if (project)
+			project.draw(ctx, this._matrix, this._pixelRatio);
+		this._needsUpdate = false;
+		return true;
+	}
+});
+
+var Event = Base.extend({
+	_class: 'Event',
+
+	initialize: function Event(event) {
+		this.event = event;
+		this.type = event && event.type;
+	},
+
+	prevented: false,
+	stopped: false,
+
+	preventDefault: function() {
+		this.prevented = true;
+		this.event.preventDefault();
+	},
+
+	stopPropagation: function() {
+		this.stopped = true;
+		this.event.stopPropagation();
+	},
+
+	stop: function() {
+		this.stopPropagation();
+		this.preventDefault();
+	},
+
+	getTimeStamp: function() {
+		return this.event.timeStamp;
+	},
+
+	getModifiers: function() {
+		return Key.modifiers;
+	}
+});
+
+var KeyEvent = Event.extend({
+	_class: 'KeyEvent',
+
+	initialize: function KeyEvent(type, event, key, character) {
+		this.type = type;
+		this.event = event;
+		this.key = key;
+		this.character = character;
+	},
+
+	toString: function() {
+		return "{ type: '" + this.type
+				+ "', key: '" + this.key
+				+ "', character: '" + this.character
+				+ "', modifiers: " + this.getModifiers()
+				+ " }";
+	}
+});
+
+var Key = new function() {
+	var keyLookup = {
+			'\t': 'tab',
+			' ': 'space',
+			'\b': 'backspace',
+			'\x7f': 'delete',
+			'Spacebar': 'space',
+			'Del': 'delete',
+			'Win': 'meta',
+			'Esc': 'escape'
+		},
+
+		charLookup = {
+			'tab': '\t',
+			'space': ' ',
+			'enter': '\r'
+		},
+
+		keyMap = {},
+		charMap = {},
+		metaFixMap,
+		downKey,
+
+		modifiers = new Base({
+			shift: false,
+			control: false,
+			alt: false,
+			meta: false,
+			capsLock: false,
+			space: false
+		}).inject({
+			option: {
+				get: function() {
+					return this.alt;
+				}
+			},
+
+			command: {
+				get: function() {
+					var agent = paper && paper.agent;
+					return agent && agent.mac ? this.meta : this.control;
+				}
+			}
+		});
+
+	function getKey(event) {
+		var key = event.key || event.keyIdentifier;
+		key = /^U\+/.test(key)
+				? String.fromCharCode(parseInt(key.substr(2), 16))
+				: /^Arrow[A-Z]/.test(key) ? key.substr(5)
+				: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
+				: key;
+		return keyLookup[key] ||
+				(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());
+	}
+
+	function handleKey(down, key, character, event) {
+		var type = down ? 'keydown' : 'keyup',
+			view = View._focused,
+			name;
+		keyMap[key] = down;
+		if (down) {
+			charMap[key] = character;
+		} else {
+			delete charMap[key];
+		}
+		if (key.length > 1 && (name = Base.camelize(key)) in modifiers) {
+			modifiers[name] = down;
+			var agent = paper && paper.agent;
+			if (name === 'meta' && agent && agent.mac) {
+				if (down) {
+					metaFixMap = {};
+				} else {
+					for (var k in metaFixMap) {
+						if (k in charMap)
+							handleKey(false, k, metaFixMap[k], event);
+					}
+					metaFixMap = null;
+				}
+			}
+		} else if (down && metaFixMap) {
+			metaFixMap[key] = character;
+		}
+		if (view) {
+			view._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,
+					character);
+		}
+	}
+
+	DomEvent.add(document, {
+		keydown: function(event) {
+			var key = getKey(event),
+				agent = paper && paper.agent;
+			if (key.length > 1 || agent && (agent.chrome && (event.altKey
+						|| agent.mac && event.metaKey
+						|| !agent.mac && event.ctrlKey))) {
+				handleKey(true, key,
+						charLookup[key] || (key.length > 1 ? '' : key), event);
+			} else {
+				downKey = key;
+			}
+		},
+
+		keypress: function(event) {
+			if (downKey) {
+				var key = getKey(event),
+					code = event.charCode,
+					character = code >= 32 ? String.fromCharCode(code)
+						: key.length > 1 ? '' : key;
+				if (key !== downKey) {
+					key = character.toLowerCase();
+				}
+				handleKey(true, key, character, event);
+				downKey = null;
+			}
+		},
+
+		keyup: function(event) {
+			var key = getKey(event);
+			if (key in charMap)
+				handleKey(false, key, charMap[key], event);
+		}
+	});
+
+	DomEvent.add(window, {
+		blur: function(event) {
+			for (var key in charMap)
+				handleKey(false, key, charMap[key], event);
+		}
+	});
+
+	return {
+		modifiers: modifiers,
+
+		isDown: function(key) {
+			return !!keyMap[key];
+		}
+	};
+};
+
+var MouseEvent = Event.extend({
+	_class: 'MouseEvent',
+
+	initialize: function MouseEvent(type, event, point, target, delta) {
+		this.type = type;
+		this.event = event;
+		this.point = point;
+		this.target = target;
+		this.delta = delta;
+	},
+
+	toString: function() {
+		return "{ type: '" + this.type
+				+ "', point: " + this.point
+				+ ', target: ' + this.target
+				+ (this.delta ? ', delta: ' + this.delta : '')
+				+ ', modifiers: ' + this.getModifiers()
+				+ ' }';
+	}
+});
+
+var ToolEvent = Event.extend({
+	_class: 'ToolEvent',
+	_item: null,
+
+	initialize: function ToolEvent(tool, type, event) {
+		this.tool = tool;
+		this.type = type;
+		this.event = event;
+	},
+
+	_choosePoint: function(point, toolPoint) {
+		return point ? point : toolPoint ? toolPoint.clone() : null;
+	},
+
+	getPoint: function() {
+		return this._choosePoint(this._point, this.tool._point);
+	},
+
+	setPoint: function(point) {
+		this._point = point;
+	},
+
+	getLastPoint: function() {
+		return this._choosePoint(this._lastPoint, this.tool._lastPoint);
+	},
+
+	setLastPoint: function(lastPoint) {
+		this._lastPoint = lastPoint;
+	},
+
+	getDownPoint: function() {
+		return this._choosePoint(this._downPoint, this.tool._downPoint);
+	},
+
+	setDownPoint: function(downPoint) {
+		this._downPoint = downPoint;
+	},
+
+	getMiddlePoint: function() {
+		if (!this._middlePoint && this.tool._lastPoint) {
+			return this.tool._point.add(this.tool._lastPoint).divide(2);
+		}
+		return this._middlePoint;
+	},
+
+	setMiddlePoint: function(middlePoint) {
+		this._middlePoint = middlePoint;
+	},
+
+	getDelta: function() {
+		return !this._delta && this.tool._lastPoint
+				? this.tool._point.subtract(this.tool._lastPoint)
+				: this._delta;
+	},
+
+	setDelta: function(delta) {
+		this._delta = delta;
+	},
+
+	getCount: function() {
+		return this.tool[/^mouse(down|up)$/.test(this.type)
+				? '_downCount' : '_moveCount'];
+	},
+
+	setCount: function(count) {
+		this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
+			= count;
+	},
+
+	getItem: function() {
+		if (!this._item) {
+			var result = this.tool._scope.project.hitTest(this.getPoint());
+			if (result) {
+				var item = result.item,
+					parent = item._parent;
+				while (/^(Group|CompoundPath)$/.test(parent._class)) {
+					item = parent;
+					parent = parent._parent;
+				}
+				this._item = item;
+			}
+		}
+		return this._item;
+	},
+
+	setItem: function(item) {
+		this._item = item;
+	},
+
+	toString: function() {
+		return '{ type: ' + this.type
+				+ ', point: ' + this.getPoint()
+				+ ', count: ' + this.getCount()
+				+ ', modifiers: ' + this.getModifiers()
+				+ ' }';
+	}
+});
+
+var Tool = PaperScopeItem.extend({
+	_class: 'Tool',
+	_list: 'tools',
+	_reference: 'tool',
+	_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',
+			'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',
+			'onKeyUp'],
+
+	initialize: function Tool(props) {
+		PaperScopeItem.call(this);
+		this._moveCount = -1;
+		this._downCount = -1;
+		this._set(props);
+	},
+
+	getMinDistance: function() {
+		return this._minDistance;
+	},
+
+	setMinDistance: function(minDistance) {
+		this._minDistance = minDistance;
+		if (minDistance != null && this._maxDistance != null
+				&& minDistance > this._maxDistance) {
+			this._maxDistance = minDistance;
+		}
+	},
+
+	getMaxDistance: function() {
+		return this._maxDistance;
+	},
+
+	setMaxDistance: function(maxDistance) {
+		this._maxDistance = maxDistance;
+		if (this._minDistance != null && maxDistance != null
+				&& maxDistance < this._minDistance) {
+			this._minDistance = maxDistance;
+		}
+	},
+
+	getFixedDistance: function() {
+		return this._minDistance == this._maxDistance
+			? this._minDistance : null;
+	},
+
+	setFixedDistance: function(distance) {
+		this._minDistance = this._maxDistance = distance;
+	},
+
+	_handleMouseEvent: function(type, event, point, mouse) {
+		paper = this._scope;
+		if (mouse.drag && !this.responds(type))
+			type = 'mousemove';
+		var move = mouse.move || mouse.drag,
+			responds = this.responds(type),
+			minDistance = this.minDistance,
+			maxDistance = this.maxDistance,
+			called = false,
+			tool = this;
+		function update(minDistance, maxDistance) {
+			var pt = point,
+				toolPoint = move ? tool._point : (tool._downPoint || pt);
+			if (move) {
+				if (tool._moveCount && pt.equals(toolPoint)) {
+					return false;
+				}
+				if (toolPoint && (minDistance != null || maxDistance != null)) {
+					var vector = pt.subtract(toolPoint),
+						distance = vector.getLength();
+					if (distance < (minDistance || 0))
+						return false;
+					if (maxDistance) {
+						pt = toolPoint.add(vector.normalize(
+								Math.min(distance, maxDistance)));
+					}
+				}
+				tool._moveCount++;
+			}
+			tool._point = pt;
+			tool._lastPoint = toolPoint || pt;
+			if (mouse.down) {
+				tool._moveCount = -1;
+				tool._downPoint = pt;
+				tool._downCount++;
+			}
+			return true;
+		}
+
+		function emit() {
+			if (responds) {
+				called = tool.emit(type, new ToolEvent(tool, type, event))
+						|| called;
+			}
+		}
+
+		if (mouse.down) {
+			update();
+			emit();
+		} else if (mouse.up) {
+			update(null, maxDistance);
+			emit();
+		} else if (responds) {
+			while (update(minDistance, maxDistance))
+				emit();
+		}
+		return called;
+	}
+
+});
+
+var Http = {
+	request: function(options) {
+		var xhr = new window.XMLHttpRequest();
+		xhr.open((options.method || 'get').toUpperCase(), options.url,
+				Base.pick(options.async, true));
+		if (options.mimeType)
+			xhr.overrideMimeType(options.mimeType);
+		xhr.onload = function() {
+			var status = xhr.status;
+			if (status === 0 || status === 200) {
+				if (options.onLoad) {
+					options.onLoad.call(xhr, xhr.responseText);
+				}
+			} else {
+				xhr.onerror();
+			}
+		};
+		xhr.onerror = function() {
+			var status = xhr.status,
+				message = 'Could not load "' + options.url + '" (Status: '
+						+ status + ')';
+			if (options.onError) {
+				options.onError(message, status);
+			} else {
+				throw new Error(message);
+			}
+		};
+		return xhr.send(null);
+	}
+};
+
+var CanvasProvider = {
+	canvases: [],
+
+	getCanvas: function(width, height) {
+		if (!window)
+			return null;
+		var canvas,
+			clear = true;
+		if (typeof width === 'object') {
+			height = width.height;
+			width = width.width;
+		}
+		if (this.canvases.length) {
+			canvas = this.canvases.pop();
+		} else {
+			canvas = document.createElement('canvas');
+			clear = false;
+		}
+		var ctx = canvas.getContext('2d');
+		if (!ctx) {
+			throw new Error('Canvas ' + canvas +
+					' is unable toprovide a 2D context.');
+		}
+		if (canvas.width === width && canvas.height === height) {
+			if (clear)
+				ctx.clearRect(0, 0, width + 1, height + 1);
+		} else {
+			canvas.width = width;
+			canvas.height = height;
+		}
+		ctx.save();
+		return canvas;
+	},
+
+	getContext: function(width, height) {
+		var canvas = this.getCanvas(width, height);
+		return canvas ? canvas.getContext('2d') : null;
+	},
+
+	release: function(obj) {
+		var canvas = obj && obj.canvas ? obj.canvas : obj;
+		if (canvas && canvas.getContext) {
+			canvas.getContext('2d').restore();
+			this.canvases.push(canvas);
+		}
+	}
+};
+
+var BlendMode = new function() {
+	var min = Math.min,
+		max = Math.max,
+		abs = Math.abs,
+		sr, sg, sb, sa,
+		br, bg, bb, ba,
+		dr, dg, db;
+
+	function getLum(r, g, b) {
+		return 0.2989 * r + 0.587 * g + 0.114 * b;
+	}
+
+	function setLum(r, g, b, l) {
+		var d = l - getLum(r, g, b);
+		dr = r + d;
+		dg = g + d;
+		db = b + d;
+		var l = getLum(dr, dg, db),
+			mn = min(dr, dg, db),
+			mx = max(dr, dg, db);
+		if (mn < 0) {
+			var lmn = l - mn;
+			dr = l + (dr - l) * l / lmn;
+			dg = l + (dg - l) * l / lmn;
+			db = l + (db - l) * l / lmn;
+		}
+		if (mx > 255) {
+			var ln = 255 - l,
+				mxl = mx - l;
+			dr = l + (dr - l) * ln / mxl;
+			dg = l + (dg - l) * ln / mxl;
+			db = l + (db - l) * ln / mxl;
+		}
+	}
+
+	function getSat(r, g, b) {
+		return max(r, g, b) - min(r, g, b);
+	}
+
+	function setSat(r, g, b, s) {
+		var col = [r, g, b],
+			mx = max(r, g, b),
+			mn = min(r, g, b),
+			md;
+		mn = mn === r ? 0 : mn === g ? 1 : 2;
+		mx = mx === r ? 0 : mx === g ? 1 : 2;
+		md = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;
+		if (col[mx] > col[mn]) {
+			col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);
+			col[mx] = s;
+		} else {
+			col[md] = col[mx] = 0;
+		}
+		col[mn] = 0;
+		dr = col[0];
+		dg = col[1];
+		db = col[2];
+	}
+
+	var modes = {
+		multiply: function() {
+			dr = br * sr / 255;
+			dg = bg * sg / 255;
+			db = bb * sb / 255;
+		},
+
+		screen: function() {
+			dr = br + sr - (br * sr / 255);
+			dg = bg + sg - (bg * sg / 255);
+			db = bb + sb - (bb * sb / 255);
+		},
+
+		overlay: function() {
+			dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;
+			dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;
+			db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;
+		},
+
+		'soft-light': function() {
+			var t = sr * br / 255;
+			dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;
+			t = sg * bg / 255;
+			dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;
+			t = sb * bb / 255;
+			db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;
+		},
+
+		'hard-light': function() {
+			dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;
+			dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;
+			db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;
+		},
+
+		'color-dodge': function() {
+			dr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));
+			dg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));
+			db = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));
+		},
+
+		'color-burn': function() {
+			dr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);
+			dg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);
+			db = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);
+		},
+
+		darken: function() {
+			dr = br < sr ? br : sr;
+			dg = bg < sg ? bg : sg;
+			db = bb < sb ? bb : sb;
+		},
+
+		lighten: function() {
+			dr = br > sr ? br : sr;
+			dg = bg > sg ? bg : sg;
+			db = bb > sb ? bb : sb;
+		},
+
+		difference: function() {
+			dr = br - sr;
+			if (dr < 0)
+				dr = -dr;
+			dg = bg - sg;
+			if (dg < 0)
+				dg = -dg;
+			db = bb - sb;
+			if (db < 0)
+				db = -db;
+		},
+
+		exclusion: function() {
+			dr = br + sr * (255 - br - br) / 255;
+			dg = bg + sg * (255 - bg - bg) / 255;
+			db = bb + sb * (255 - bb - bb) / 255;
+		},
+
+		hue: function() {
+			setSat(sr, sg, sb, getSat(br, bg, bb));
+			setLum(dr, dg, db, getLum(br, bg, bb));
+		},
+
+		saturation: function() {
+			setSat(br, bg, bb, getSat(sr, sg, sb));
+			setLum(dr, dg, db, getLum(br, bg, bb));
+		},
+
+		luminosity: function() {
+			setLum(br, bg, bb, getLum(sr, sg, sb));
+		},
+
+		color: function() {
+			setLum(sr, sg, sb, getLum(br, bg, bb));
+		},
+
+		add: function() {
+			dr = min(br + sr, 255);
+			dg = min(bg + sg, 255);
+			db = min(bb + sb, 255);
+		},
+
+		subtract: function() {
+			dr = max(br - sr, 0);
+			dg = max(bg - sg, 0);
+			db = max(bb - sb, 0);
+		},
+
+		average: function() {
+			dr = (br + sr) / 2;
+			dg = (bg + sg) / 2;
+			db = (bb + sb) / 2;
+		},
+
+		negation: function() {
+			dr = 255 - abs(255 - sr - br);
+			dg = 255 - abs(255 - sg - bg);
+			db = 255 - abs(255 - sb - bb);
+		}
+	};
+
+	var nativeModes = this.nativeModes = Base.each([
+		'source-over', 'source-in', 'source-out', 'source-atop',
+		'destination-over', 'destination-in', 'destination-out',
+		'destination-atop', 'lighter', 'darker', 'copy', 'xor'
+	], function(mode) {
+		this[mode] = true;
+	}, {});
+
+	var ctx = CanvasProvider.getContext(1, 1);
+	if (ctx) {
+		Base.each(modes, function(func, mode) {
+			var darken = mode === 'darken',
+				ok = false;
+			ctx.save();
+			try {
+				ctx.fillStyle = darken ? '#300' : '#a00';
+				ctx.fillRect(0, 0, 1, 1);
+				ctx.globalCompositeOperation = mode;
+				if (ctx.globalCompositeOperation === mode) {
+					ctx.fillStyle = darken ? '#a00' : '#300';
+					ctx.fillRect(0, 0, 1, 1);
+					ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken
+							? 170 : 51;
+				}
+			} catch (e) {}
+			ctx.restore();
+			nativeModes[mode] = ok;
+		});
+		CanvasProvider.release(ctx);
+	}
+
+	this.process = function(mode, srcContext, dstContext, alpha, offset) {
+		var srcCanvas = srcContext.canvas,
+			normal = mode === 'normal';
+		if (normal || nativeModes[mode]) {
+			dstContext.save();
+			dstContext.setTransform(1, 0, 0, 1, 0, 0);
+			dstContext.globalAlpha = alpha;
+			if (!normal)
+				dstContext.globalCompositeOperation = mode;
+			dstContext.drawImage(srcCanvas, offset.x, offset.y);
+			dstContext.restore();
+		} else {
+			var process = modes[mode];
+			if (!process)
+				return;
+			var dstData = dstContext.getImageData(offset.x, offset.y,
+					srcCanvas.width, srcCanvas.height),
+				dst = dstData.data,
+				src = srcContext.getImageData(0, 0,
+					srcCanvas.width, srcCanvas.height).data;
+			for (var i = 0, l = dst.length; i < l; i += 4) {
+				sr = src[i];
+				br = dst[i];
+				sg = src[i + 1];
+				bg = dst[i + 1];
+				sb = src[i + 2];
+				bb = dst[i + 2];
+				sa = src[i + 3];
+				ba = dst[i + 3];
+				process();
+				var a1 = sa * alpha / 255,
+					a2 = 1 - a1;
+				dst[i] = a1 * dr + a2 * br;
+				dst[i + 1] = a1 * dg + a2 * bg;
+				dst[i + 2] = a1 * db + a2 * bb;
+				dst[i + 3] = sa * alpha + a2 * ba;
+			}
+			dstContext.putImageData(dstData, offset.x, offset.y);
+		}
+	};
+};
+
+var SvgElement = new function() {
+	var svg = 'http://www.w3.org/2000/svg',
+		xmlns = 'http://www.w3.org/2000/xmlns',
+		xlink = 'http://www.w3.org/1999/xlink',
+		attributeNamespace = {
+			href: xlink,
+			xlink: xmlns,
+			xmlns: xmlns + '/',
+			'xmlns:xlink': xmlns + '/'
+		};
+
+	function create(tag, attributes, formatter) {
+		return set(document.createElementNS(svg, tag), attributes, formatter);
+	}
+
+	function get(node, name) {
+		var namespace = attributeNamespace[name],
+			value = namespace
+				? node.getAttributeNS(namespace, name)
+				: node.getAttribute(name);
+		return value === 'null' ? null : value;
+	}
+
+	function set(node, attributes, formatter) {
+		for (var name in attributes) {
+			var value = attributes[name],
+				namespace = attributeNamespace[name];
+			if (typeof value === 'number' && formatter)
+				value = formatter.number(value);
+			if (namespace) {
+				node.setAttributeNS(namespace, name, value);
+			} else {
+				node.setAttribute(name, value);
+			}
+		}
+		return node;
+	}
+
+	return {
+		svg: svg,
+		xmlns: xmlns,
+		xlink: xlink,
+
+		create: create,
+		get: get,
+		set: set
+	};
+};
+
+var SvgStyles = Base.each({
+	fillColor: ['fill', 'color'],
+	fillRule: ['fill-rule', 'string'],
+	strokeColor: ['stroke', 'color'],
+	strokeWidth: ['stroke-width', 'number'],
+	strokeCap: ['stroke-linecap', 'string'],
+	strokeJoin: ['stroke-linejoin', 'string'],
+	strokeScaling: ['vector-effect', 'lookup', {
+		true: 'none',
+		false: 'non-scaling-stroke'
+	}, function(item, value) {
+		return !value
+				&& (item instanceof PathItem
+					|| item instanceof Shape
+					|| item instanceof TextItem);
+	}],
+	miterLimit: ['stroke-miterlimit', 'number'],
+	dashArray: ['stroke-dasharray', 'array'],
+	dashOffset: ['stroke-dashoffset', 'number'],
+	fontFamily: ['font-family', 'string'],
+	fontWeight: ['font-weight', 'string'],
+	fontSize: ['font-size', 'number'],
+	justification: ['text-anchor', 'lookup', {
+		left: 'start',
+		center: 'middle',
+		right: 'end'
+	}],
+	opacity: ['opacity', 'number'],
+	blendMode: ['mix-blend-mode', 'style']
+}, function(entry, key) {
+	var part = Base.capitalize(key),
+		lookup = entry[2];
+	this[key] = {
+		type: entry[1],
+		property: key,
+		attribute: entry[0],
+		toSVG: lookup,
+		fromSVG: lookup && Base.each(lookup, function(value, name) {
+			this[value] = name;
+		}, {}),
+		exportFilter: entry[3],
+		get: 'get' + part,
+		set: 'set' + part
+	};
+}, {});
+
+new function() {
+	var formatter;
+
+	function getTransform(matrix, coordinates, center) {
+		var attrs = new Base(),
+			trans = matrix.getTranslation();
+		if (coordinates) {
+			matrix = matrix._shiftless();
+			var point = matrix._inverseTransform(trans);
+			attrs[center ? 'cx' : 'x'] = point.x;
+			attrs[center ? 'cy' : 'y'] = point.y;
+			trans = null;
+		}
+		if (!matrix.isIdentity()) {
+			var decomposed = matrix.decompose();
+			if (decomposed) {
+				var parts = [],
+					angle = decomposed.rotation,
+					scale = decomposed.scaling,
+					skew = decomposed.skewing;
+				if (trans && !trans.isZero())
+					parts.push('translate(' + formatter.point(trans) + ')');
+				if (angle)
+					parts.push('rotate(' + formatter.number(angle) + ')');
+				if (!Numerical.isZero(scale.x - 1)
+						|| !Numerical.isZero(scale.y - 1))
+					parts.push('scale(' + formatter.point(scale) +')');
+				if (skew && skew.x)
+					parts.push('skewX(' + formatter.number(skew.x) + ')');
+				if (skew && skew.y)
+					parts.push('skewY(' + formatter.number(skew.y) + ')');
+				attrs.transform = parts.join(' ');
+			} else {
+				attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';
+			}
+		}
+		return attrs;
+	}
+
+	function exportGroup(item, options) {
+		var attrs = getTransform(item._matrix),
+			children = item._children;
+		var node = SvgElement.create('g', attrs, formatter);
+		for (var i = 0, l = children.length; i < l; i++) {
+			var child = children[i];
+			var childNode = exportSVG(child, options);
+			if (childNode) {
+				if (child.isClipMask()) {
+					var clip = SvgElement.create('clipPath');
+					clip.appendChild(childNode);
+					setDefinition(child, clip, 'clip');
+					SvgElement.set(node, {
+						'clip-path': 'url(#' + clip.id + ')'
+					});
+				} else {
+					node.appendChild(childNode);
+				}
+			}
+		}
+		return node;
+	}
+
+	function exportRaster(item, options) {
+		var attrs = getTransform(item._matrix, true),
+			size = item.getSize(),
+			image = item.getImage();
+		attrs.x -= size.width / 2;
+		attrs.y -= size.height / 2;
+		attrs.width = size.width;
+		attrs.height = size.height;
+		attrs.href = options.embedImages === false && image && image.src
+				|| item.toDataURL();
+		return SvgElement.create('image', attrs, formatter);
+	}
+
+	function exportPath(item, options) {
+		var matchShapes = options.matchShapes;
+		if (matchShapes) {
+			var shape = item.toShape(false);
+			if (shape)
+				return exportShape(shape, options);
+		}
+		var segments = item._segments,
+			length = segments.length,
+			type,
+			attrs = getTransform(item._matrix);
+		if (matchShapes && length >= 2 && !item.hasHandles()) {
+			if (length > 2) {
+				type = item._closed ? 'polygon' : 'polyline';
+				var parts = [];
+				for(var i = 0; i < length; i++)
+					parts.push(formatter.point(segments[i]._point));
+				attrs.points = parts.join(' ');
+			} else {
+				type = 'line';
+				var start = segments[0]._point,
+					end = segments[1]._point;
+				attrs.set({
+					x1: start.x,
+					y1: start.y,
+					x2: end.x,
+					y2: end.y
+				});
+			}
+		} else {
+			type = 'path';
+			attrs.d = item.getPathData(null, options.precision);
+		}
+		return SvgElement.create(type, attrs, formatter);
+	}
+
+	function exportShape(item) {
+		var type = item._type,
+			radius = item._radius,
+			attrs = getTransform(item._matrix, true, type !== 'rectangle');
+		if (type === 'rectangle') {
+			type = 'rect';
+			var size = item._size,
+				width = size.width,
+				height = size.height;
+			attrs.x -= width / 2;
+			attrs.y -= height / 2;
+			attrs.width = width;
+			attrs.height = height;
+			if (radius.isZero())
+				radius = null;
+		}
+		if (radius) {
+			if (type === 'circle') {
+				attrs.r = radius;
+			} else {
+				attrs.rx = radius.width;
+				attrs.ry = radius.height;
+			}
+		}
+		return SvgElement.create(type, attrs, formatter);
+	}
+
+	function exportCompoundPath(item, options) {
+		var attrs = getTransform(item._matrix);
+		var data = item.getPathData(null, options.precision);
+		if (data)
+			attrs.d = data;
+		return SvgElement.create('path', attrs, formatter);
+	}
+
+	function exportSymbolItem(item, options) {
+		var attrs = getTransform(item._matrix, true),
+			definition = item._definition,
+			node = getDefinition(definition, 'symbol'),
+			definitionItem = definition._item,
+			bounds = definitionItem.getBounds();
+		if (!node) {
+			node = SvgElement.create('symbol', {
+				viewBox: formatter.rectangle(bounds)
+			});
+			node.appendChild(exportSVG(definitionItem, options));
+			setDefinition(definition, node, 'symbol');
+		}
+		attrs.href = '#' + node.id;
+		attrs.x += bounds.x;
+		attrs.y += bounds.y;
+		attrs.width = bounds.width;
+		attrs.height = bounds.height;
+		attrs.overflow = 'visible';
+		return SvgElement.create('use', attrs, formatter);
+	}
+
+	function exportGradient(color) {
+		var gradientNode = getDefinition(color, 'color');
+		if (!gradientNode) {
+			var gradient = color.getGradient(),
+				radial = gradient._radial,
+				origin = color.getOrigin(),
+				destination = color.getDestination(),
+				attrs;
+			if (radial) {
+				attrs = {
+					cx: origin.x,
+					cy: origin.y,
+					r: origin.getDistance(destination)
+				};
+				var highlight = color.getHighlight();
+				if (highlight) {
+					attrs.fx = highlight.x;
+					attrs.fy = highlight.y;
+				}
+			} else {
+				attrs = {
+					x1: origin.x,
+					y1: origin.y,
+					x2: destination.x,
+					y2: destination.y
+				};
+			}
+			attrs.gradientUnits = 'userSpaceOnUse';
+			gradientNode = SvgElement.create((radial ? 'radial' : 'linear')
+					+ 'Gradient', attrs, formatter);
+			var stops = gradient._stops;
+			for (var i = 0, l = stops.length; i < l; i++) {
+				var stop = stops[i],
+					stopColor = stop._color,
+					alpha = stopColor.getAlpha();
+				attrs = {
+					offset: stop._offset || i / (l - 1)
+				};
+				if (stopColor)
+					attrs['stop-color'] = stopColor.toCSS(true);
+				if (alpha < 1)
+					attrs['stop-opacity'] = alpha;
+				gradientNode.appendChild(
+						SvgElement.create('stop', attrs, formatter));
+			}
+			setDefinition(color, gradientNode, 'color');
+		}
+		return 'url(#' + gradientNode.id + ')';
+	}
+
+	function exportText(item) {
+		var node = SvgElement.create('text', getTransform(item._matrix, true),
+				formatter);
+		node.textContent = item._content;
+		return node;
+	}
+
+	var exporters = {
+		Group: exportGroup,
+		Layer: exportGroup,
+		Raster: exportRaster,
+		Path: exportPath,
+		Shape: exportShape,
+		CompoundPath: exportCompoundPath,
+		SymbolItem: exportSymbolItem,
+		PointText: exportText
+	};
+
+	function applyStyle(item, node, isRoot) {
+		var attrs = {},
+			parent = !isRoot && item.getParent(),
+			style = [];
+
+		if (item._name != null)
+			attrs.id = item._name;
+
+		Base.each(SvgStyles, function(entry) {
+			var get = entry.get,
+				type = entry.type,
+				value = item[get]();
+			if (entry.exportFilter
+					? entry.exportFilter(item, value)
+					: !parent || !Base.equals(parent[get](), value)) {
+				if (type === 'color' && value != null) {
+					var alpha = value.getAlpha();
+					if (alpha < 1)
+						attrs[entry.attribute + '-opacity'] = alpha;
+				}
+				if (type === 'style') {
+					style.push(entry.attribute + ': ' + value);
+				} else {
+					attrs[entry.attribute] = value == null ? 'none'
+							: type === 'color' ? value.gradient
+								? exportGradient(value, item)
+								: value.toCSS(true)
+							: type === 'array' ? value.join(',')
+							: type === 'lookup' ? entry.toSVG[value]
+							: value;
+				}
+			}
+		});
+
+		if (style.length)
+			attrs.style = style.join(';');
+
+		if (attrs.opacity === 1)
+			delete attrs.opacity;
+
+		if (!item._visible)
+			attrs.visibility = 'hidden';
+
+		return SvgElement.set(node, attrs, formatter);
+	}
+
+	var definitions;
+	function getDefinition(item, type) {
+		if (!definitions)
+			definitions = { ids: {}, svgs: {} };
+		var id = item._id || item.__id || (item.__id = UID.get('svg'));
+		return item && definitions.svgs[type + '-' + id];
+	}
+
+	function setDefinition(item, node, type) {
+		if (!definitions)
+			getDefinition();
+		var typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;
+		node.id = type + '-' + typeId;
+		definitions.svgs[type + '-' + (item._id || item.__id)] = node;
+	}
+
+	function exportDefinitions(node, options) {
+		var svg = node,
+			defs = null;
+		if (definitions) {
+			svg = node.nodeName.toLowerCase() === 'svg' && node;
+			for (var i in definitions.svgs) {
+				if (!defs) {
+					if (!svg) {
+						svg = SvgElement.create('svg');
+						svg.appendChild(node);
+					}
+					defs = svg.insertBefore(SvgElement.create('defs'),
+							svg.firstChild);
+				}
+				defs.appendChild(definitions.svgs[i]);
+			}
+			definitions = null;
+		}
+		return options.asString
+				? new window.XMLSerializer().serializeToString(svg)
+				: svg;
+	}
+
+	function exportSVG(item, options, isRoot) {
+		var exporter = exporters[item._class],
+			node = exporter && exporter(item, options);
+		if (node) {
+			var onExport = options.onExport;
+			if (onExport)
+				node = onExport(item, node, options) || node;
+			var data = JSON.stringify(item._data);
+			if (data && data !== '{}' && data !== 'null')
+				node.setAttribute('data-paper-data', data);
+		}
+		return node && applyStyle(item, node, isRoot);
+	}
+
+	function setOptions(options) {
+		if (!options)
+			options = {};
+		formatter = new Formatter(options.precision);
+		return options;
+	}
+
+	Item.inject({
+		exportSVG: function(options) {
+			options = setOptions(options);
+			return exportDefinitions(exportSVG(this, options, true), options);
+		}
+	});
+
+	Project.inject({
+		exportSVG: function(options) {
+			options = setOptions(options);
+			var children = this._children,
+				view = this.getView(),
+				bounds = Base.pick(options.bounds, 'view'),
+				mx = options.matrix || bounds === 'view' && view._matrix,
+				matrix = mx && Matrix.read([mx]),
+				rect = bounds === 'view'
+					? new Rectangle([0, 0], view.getViewSize())
+					: bounds === 'content'
+						? Item._getBounds(children, matrix, { stroke: true })
+						: Rectangle.read([bounds], 0, { readNull: true }),
+				attrs = {
+					version: '1.1',
+					xmlns: SvgElement.svg,
+					'xmlns:xlink': SvgElement.xlink,
+				};
+			if (rect) {
+				attrs.width = rect.width;
+				attrs.height = rect.height;
+				if (rect.x || rect.y)
+					attrs.viewBox = formatter.rectangle(rect);
+			}
+			var node = SvgElement.create('svg', attrs, formatter),
+				parent = node;
+			if (matrix && !matrix.isIdentity()) {
+				parent = node.appendChild(SvgElement.create('g',
+						getTransform(matrix), formatter));
+			}
+			for (var i = 0, l = children.length; i < l; i++) {
+				parent.appendChild(exportSVG(children[i], options, true));
+			}
+			return exportDefinitions(node, options);
+		}
+	});
+};
+
+new function() {
+
+	var definitions = {},
+		rootSize;
+
+	function getValue(node, name, isString, allowNull, allowPercent) {
+		var value = SvgElement.get(node, name),
+			res = value == null
+				? allowNull
+					? null
+					: isString ? '' : 0
+				: isString
+					? value
+					: parseFloat(value);
+		return /%\s*$/.test(value)
+			? (res / 100) * (allowPercent ? 1
+				: rootSize[/x|^width/.test(name) ? 'width' : 'height'])
+			: res;
+	}
+
+	function getPoint(node, x, y, allowNull, allowPercent) {
+		x = getValue(node, x || 'x', false, allowNull, allowPercent);
+		y = getValue(node, y || 'y', false, allowNull, allowPercent);
+		return allowNull && (x == null || y == null) ? null
+				: new Point(x, y);
+	}
+
+	function getSize(node, w, h, allowNull, allowPercent) {
+		w = getValue(node, w || 'width', false, allowNull, allowPercent);
+		h = getValue(node, h || 'height', false, allowNull, allowPercent);
+		return allowNull && (w == null || h == null) ? null
+				: new Size(w, h);
+	}
+
+	function convertValue(value, type, lookup) {
+		return value === 'none' ? null
+				: type === 'number' ? parseFloat(value)
+				: type === 'array' ?
+					value ? value.split(/[\s,]+/g).map(parseFloat) : []
+				: type === 'color' ? getDefinition(value) || value
+				: type === 'lookup' ? lookup[value]
+				: value;
+	}
+
+	function importGroup(node, type, options, isRoot) {
+		var nodes = node.childNodes,
+			isClip = type === 'clippath',
+			isDefs = type === 'defs',
+			item = new Group(),
+			project = item._project,
+			currentStyle = project._currentStyle,
+			children = [];
+		if (!isClip && !isDefs) {
+			item = applyAttributes(item, node, isRoot);
+			project._currentStyle = item._style.clone();
+		}
+		if (isRoot) {
+			var defs = node.querySelectorAll('defs');
+			for (var i = 0, l = defs.length; i < l; i++) {
+				importNode(defs[i], options, false);
+			}
+		}
+		for (var i = 0, l = nodes.length; i < l; i++) {
+			var childNode = nodes[i],
+				child;
+			if (childNode.nodeType === 1
+					&& !/^defs$/i.test(childNode.nodeName)
+					&& (child = importNode(childNode, options, false))
+					&& !(child instanceof SymbolDefinition))
+				children.push(child);
+		}
+		item.addChildren(children);
+		if (isClip)
+			item = applyAttributes(item.reduce(), node, isRoot);
+		project._currentStyle = currentStyle;
+		if (isClip || isDefs) {
+			item.remove();
+			item = null;
+		}
+		return item;
+	}
+
+	function importPoly(node, type) {
+		var coords = node.getAttribute('points').match(
+					/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),
+			points = [];
+		for (var i = 0, l = coords.length; i < l; i += 2)
+			points.push(new Point(
+					parseFloat(coords[i]),
+					parseFloat(coords[i + 1])));
+		var path = new Path(points);
+		if (type === 'polygon')
+			path.closePath();
+		return path;
+	}
+
+	function importPath(node) {
+		return PathItem.create(node.getAttribute('d'));
+	}
+
+	function importGradient(node, type) {
+		var id = (getValue(node, 'href', true) || '').substring(1),
+			radial = type === 'radialgradient',
+			gradient;
+		if (id) {
+			gradient = definitions[id].getGradient();
+			if (gradient._radial ^ radial) {
+				gradient = gradient.clone();
+				gradient._radial = radial;
+			}
+		} else {
+			var nodes = node.childNodes,
+				stops = [];
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				var child = nodes[i];
+				if (child.nodeType === 1)
+					stops.push(applyAttributes(new GradientStop(), child));
+			}
+			gradient = new Gradient(stops, radial);
+		}
+		var origin, destination, highlight,
+			scaleToBounds = getValue(node, 'gradientUnits', true) !==
+				'userSpaceOnUse';
+		if (radial) {
+			origin = getPoint(node, 'cx', 'cy', false, scaleToBounds);
+			destination = origin.add(
+					getValue(node, 'r', false, false, scaleToBounds), 0);
+			highlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);
+		} else {
+			origin = getPoint(node, 'x1', 'y1', false, scaleToBounds);
+			destination = getPoint(node, 'x2', 'y2', false, scaleToBounds);
+		}
+		var color = applyAttributes(
+				new Color(gradient, origin, destination, highlight), node);
+		color._scaleToBounds = scaleToBounds;
+		return null;
+	}
+
+	var importers = {
+		'#document': function (node, type, options, isRoot) {
+			var nodes = node.childNodes;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				var child = nodes[i];
+				if (child.nodeType === 1)
+					return importNode(child, options, isRoot);
+			}
+		},
+		g: importGroup,
+		svg: importGroup,
+		clippath: importGroup,
+		polygon: importPoly,
+		polyline: importPoly,
+		path: importPath,
+		lineargradient: importGradient,
+		radialgradient: importGradient,
+
+		image: function (node) {
+			var raster = new Raster(getValue(node, 'href', true));
+			raster.on('load', function() {
+				var size = getSize(node);
+				this.setSize(size);
+				var center = this._matrix._transformPoint(
+						getPoint(node).add(size.divide(2)));
+				this.translate(center);
+			});
+			return raster;
+		},
+
+		symbol: function(node, type, options, isRoot) {
+			return new SymbolDefinition(
+					importGroup(node, type, options, isRoot), true);
+		},
+
+		defs: importGroup,
+
+		use: function(node) {
+			var id = (getValue(node, 'href', true) || '').substring(1),
+				definition = definitions[id],
+				point = getPoint(node);
+			return definition
+					? definition instanceof SymbolDefinition
+						? definition.place(point)
+						: definition.clone().translate(point)
+					: null;
+		},
+
+		circle: function(node) {
+			return new Shape.Circle(
+					getPoint(node, 'cx', 'cy'),
+					getValue(node, 'r'));
+		},
+
+		ellipse: function(node) {
+			return new Shape.Ellipse({
+				center: getPoint(node, 'cx', 'cy'),
+				radius: getSize(node, 'rx', 'ry')
+			});
+		},
+
+		rect: function(node) {
+			return new Shape.Rectangle(new Rectangle(
+						getPoint(node),
+						getSize(node)
+					), getSize(node, 'rx', 'ry'));
+			},
+
+		line: function(node) {
+			return new Path.Line(
+					getPoint(node, 'x1', 'y1'),
+					getPoint(node, 'x2', 'y2'));
+		},
+
+		text: function(node) {
+			var text = new PointText(getPoint(node).add(
+					getPoint(node, 'dx', 'dy')));
+			text.setContent(node.textContent.trim() || '');
+			return text;
+		}
+	};
+
+	function applyTransform(item, value, name, node) {
+		if (item.transform) {
+			var transforms = (node.getAttribute(name) || '').split(/\)\s*/g),
+				matrix = new Matrix();
+			for (var i = 0, l = transforms.length; i < l; i++) {
+				var transform = transforms[i];
+				if (!transform)
+					break;
+				var parts = transform.split(/\(\s*/),
+					command = parts[0],
+					v = parts[1].split(/[\s,]+/g);
+				for (var j = 0, m = v.length; j < m; j++)
+					v[j] = parseFloat(v[j]);
+				switch (command) {
+				case 'matrix':
+					matrix.append(
+							new Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));
+					break;
+				case 'rotate':
+					matrix.rotate(v[0], v[1], v[2]);
+					break;
+				case 'translate':
+					matrix.translate(v[0], v[1]);
+					break;
+				case 'scale':
+					matrix.scale(v);
+					break;
+				case 'skewX':
+					matrix.skew(v[0], 0);
+					break;
+				case 'skewY':
+					matrix.skew(0, v[0]);
+					break;
+				}
+			}
+			item.transform(matrix);
+		}
+	}
+
+	function applyOpacity(item, value, name) {
+		var key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',
+			color = item[key] && item[key]();
+		if (color)
+			color.setAlpha(parseFloat(value));
+	}
+
+	var attributes = Base.set(Base.each(SvgStyles, function(entry) {
+		this[entry.attribute] = function(item, value) {
+			if (item[entry.set]) {
+				item[entry.set](convertValue(value, entry.type, entry.fromSVG));
+				if (entry.type === 'color') {
+					var color = item[entry.get]();
+					if (color) {
+						if (color._scaleToBounds) {
+							var bounds = item.getBounds();
+							color.transform(new Matrix()
+								.translate(bounds.getPoint())
+								.scale(bounds.getSize()));
+						}
+						if (item instanceof Shape) {
+							color.transform(new Matrix().translate(
+								item.getPosition(true).negate()));
+						}
+					}
+				}
+			}
+		};
+	}, {}), {
+		id: function(item, value) {
+			definitions[value] = item;
+			if (item.setName)
+				item.setName(value);
+		},
+
+		'clip-path': function(item, value) {
+			var clip = getDefinition(value);
+			if (clip) {
+				clip = clip.clone();
+				clip.setClipMask(true);
+				if (item instanceof Group) {
+					item.insertChild(0, clip);
+				} else {
+					return new Group(clip, item);
+				}
+			}
+		},
+
+		gradientTransform: applyTransform,
+		transform: applyTransform,
+
+		'fill-opacity': applyOpacity,
+		'stroke-opacity': applyOpacity,
+
+		visibility: function(item, value) {
+			if (item.setVisible)
+				item.setVisible(value === 'visible');
+		},
+
+		display: function(item, value) {
+			if (item.setVisible)
+				item.setVisible(value !== null);
+		},
+
+		'stop-color': function(item, value) {
+			if (item.setColor)
+				item.setColor(value);
+		},
+
+		'stop-opacity': function(item, value) {
+			if (item._color)
+				item._color.setAlpha(parseFloat(value));
+		},
+
+		offset: function(item, value) {
+			if (item.setOffset) {
+				var percent = value.match(/(.*)%$/);
+				item.setOffset(percent ? percent[1] / 100 : parseFloat(value));
+			}
+		},
+
+		viewBox: function(item, value, name, node, styles) {
+			var rect = new Rectangle(convertValue(value, 'array')),
+				size = getSize(node, null, null, true),
+				group,
+				matrix;
+			if (item instanceof Group) {
+				var scale = size ? size.divide(rect.getSize()) : 1,
+				matrix = new Matrix().scale(scale)
+						.translate(rect.getPoint().negate());
+				group = item;
+			} else if (item instanceof SymbolDefinition) {
+				if (size)
+					rect.setSize(size);
+				group = item._item;
+			}
+			if (group)  {
+				if (getAttribute(node, 'overflow', styles) !== 'visible') {
+					var clip = new Shape.Rectangle(rect);
+					clip.setClipMask(true);
+					group.addChild(clip);
+				}
+				if (matrix)
+					group.transform(matrix);
+			}
+		}
+	});
+
+	function getAttribute(node, name, styles) {
+		var attr = node.attributes[name],
+			value = attr && attr.value;
+		if (!value) {
+			var style = Base.camelize(name);
+			value = node.style[style];
+			if (!value && styles.node[style] !== styles.parent[style])
+				value = styles.node[style];
+		}
+		return !value ? undefined
+				: value === 'none' ? null
+				: value;
+	}
+
+	function applyAttributes(item, node, isRoot) {
+		var parent = node.parentNode,
+			styles = {
+				node: DomElement.getStyles(node) || {},
+				parent: !isRoot && !/^defs$/i.test(parent.tagName)
+						&& DomElement.getStyles(parent) || {}
+			};
+		Base.each(attributes, function(apply, name) {
+			var value = getAttribute(node, name, styles);
+			item = value !== undefined && apply(item, value, name, node, styles)
+					|| item;
+		});
+		return item;
+	}
+
+	function getDefinition(value) {
+		var match = value && value.match(/\((?:["'#]*)([^"')]+)/),
+			res = match && definitions[match[1]
+				.replace(window.location.href.split('#')[0] + '#', '')];
+		if (res && res._scaleToBounds) {
+			res = res.clone();
+			res._scaleToBounds = true;
+		}
+		return res;
+	}
+
+	function importNode(node, options, isRoot) {
+		var type = node.nodeName.toLowerCase(),
+			isElement = type !== '#document',
+			body = document.body,
+			container,
+			parent,
+			next;
+		if (isRoot && isElement) {
+			rootSize = getSize(node, null, null, true)
+					|| paper.getView().getSize();
+			container = SvgElement.create('svg', {
+				style: 'stroke-width: 1px; stroke-miterlimit: 10'
+			});
+			parent = node.parentNode;
+			next = node.nextSibling;
+			container.appendChild(node);
+			body.appendChild(container);
+		}
+		var settings = paper.settings,
+			applyMatrix = settings.applyMatrix,
+			insertItems = settings.insertItems;
+		settings.applyMatrix = false;
+		settings.insertItems = false;
+		var importer = importers[type],
+			item = importer && importer(node, type, options, isRoot) || null;
+		settings.insertItems = insertItems;
+		settings.applyMatrix = applyMatrix;
+		if (item) {
+			if (isElement && !(item instanceof Group))
+				item = applyAttributes(item, node, isRoot);
+			var onImport = options.onImport,
+				data = isElement && node.getAttribute('data-paper-data');
+			if (onImport)
+				item = onImport(node, item, options) || item;
+			if (options.expandShapes && item instanceof Shape) {
+				item.remove();
+				item = item.toPath();
+			}
+			if (data)
+				item._data = JSON.parse(data);
+		}
+		if (container) {
+			body.removeChild(container);
+			if (parent) {
+				if (next) {
+					parent.insertBefore(node, next);
+				} else {
+					parent.appendChild(node);
+				}
+			}
+		}
+		if (isRoot) {
+			definitions = {};
+			if (item && Base.pick(options.applyMatrix, applyMatrix))
+				item.matrix.apply(true, true);
+		}
+		return item;
+	}
+
+	function importSVG(source, options, owner) {
+		if (!source)
+			return null;
+		options = typeof options === 'function' ? { onLoad: options }
+				: options || {};
+		var scope = paper,
+			item = null;
+
+		function onLoad(svg) {
+			try {
+				var node = typeof svg === 'object' ? svg : new window.DOMParser()
+						.parseFromString(svg, 'image/svg+xml');
+				if (!node.nodeName) {
+					node = null;
+					throw new Error('Unsupported SVG source: ' + source);
+				}
+				paper = scope;
+				item = importNode(node, options, true);
+				if (!options || options.insert !== false) {
+					owner._insertItem(undefined, item);
+				}
+				var onLoad = options.onLoad;
+				if (onLoad)
+					onLoad(item, svg);
+			} catch (e) {
+				onError(e);
+			}
+		}
+
+		function onError(message, status) {
+			var onError = options.onError;
+			if (onError) {
+				onError(message, status);
+			} else {
+				throw new Error(message);
+			}
+		}
+
+		if (typeof source === 'string' && !/^.*</.test(source)) {
+			var node = document.getElementById(source);
+			if (node) {
+				onLoad(node);
+			} else {
+				Http.request({
+					url: source,
+					async: true,
+					onLoad: onLoad,
+					onError: onError
+				});
+			}
+		} else if (typeof File !== 'undefined' && source instanceof File) {
+			var reader = new FileReader();
+			reader.onload = function() {
+				onLoad(reader.result);
+			};
+			reader.onerror = function() {
+				onError(reader.error);
+			};
+			return reader.readAsText(source);
+		} else {
+			onLoad(source);
+		}
+
+		return item;
+	}
+
+	Item.inject({
+		importSVG: function(node, options) {
+			return importSVG(node, options, this);
+		}
+	});
+
+	Project.inject({
+		importSVG: function(node, options) {
+			this.activate();
+			return importSVG(node, options, this);
+		}
+	});
+};
+
+paper = new (PaperScope.inject(Base.exports, {
+	enumerable: true,
+	Base: Base,
+	Numerical: Numerical,
+	Key: Key,
+	DomEvent: DomEvent,
+	DomElement: DomElement,
+	document: document,
+	window: window,
+	Symbol: SymbolDefinition,
+	PlacedSymbol: SymbolItem
+}))();
+
+if (paper.agent.node)
+	require('./node/extend')(paper);
+
+if (typeof define === 'function' && define.amd) {
+	define('paper', paper);
+} else if (typeof module === 'object' && module) {
+	module.exports = paper;
+}
+
+return paper;
+}.call(this, typeof self === 'object' ? self : null);
diff --git a/dist/paper-core.min.js b/dist/paper-core.min.js
new file mode 100644
index 00000000..548fbcce
--- /dev/null
+++ b/dist/paper-core.min.js
@@ -0,0 +1,38 @@
+/*!
+ * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
+ * http://scratchdisk.com/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ *
+ * Date: Sat Jul 9 20:56:58 2016 +0200
+ *
+ ***
+ *
+ * Straps.js - Class inheritance library with support for bean-style accessors
+ *
+ * Copyright (c) 2006 - 2016 Juerg Lehni
+ * http://scratchdisk.com/
+ *
+ * Distributed under the MIT license.
+ *
+ ***
+ *
+ * Acorn.js
+ * http://marijnhaverbeke.nl/acorn/
+ *
+ * Acorn is a tiny, fast JavaScript parser written in JavaScript,
+ * created by Marijn Haverbeke and released under an MIT license.
+ *
+ */
+var paper=function(t,e){var i=t?t.window:require("./node/window"),n=i&&i.document;t=t||i;var r=new function(){function t(t,e,i,n,a){function o(s,o){o=o||(o=u(e,s))&&(o.get?o:o.value),"string"==typeof o&&"#"===o[0]&&(o=t[o.substring(1)]||o);var l,d="function"==typeof o,f=o,_=a||d&&!o.base?o&&o.get?s in t:t[s]:null;a&&_||(d&&_&&(o.base=_),d&&n!==!1&&(l=s.match(/^([gs]et|is)(([A-Z])(.*))$/))&&(h[l[3].toLowerCase()+l[4]]=l[2]),f&&!d&&f.get&&"function"==typeof f.get&&r.isPlainObject(f)||(f={value:f,writable:!0}),(u(t,s)||{configurable:!0}).configurable&&(f.configurable=!0,f.enumerable=i),c(t,s,f))}var h={};if(e){for(var l in e)e.hasOwnProperty(l)&&!s.test(l)&&o(l);for(var l in h){var d=h[l],f=t["set"+d],_=t["get"+d]||f&&t["is"+d];!_||n!==!0&&0!==_.length||o(l,{get:_,set:f})}}return t}function i(t,e,i){return t&&("length"in t&&!t.getLength&&"number"==typeof t.length?a:o).call(t,e,i=i||t),i}function n(t,e,i){for(var n=i,r=e.length;n<r;n++){var s=e[n];for(var a in s)s.hasOwnProperty(a)&&(t[a]=s[a])}return t}var s=/^(statics|enumerable|beans|preserve)$/,a=[].forEach||function(t,e){for(var i=0,n=this.length;i<n;i++)t.call(e,this[i],i,this)},o=function(t,e){for(var i in this)this.hasOwnProperty(i)&&t.call(e,this[i],i,this)},h=Object.create||function(t){return{__proto__:t}},u=Object.getOwnPropertyDescriptor||function(t,e){var i=t.__lookupGetter__&&t.__lookupGetter__(e);return i?{get:i,set:t.__lookupSetter__(e),enumerable:!0,configurable:!0}:t.hasOwnProperty(e)?{value:t[e],enumerable:!0,configurable:!0,writable:!0}:null},l=Object.defineProperty||function(t,e,i){return(i.get||i.set)&&t.__defineGetter__?(i.get&&t.__defineGetter__(e,i.get),i.set&&t.__defineSetter__(e,i.set)):t[e]=i.value,t},c=function(t,e,i){return delete t[e],l(t,e,i)};return t(function(){n(this,arguments,0)},{inject:function(e){if(e){var i=e.statics===!0?e:e.statics,n=e.beans,r=e.preserve;i!==e&&t(this.prototype,e,e.enumerable,n,r),t(this,i,!0,n,r)}for(var s=1,a=arguments.length;s<a;s++)this.inject(arguments[s]);return this},extend:function(){for(var e,i,n,r=this,s=0,a=arguments.length;s<a&&(!e||!i);s++)n=arguments[s],e=e||n.initialize,i=i||n.prototype;return e=e||function(){r.apply(this,arguments)},i=e.prototype=i||h(this.prototype),c(i,"constructor",{value:e,writable:!0,configurable:!0}),t(e,this,!0),arguments.length&&this.inject.apply(e,arguments),e.base=r,e}},!0).inject({inject:function(){for(var e=0,i=arguments.length;e<i;e++){var n=arguments[e];n&&t(this,n,n.enumerable,n.beans,n.preserve)}return this},extend:function(){var t=h(this);return t.inject.apply(t,arguments)},each:function(t,e){return i(this,t,e)},set:function(){return n(this,arguments,0)},clone:function(){return new this.constructor(this)},statics:{each:i,create:h,define:c,describe:u,set:function(t){return n(t,arguments,1)},clone:function(t){return n(new t.constructor,arguments,0)},isPlainObject:function(t){var e=null!=t&&t.constructor;return e&&(e===Object||e===r||"Object"===e.name)},pick:function(t,i){return t!==e?t:i}}})};"undefined"!=typeof module&&(module.exports=r),r.inject({toString:function(){return null!=this._id?(this._class||"Object")+(this._name?" '"+this._name+"'":" @"+this._id):"{ "+r.each(this,function(t,e){if(!/^_/.test(e)){var i=typeof t;this.push(e+": "+("number"===i?h.instance.number(t):"string"===i?"'"+t+"'":t))}},[]).join(", ")+" }"},getClassName:function(){return this._class||""},importJSON:function(t){return r.importJSON(t,this)},exportJSON:function(t){return r.exportJSON(this,t)},toJSON:function(){return r.serialize(this)},_set:function(t){if(t&&r.isPlainObject(t))return r.filter(this,t)},statics:{exports:{enumerable:!0},extend:function nt(){var t=nt.base.apply(this,arguments),e=t.prototype._class;return e&&!r.exports[e]&&(r.exports[e]=t),t},equals:function(t,e){if(t===e)return!0;if(t&&t.equals)return t.equals(e);if(e&&e.equals)return e.equals(t);if(t&&e&&"object"==typeof t&&"object"==typeof e){if(Array.isArray(t)&&Array.isArray(e)){var i=t.length;if(i!==e.length)return!1;for(;i--;)if(!r.equals(t[i],e[i]))return!1}else{var n=Object.keys(t),i=n.length;if(i!==Object.keys(e).length)return!1;for(;i--;){var s=n[i];if(!e.hasOwnProperty(s)||!r.equals(t[s],e[s]))return!1}}return!0}return!1},read:function(t,i,n,s){if(this===r){var a=this.peek(t,i);return t.__index++,a}var o=this.prototype,h=o._readIndex,u=i||h&&t.__index||0;s||(s=t.length-u);var l=t[u];return l instanceof this||n&&n.readNull&&null==l&&s<=1?(h&&(t.__index=u+1),l&&n&&n.clone?l.clone():l):(l=r.create(this.prototype),h&&(l.__read=!0),l=l.initialize.apply(l,u>0||s<t.length?Array.prototype.slice.call(t,u,u+s):t)||l,h&&(t.__index=u+l.__read,l.__read=e),l)},peek:function(t,e){return t[t.__index=e||t.__index||0]},remain:function(t){return t.length-(t.__index||0)},readAll:function(t,e,i){for(var n,r=[],s=e||0,a=t.length;s<a;s++)r.push(Array.isArray(n=t[s])?this.read(n,0,i):this.read(t,s,i,1));return r},readNamed:function(t,i,n,s,a){var o=this.getNamed(t,i),h=o!==e;if(h){var u=t._filtered;u||(u=t._filtered=r.create(t[0]),u._filtering=t[0]),u[i]=e}return this.read(h?[o]:t,n,s,a)},getNamed:function(t,i){var n=t[0];if(t._hasObject===e&&(t._hasObject=1===t.length&&r.isPlainObject(n)),t._hasObject)return i?n[i]:t._filtered||n},hasNamed:function(t,e){return!!this.getNamed(t,e)},filter:function(t,i,n){for(var r=Object.keys(i._filtering||i),s=0,a=r.length;s<a;s++){var o=r[s];if(!n||!n[o]){var h=i[o];h!==e&&(t[o]=h)}}return t},isPlainValue:function(t,e){return this.isPlainObject(t)||Array.isArray(t)||e&&"string"==typeof t},serialize:function(t,e,i,n){e=e||{};var s,a=!n;if(a&&(e.formatter=new h(e.precision),n={length:0,definitions:{},references:{},add:function(t,e){var i="#"+t._id,n=this.references[i];if(!n){this.length++;var r=e.call(t),s=t._class;s&&r[0]!==s&&r.unshift(s),this.definitions[i]=r,n=this.references[i]=[i]}return n}}),t&&t._serialize){s=t._serialize(e,n);var o=t._class;!o||t._compactSerialize||!a&&i||s[0]===o||s.unshift(o)}else if(Array.isArray(t)){s=[];for(var u=0,l=t.length;u<l;u++)s[u]=r.serialize(t[u],e,i,n)}else if(r.isPlainObject(t)){s={};for(var c=Object.keys(t),u=0,l=c.length;u<l;u++){var d=c[u];s[d]=r.serialize(t[d],e,i,n)}}else s="number"==typeof t?e.formatter.number(t,e.precision):t;return a&&n.length>0?[["dictionary",n.definitions],s]:s},deserialize:function(t,e,i,n,s){var a=t,o=!i,h=o&&t&&t.length&&"dictionary"===t[0][0];if(i=i||{},Array.isArray(t)){var u=t[0],l="dictionary"===u;if(1==t.length&&/^#/.test(u))return i.dictionary[u];u=r.exports[u],a=[];for(var c=u?1:0,d=t.length;c<d;c++)a.push(r.deserialize(t[c],e,i,l,h));if(u){var f=a;e?a=e(u,f,o||s):(a=r.create(u.prototype),u.apply(a,f))}}else if(r.isPlainObject(t)){a={},n&&(i.dictionary=a);for(var _ in t)a[_]=r.deserialize(t[_],e,i)}return h?a[1]:a},exportJSON:function(t,e){var i=r.serialize(t,e);return e&&e.asString===!1?i:JSON.stringify(i)},importJSON:function(t,e){return r.deserialize("string"==typeof t?JSON.parse(t):t,function(t,i,n){var s=n&&e&&e.constructor===t,a=s?e:r.create(t.prototype);if(1===i.length&&a instanceof w&&(s||!(a instanceof b))){var o=i[0];r.isPlainObject(o)&&(o.insert=!1)}return(s?a._set:t).apply(a,i),s&&(e=null),a})},splice:function(t,i,n,r){var s=i&&i.length,a=n===e;n=a?t.length:n,n>t.length&&(n=t.length);for(var o=0;o<s;o++)i[o]._index=n+o;if(a)return t.push.apply(t,i),[];var h=[n,r];i&&h.push.apply(h,i);for(var u=t.splice.apply(t,h),o=0,l=u.length;o<l;o++)u[o]._index=e;for(var o=n+s,l=t.length;o<l;o++)t[o]._index=o;return u},capitalize:function(t){return t.replace(/\b[a-z]/g,function(t){return t.toUpperCase()})},camelize:function(t){return t.replace(/-(.)/g,function(t,e){return e.toUpperCase()})},hyphenate:function(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}}});var s={on:function(t,e){if("string"!=typeof t)r.each(t,function(t,e){this.on(e,t)},this);else{var i=this._eventTypes,n=i&&i[t],s=this._callbacks=this._callbacks||{};s=s[t]=s[t]||[],s.indexOf(e)===-1&&(s.push(e),n&&n.install&&1===s.length&&n.install.call(this,t))}return this},off:function(t,e){if("string"!=typeof t)return void r.each(t,function(t,e){this.off(e,t)},this);var i,n=this._eventTypes,s=n&&n[t],a=this._callbacks&&this._callbacks[t];return a&&(!e||(i=a.indexOf(e))!==-1&&1===a.length?(s&&s.uninstall&&s.uninstall.call(this,t),delete this._callbacks[t]):i!==-1&&a.splice(i,1)),this},once:function(t,e){return this.on(t,function(){e.apply(this,arguments),this.off(t,e)})},emit:function(t,e){var i=this._callbacks&&this._callbacks[t];if(!i)return!1;var n=[].slice.call(arguments,1),r=e&&e.target&&!e.currentTarget;i=i.slice(),r&&(e.currentTarget=this);for(var s=0,a=i.length;s<a;s++)if(i[s].apply(this,n)===!1){e&&e.stop&&e.stop();break}return r&&delete e.currentTarget,!0},responds:function(t){return!(!this._callbacks||!this._callbacks[t])},attach:"#on",detach:"#off",fire:"#emit",_installEvents:function(t){var e=this._eventTypes,i=this._callbacks,n=t?"install":"uninstall";if(e)for(var r in i)if(i[r].length>0){var s=e[r],a=s&&s[n];a&&a.call(this,r)}},statics:{inject:function rt(t){var e=t._events;if(e){var i={};r.each(e,function(e,n){var s="string"==typeof e,a=s?e:n,o=r.capitalize(a),h=a.substring(2).toLowerCase();i[h]=s?{}:e,a="_"+a,t["get"+o]=function(){return this[a]},t["set"+o]=function(t){var e=this[a];e&&this.off(h,e),t&&this.on(h,t),this[a]=t}}),t._eventTypes=i}return rt.base.apply(this,arguments)}}},a=r.extend({_class:"PaperScope",initialize:function st(){paper=this,this.settings=new r({applyMatrix:!0,insertItems:!0,handleSize:4,hitTolerance:0}),this.project=null,this.projects=[],this.tools=[],this.palettes=[],this._id=st._id++,st._scopes[this._id]=this;var e=st.prototype;if(!this.support){var i=Q.getContext(1,1)||{};e.support={nativeDash:"setLineDash"in i||"mozDash"in i,nativeBlendModes:tt.nativeModes},Q.release(i)}if(!this.agent){var n=t.navigator.userAgent.toLowerCase(),s=(/(darwin|win|mac|linux|freebsd|sunos)/.exec(n)||[])[0],a="darwin"===s?"mac":s,o=e.agent=e.browser={platform:a};a&&(o[a]=!0),n.replace(/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,function(t,e,i,n,r){if(!o.chrome){var s="opera"===e?n:/^(node|trident)$/.test(e)?r:i;o.version=s,o.versionNumber=parseFloat(s),e="trident"===e?"msie":e,o.name=e,o[e]=!0}}),o.chrome&&delete o.webkit,o.atom&&delete o.chrome}},version:"0.10.2",getView:function(){var t=this.project;return t&&t._view},getPaper:function(){return this},execute:function(t,e){paper.PaperScript.execute(t,this,e),U.updateFocus()},install:function(t){var e=this;r.each(["project","view","tool"],function(i){r.define(t,i,{configurable:!0,get:function(){return e[i]}})});for(var i in this)!/^_/.test(i)&&this[i]&&(t[i]=this[i])},setup:function(t){return paper=this,this.project=new y(t),this},createCanvas:function(t,e){return Q.getCanvas(t,e)},activate:function(){paper=this},clear:function(){for(var t=this.projects,e=this.tools,i=this.palettes,n=t.length-1;n>=0;n--)t[n].remove();for(var n=e.length-1;n>=0;n--)e[n].remove();for(var n=i.length-1;n>=0;n--)i[n].remove()},remove:function(){this.clear(),delete a._scopes[this._id]},statics:new function(){function t(t){return t+="Attribute",function(e,i){return e[t](i)||e[t]("data-paper-"+i)}}return{_scopes:{},_id:0,get:function(t){return this._scopes[t]||null},getAttribute:t("get"),hasAttribute:t("has")}}}),o=r.extend(s,{initialize:function(t){this._scope=paper,this._index=this._scope[this._list].push(this)-1,!t&&this._scope[this._reference]||this.activate()},activate:function(){if(!this._scope)return!1;var t=this._scope[this._reference];return t&&t!==this&&t.emit("deactivate"),this._scope[this._reference]=this,this.emit("activate",t),!0},isActive:function(){return this._scope[this._reference]===this},remove:function(){return null!=this._index&&(r.splice(this._scope[this._list],null,this._index,1),this._scope[this._reference]==this&&(this._scope[this._reference]=null),this._scope=null,!0)},getView:function(){return this._scope.getView()}}),h=r.extend({initialize:function(t){this.precision=r.pick(t,5),this.multiplier=Math.pow(10,this.precision)},number:function(t){return this.precision<16?Math.round(t*this.multiplier)/this.multiplier:t},pair:function(t,e,i){return this.number(t)+(i||",")+this.number(e)},point:function(t,e){return this.number(t.x)+(e||",")+this.number(t.y)},size:function(t,e){return this.number(t.width)+(e||",")+this.number(t.height)},rectangle:function(t,e){return this.point(t,e)+(e||",")+this.size(t,e)}});h.instance=new h;var u=new function(){function t(t,e,i){return t<e?e:t>i?i:t}function e(t,e,i){function n(t){var e=134217729*t,i=t-e,n=i+e,r=t-n;return[n,r]}var r=e*e-t*i,a=e*e+t*i;if(3*s(r)<a){var o=n(t),h=n(e),u=n(i),l=e*e,c=h[0]*h[0]-l+2*h[0]*h[1]+h[1]*h[1],d=t*i,f=o[0]*u[0]-d+o[0]*u[1]+o[1]*u[0]+o[1]*u[1];r=l-d+(c-f)}return r}function i(){var t=Math.max.apply(Math,arguments);return t&&(t<1e-8||t>1e8)?o(2,-Math.round(h(t))):0}var n=[[.5773502691896257],[0,.7745966692414834],[.33998104358485626,.8611363115940526],[0,.5384693101056831,.906179845938664],[.2386191860831969,.6612093864662645,.932469514203152],[0,.4058451513773972,.7415311855993945,.9491079123427585],[.1834346424956498,.525532409916329,.7966664774136267,.9602898564975363],[0,.3242534234038089,.6133714327005904,.8360311073266358,.9681602395076261],[.14887433898163122,.4333953941292472,.6794095682990244,.8650633666889845,.9739065285171717],[0,.26954315595234496,.5190961292068118,.7301520055740494,.8870625997680953,.978228658146057],[.1252334085114689,.3678314989981802,.5873179542866175,.7699026741943047,.9041172563704749,.9815606342467192],[0,.2304583159551348,.44849275103644687,.6423493394403402,.8015780907333099,.9175983992229779,.9841830547185881],[.10805494870734367,.31911236892788974,.5152486363581541,.6872929048116855,.827201315069765,.9284348836635735,.9862838086968123],[0,.20119409399743451,.3941513470775634,.5709721726085388,.7244177313601701,.8482065834104272,.937273392400706,.9879925180204854],[.09501250983763744,.2816035507792589,.45801677765722737,.6178762444026438,.755404408355003,.8656312023878318,.9445750230732326,.9894009349916499]],r=[[1],[.8888888888888888,.5555555555555556],[.6521451548625461,.34785484513745385],[.5688888888888889,.47862867049936647,.23692688505618908],[.46791393457269104,.3607615730481386,.17132449237917036],[.4179591836734694,.3818300505051189,.27970539148927664,.1294849661688697],[.362683783378362,.31370664587788727,.22238103445337448,.10122853629037626],[.3302393550012598,.31234707704000286,.26061069640293544,.1806481606948574,.08127438836157441],[.29552422471475287,.26926671930999635,.21908636251598204,.1494513491505806,.06667134430868814],[.2729250867779006,.26280454451024665,.23319376459199048,.18629021092773426,.1255803694649046,.05566856711617366],[.24914704581340277,.2334925365383548,.20316742672306592,.16007832854334622,.10693932599531843,.04717533638651183],[.2325515532308739,.22628318026289723,.2078160475368885,.17814598076194574,.13887351021978725,.09212149983772845,.04048400476531588],[.2152638534631578,.2051984637212956,.18553839747793782,.15720316715819355,.12151857068790319,.08015808715976021,.03511946033175186],[.2025782419255613,.19843148532711158,.1861610000155622,.16626920581699392,.13957067792615432,.10715922046717194,.07036604748810812,.03075324199611727],[.1894506104550685,.18260341504492358,.16915651939500254,.14959598881657674,.12462897125553388,.09515851168249279,.062253523938647894,.027152459411754096]],s=Math.abs,a=Math.sqrt,o=Math.pow,h=Math.log2||function(t){return Math.log(t)*Math.LOG2E},l=1e-12,c=1.12e-16;return{TOLERANCE:1e-6,EPSILON:l,MACHINE_EPSILON:c,CURVETIME_EPSILON:4e-7,GEOMETRIC_EPSILON:2e-7,WINDING_EPSILON:2e-7,TRIGONOMETRIC_EPSILON:1e-7,CLIPPING_EPSILON:1e-9,KAPPA:4*(a(2)-1)/3,isZero:function(t){return t>=-l&&t<=l},clamp:t,integrate:function(t,e,i,s){for(var a=n[s-2],o=r[s-2],h=.5*(i-e),u=h+e,l=0,c=s+1>>1,d=1&s?o[l++]*t(u):0;l<c;){var f=h*a[l];d+=o[l++]*(t(u+f)+t(u-f))}return h*d},findRoot:function(t,e,i,n,r,a,o){for(var h=0;h<a;h++){var u=t(i),l=u/e(i),c=i-l;if(s(l)<o)return c;u>0?(r=i,i=c<=n?.5*(n+r):c):(n=i,i=c>=r?.5*(n+r):c)}return i},solveQuadratic:function(n,r,o,h,u,d){var f,_=1/0;if(s(n)<l){if(s(r)<l)return s(o)<l?-1:0;f=-o/r}else{r*=-.5;var g=e(n,r,o);if(g&&s(g)<c){var v=i(s(n),s(r),s(o));v&&(n*=v,r*=v,o*=v,g=e(n,r,o))}if(g>=-c){var p=g<0?0:a(g),m=r+(r<0?-p:p);0===m?(f=o/n,_=-f):(f=m/n,_=o/m)}}var y=0,w=null==u,x=u-l,b=d+l;return isFinite(f)&&(w||f>x&&f<b)&&(h[y++]=w?f:t(f,u,d)),_!==f&&isFinite(_)&&(w||_>x&&_<b)&&(h[y++]=w?_:t(_,u,d)),y},solveCubic:function(e,n,r,h,d,f,_){function g(t){v=t;var i=e*v;p=i+n,m=p*v+r,y=(i+p)*v+m,w=m*v+h}var v,p,m,y,w,x=i(s(e),s(n),s(r),s(h));if(x&&(e*=x,n*=x,r*=x,h*=x),s(e)<l)e=n,p=r,m=h,v=1/0;else if(s(h)<l)p=n,m=r,v=0;else{g(-(n/e)/3);var b=w/e,C=o(s(b),1/3),S=b<0?-1:1,P=-y/e,I=P>0?1.324717957244746*Math.max(C,a(P)):C,M=v-S*I;if(M!==v){do g(M),M=0===y?v:v-w/y/(1+c);while(S*M>S*v);s(e)*v*v>s(h/v)&&(m=-h/v,p=(m-r)/v)}}var T=u.solveQuadratic(e,p,m,d,f,_),k=null==f;return isFinite(v)&&(0===T||T>0&&v!==d[0]&&v!==d[1])&&(k||v>f-l&&v<_+l)&&(d[T++]=k?v:t(v,f,_)),T}}},l={_id:1,_pools:{},get:function(t){if(t){var e=this._pools[t];return e||(e=this._pools[t]={_id:1}),e._id++}return this._id++}},c=r.extend({_class:"Point",_readIndex:!0,initialize:function(t,e){var i=typeof t;if("number"===i){var n="number"==typeof e;this.x=t,this.y=n?e:t,this.__read&&(this.__read=n?2:1)}else if("undefined"===i||null===t)this.x=this.y=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===i?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.x=r[0],this.y=r.length>1?r[1]:r[0]):"x"in r?(this.x=r.x,this.y=r.y):"width"in r?(this.x=r.width,this.y=r.height):"angle"in r?(this.x=r.length,this.y=0,this.setAngle(r.angle)):(this.x=this.y=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.x=t,this.y=e,this},equals:function(t){return this===t||t&&(this.x===t.x&&this.y===t.y||Array.isArray(t)&&this.x===t[0]&&this.y===t[1])||!1},clone:function(){return new c(this.x,this.y)},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y)]},getLength:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},setLength:function(t){if(this.isZero()){var e=this._angle||0;this.set(Math.cos(e)*t,Math.sin(e)*t)}else{var i=t/this.getLength();u.isZero(i)&&this.getAngle(),this.set(this.x*i,this.y*i)}},getAngle:function(){return 180*this.getAngleInRadians.apply(this,arguments)/Math.PI},setAngle:function(t){this.setAngleInRadians.call(this,t*Math.PI/180)},getAngleInDegrees:"#getAngle",setAngleInDegrees:"#setAngle",getAngleInRadians:function(){if(arguments.length){var t=c.read(arguments),e=this.getLength()*t.getLength();if(u.isZero(e))return NaN;var i=this.dot(t)/e;return Math.acos(i<-1?-1:i>1?1:i)}return this.isZero()?this._angle||0:this._angle=Math.atan2(this.y,this.x)},setAngleInRadians:function(t){if(this._angle=t,!this.isZero()){var e=this.getLength();this.set(Math.cos(t)*e,Math.sin(t)*e)}},getQuadrant:function(){return this.x>=0?this.y>=0?1:4:this.y>=0?2:3}},{beans:!1,getDirectedAngle:function(){var t=c.read(arguments);return 180*Math.atan2(this.cross(t),this.dot(t))/Math.PI},getDistance:function(){var t=c.read(arguments),e=t.x-this.x,i=t.y-this.y,n=e*e+i*i,s=r.read(arguments);return s?n:Math.sqrt(n)},normalize:function(t){t===e&&(t=1);var i=this.getLength(),n=0!==i?t/i:0,r=new c(this.x*n,this.y*n);return n>=0&&(r._angle=this._angle),r},rotate:function(t,e){if(0===t)return this.clone();t=t*Math.PI/180;var i=e?this.subtract(e):this,n=Math.sin(t),r=Math.cos(t);return i=new c(i.x*r-i.y*n,i.x*n+i.y*r),e?i.add(e):i},transform:function(t){return t?t._transformPoint(this):this},add:function(){var t=c.read(arguments);return new c(this.x+t.x,this.y+t.y)},subtract:function(){var t=c.read(arguments);return new c(this.x-t.x,this.y-t.y)},multiply:function(){var t=c.read(arguments);return new c(this.x*t.x,this.y*t.y)},divide:function(){var t=c.read(arguments);return new c(this.x/t.x,this.y/t.y)},modulo:function(){var t=c.read(arguments);return new c(this.x%t.x,this.y%t.y)},negate:function(){return new c((-this.x),(-this.y))},isInside:function(){return g.read(arguments).contains(this)},isClose:function(){var t=c.read(arguments),e=r.read(arguments);return this.getDistance(t)<=e},isCollinear:function(){var t=c.read(arguments);return c.isCollinear(this.x,this.y,t.x,t.y)},isColinear:"#isCollinear",isOrthogonal:function(){var t=c.read(arguments);return c.isOrthogonal(this.x,this.y,t.x,t.y)},isZero:function(){return u.isZero(this.x)&&u.isZero(this.y)},isNaN:function(){return isNaN(this.x)||isNaN(this.y)},dot:function(){var t=c.read(arguments);return this.x*t.x+this.y*t.y},cross:function(){var t=c.read(arguments);return this.x*t.y-this.y*t.x},project:function(){var t=c.read(arguments),e=t.isZero()?0:this.dot(t)/t.dot(t);return new c(t.x*e,t.y*e)},statics:{min:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.min(t.x,e.x),Math.min(t.y,e.y))},max:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.max(t.x,e.x),Math.max(t.y,e.y))},random:function(){return new c(Math.random(),Math.random())},isCollinear:function(t,e,i,n){return Math.abs(t*n-e*i)<=1e-7*Math.sqrt((t*t+e*e)*(i*i+n*n))},isOrthogonal:function(t,e,i,n){return Math.abs(t*i+e*n)<=1e-7*Math.sqrt((t*t+e*e)*(i*i+n*n))}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new c(e(this.x),e(this.y))}},{})),d=c.extend({initialize:function(t,e,i,n){this._x=t,this._y=e,this._owner=i,this._setter=n},set:function(t,e,i){return this._x=t,this._y=e,i||this._owner[this._setter](this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner[this._setter](this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner[this._setter](this)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){return"setPosition"===this._setter?4:0}}),f=r.extend({_class:"Size",_readIndex:!0,initialize:function(t,e){var i=typeof t;if("number"===i){var n="number"==typeof e;this.width=t,this.height=n?e:t,this.__read&&(this.__read=n?2:1)}else if("undefined"===i||null===t)this.width=this.height=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===i?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.width=r[0],this.height=r.length>1?r[1]:r[0]):"width"in r?(this.width=r.width,this.height=r.height):"x"in r?(this.width=r.x,this.height=r.y):(this.width=this.height=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.width=t,this.height=e,this},equals:function(t){return t===this||t&&(this.width===t.width&&this.height===t.height||Array.isArray(t)&&this.width===t[0]&&this.height===t[1])||!1},clone:function(){return new f(this.width,this.height)},toString:function(){var t=h.instance;return"{ width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.width),e.number(this.height)]},add:function(){var t=f.read(arguments);return new f(this.width+t.width,this.height+t.height)},subtract:function(){var t=f.read(arguments);return new f(this.width-t.width,this.height-t.height)},multiply:function(){var t=f.read(arguments);return new f(this.width*t.width,this.height*t.height)},divide:function(){var t=f.read(arguments);return new f(this.width/t.width,this.height/t.height)},modulo:function(){var t=f.read(arguments);return new f(this.width%t.width,this.height%t.height)},negate:function(){return new f((-this.width),(-this.height))},isZero:function(){return u.isZero(this.width)&&u.isZero(this.height)},isNaN:function(){return isNaN(this.width)||isNaN(this.height)},statics:{min:function(t,e){return new f(Math.min(t.width,e.width),Math.min(t.height,e.height))},max:function(t,e){return new f(Math.max(t.width,e.width),Math.max(t.height,e.height))},random:function(){return new f(Math.random(),Math.random())}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new f(e(this.width),e(this.height))}},{})),_=f.extend({initialize:function(t,e,i,n){this._width=t,this._height=e,this._owner=i,this._setter=n},set:function(t,e,i){return this._width=t,this._height=e,i||this._owner[this._setter](this),this},getWidth:function(){return this._width},setWidth:function(t){this._width=t,this._owner[this._setter](this)},getHeight:function(){return this._height},setHeight:function(t){this._height=t,this._owner[this._setter](this)}}),g=r.extend({_class:"Rectangle",_readIndex:!0,beans:!0,initialize:function(t,i,n,s){var a=typeof t,o=0;if("number"===a?(this.x=t,this.y=i,this.width=n,this.height=s,o=4):"undefined"===a||null===t?(this.x=this.y=this.width=this.height=0,o=null===t?1:0):1===arguments.length&&(Array.isArray(t)?(this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],o=1):t.x!==e||t.width!==e?(this.x=t.x||0,this.y=t.y||0,this.width=t.width||0,this.height=t.height||0,o=1):t.from===e&&t.to===e&&(this.x=this.y=this.width=this.height=0,this._set(t),o=1)),!o){var h=c.readNamed(arguments,"from"),u=r.peek(arguments);if(this.x=h.x,this.y=h.y,u&&u.x!==e||r.hasNamed(arguments,"to")){var l=c.readNamed(arguments,"to");this.width=l.x-h.x,this.height=l.y-h.y,this.width<0&&(this.x=l.x,this.width=-this.width),this.height<0&&(this.y=l.y,this.height=-this.height)}else{var d=f.read(arguments);this.width=d.width,this.height=d.height}o=arguments.__index}this.__read&&(this.__read=o)},set:function(t,e,i,n){return this.x=t,this.y=e,this.width=i,this.height=n,this},clone:function(){return new g(this.x,this.y,this.width,this.height)},equals:function(t){var e=r.isPlainValue(t)?g.read(arguments):t;return e===this||e&&this.x===e.x&&this.y===e.y&&this.width===e.width&&this.height===e.height||!1},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+", width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y),e.number(this.width),e.number(this.height)]},getPoint:function(t){var e=t?c:d;return new e(this.x,this.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.x=t.x,this.y=t.y},getSize:function(t){var e=t?f:_;return new e(this.width,this.height,this,"setSize")},setSize:function(){var t=f.read(arguments);this._fixX&&(this.x+=(this.width-t.width)*this._fixX),this._fixY&&(this.y+=(this.height-t.height)*this._fixY),this.width=t.width,this.height=t.height,this._fixW=1,this._fixH=1},getLeft:function(){return this.x},setLeft:function(t){this._fixW||(this.width-=t-this.x),this.x=t,this._fixX=0},getTop:function(){return this.y},setTop:function(t){this._fixH||(this.height-=t-this.y),this.y=t,this._fixY=0},getRight:function(){return this.x+this.width},setRight:function(t){this._fixX!==e&&1!==this._fixX&&(this._fixW=0),this._fixW?this.x=t-this.width:this.width=t-this.x,this._fixX=1},getBottom:function(){return this.y+this.height},setBottom:function(t){this._fixY!==e&&1!==this._fixY&&(this._fixH=0),this._fixH?this.y=t-this.height:this.height=t-this.y,this._fixY=1},getCenterX:function(){return this.x+.5*this.width},setCenterX:function(t){this.x=t-.5*this.width,this._fixX=.5},getCenterY:function(){return this.y+.5*this.height},setCenterY:function(t){this.y=t-.5*this.height,this._fixY=.5},getCenter:function(t){var e=t?c:d;return new e(this.getCenterX(),this.getCenterY(),this,"setCenter")},setCenter:function(){var t=c.read(arguments);return this.setCenterX(t.x),this.setCenterY(t.y),this},getArea:function(){return this.width*this.height},isEmpty:function(){return 0===this.width||0===this.height},contains:function(t){return t&&t.width!==e||4===(Array.isArray(t)?t:arguments).length?this._containsRectangle(g.read(arguments)):this._containsPoint(c.read(arguments))},_containsPoint:function(t){var e=t.x,i=t.y;return e>=this.x&&i>=this.y&&e<=this.x+this.width&&i<=this.y+this.height},_containsRectangle:function(t){var e=t.x,i=t.y;return e>=this.x&&i>=this.y&&e+t.width<=this.x+this.width&&i+t.height<=this.y+this.height},intersects:function(){var t=g.read(arguments);return t.x+t.width>this.x&&t.y+t.height>this.y&&t.x<this.x+this.width&&t.y<this.y+this.height},touches:function(){var t=g.read(arguments);return t.x+t.width>=this.x&&t.y+t.height>=this.y&&t.x<=this.x+this.width&&t.y<=this.y+this.height},intersect:function(){var t=g.read(arguments),e=Math.max(this.x,t.x),i=Math.max(this.y,t.y),n=Math.min(this.x+this.width,t.x+t.width),r=Math.min(this.y+this.height,t.y+t.height);return new g(e,i,n-e,r-i)},unite:function(){var t=g.read(arguments),e=Math.min(this.x,t.x),i=Math.min(this.y,t.y),n=Math.max(this.x+this.width,t.x+t.width),r=Math.max(this.y+this.height,t.y+t.height);return new g(e,i,n-e,r-i)},include:function(){var t=c.read(arguments),e=Math.min(this.x,t.x),i=Math.min(this.y,t.y),n=Math.max(this.x+this.width,t.x),r=Math.max(this.y+this.height,t.y);return new g(e,i,n-e,r-i)},expand:function(){var t=f.read(arguments),e=t.width,i=t.height;return new g(this.x-e/2,this.y-i/2,this.width+e,this.height+i)},scale:function(t,i){return this.expand(this.width*t-this.width,this.height*(i===e?t:i)-this.height)}},r.each([["Top","Left"],["Top","Right"],["Bottom","Left"],["Bottom","Right"],["Left","Center"],["Top","Center"],["Right","Center"],["Bottom","Center"]],function(t,e){var i=t.join(""),n=/^[RL]/.test(i);e>=4&&(t[1]+=n?"Y":"X");var r=t[n?0:1],s=t[n?1:0],a="get"+r,o="get"+s,h="set"+r,u="set"+s,l="get"+i,f="set"+i;this[l]=function(t){var e=t?c:d;return new e(this[a](),this[o](),this,f)},this[f]=function(){var t=c.read(arguments);this[h](t.x),this[u](t.y)}},{beans:!0})),v=g.extend({initialize:function(t,e,i,n,r,s){this.set(t,e,i,n,!0),this._owner=r,this._setter=s},set:function(t,e,i,n,r){return this._x=t,this._y=e,this._width=i,this._height=n,r||this._owner[this._setter](this),this}},new function(){var t=g.prototype;return r.each(["x","y","width","height"],function(t){var e=r.capitalize(t),i="_"+t;this["get"+e]=function(){return this[i]},this["set"+e]=function(t){this[i]=t,this._dontNotify||this._owner[this._setter](this)}},r.each(["Point","Size","Center","Left","Top","Right","Bottom","CenterX","CenterY","TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],function(e){var i="set"+e;this[i]=function(){this._dontNotify=!0,t[i].apply(this,arguments),this._dontNotify=!1,this._owner[this._setter](this)}},{isSelected:function(){return!!(2&this._owner._selection)},setSelected:function(t){var e=this._owner;e.changeSelection&&e.changeSelection(2,t)}}))}),p=r.extend({_class:"Matrix",initialize:function at(t){var e=arguments.length,i=!0;if(6===e?this.set.apply(this,arguments):1===e?t instanceof at?this.set(t._a,t._b,t._c,t._d,t._tx,t._ty):Array.isArray(t)?this.set.apply(this,t):i=!1:0===e?this.reset():i=!1,!i)throw new Error("Unsupported matrix parameters")},set:function(t,e,i,n,r,s,a){return this._a=t,this._b=e,this._c=i,this._d=n,this._tx=r,this._ty=s,a||this._changed(),this},_serialize:function(t,e){return r.serialize(this.getValues(),t,!0,e)},_changed:function(){var t=this._owner;t&&(t._applyMatrix?t.transform(null,!0):t._changed(9))},clone:function(){return new p(this._a,this._b,this._c,this._d,this._tx,this._ty)},equals:function(t){return t===this||t&&this._a===t._a&&this._b===t._b&&this._c===t._c&&this._d===t._d&&this._tx===t._tx&&this._ty===t._ty},toString:function(){var t=h.instance;return"[["+[t.number(this._a),t.number(this._c),t.number(this._tx)].join(", ")+"], ["+[t.number(this._b),t.number(this._d),t.number(this._ty)].join(", ")+"]]"},reset:function(t){return this._a=this._d=1,this._b=this._c=this._tx=this._ty=0,t||this._changed(),this},apply:function(t,e){var i=this._owner;return!!i&&(i.transform(null,!0,r.pick(t,!0),e),this.isIdentity())},translate:function(){var t=c.read(arguments),e=t.x,i=t.y;return this._tx+=e*this._a+i*this._c,
+this._ty+=e*this._b+i*this._d,this._changed(),this},scale:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});return e&&this.translate(e),this._a*=t.x,this._b*=t.x,this._c*=t.y,this._d*=t.y,e&&this.translate(e.negate()),this._changed(),this},rotate:function(t){t*=Math.PI/180;var e=c.read(arguments,1),i=e.x,n=e.y,r=Math.cos(t),s=Math.sin(t),a=i-i*r+n*s,o=n-i*s-n*r,h=this._a,u=this._b,l=this._c,d=this._d;return this._a=r*h+s*l,this._b=r*u+s*d,this._c=-s*h+r*l,this._d=-s*u+r*d,this._tx+=a*h+o*l,this._ty+=a*u+o*d,this._changed(),this},shear:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});e&&this.translate(e);var i=this._a,n=this._b;return this._a+=t.y*this._c,this._b+=t.y*this._d,this._c+=t.x*i,this._d+=t.x*n,e&&this.translate(e.negate()),this._changed(),this},skew:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0}),i=Math.PI/180,n=new c(Math.tan(t.x*i),Math.tan(t.y*i));return this.shear(n,e)},append:function(t){if(t){var e=this._a,i=this._b,n=this._c,r=this._d,s=t._a,a=t._c,o=t._b,h=t._d,u=t._tx,l=t._ty;this._a=s*e+o*n,this._c=a*e+h*n,this._b=s*i+o*r,this._d=a*i+h*r,this._tx+=u*e+l*n,this._ty+=u*i+l*r,this._changed()}return this},prepend:function(t){if(t){var e=this._a,i=this._b,n=this._c,r=this._d,s=this._tx,a=this._ty,o=t._a,h=t._c,u=t._b,l=t._d,c=t._tx,d=t._ty;this._a=o*e+h*i,this._c=o*n+h*r,this._b=u*e+l*i,this._d=u*n+l*r,this._tx=o*s+h*a+c,this._ty=u*s+l*a+d,this._changed()}return this},appended:function(t){return this.clone().append(t)},prepended:function(t){return this.clone().prepend(t)},invert:function(){var t=this._a,e=this._b,i=this._c,n=this._d,r=this._tx,s=this._ty,a=t*n-e*i,o=null;return a&&!isNaN(a)&&isFinite(r)&&isFinite(s)&&(this._a=n/a,this._b=-e/a,this._c=-i/a,this._d=t/a,this._tx=(i*s-n*r)/a,this._ty=(e*r-t*s)/a,o=this),o},inverted:function(){return this.clone().invert()},concatenate:"#append",preConcatenate:"#prepend",chain:"#appended",_shiftless:function(){return new p(this._a,this._b,this._c,this._d,0,0)},_orNullIfIdentity:function(){return this.isIdentity()?null:this},isIdentity:function(){return 1===this._a&&0===this._b&&0===this._c&&1===this._d&&0===this._tx&&0===this._ty},isInvertible:function(){var t=this._a*this._d-this._c*this._b;return t&&!isNaN(t)&&isFinite(this._tx)&&isFinite(this._ty)},isSingular:function(){return!this.isInvertible()},transform:function(t,e,i){return arguments.length<3?this._transformPoint(c.read(arguments)):this._transformCoordinates(t,e,i)},_transformPoint:function(t,e,i){var n=t.x,r=t.y;return e||(e=new c),e.set(n*this._a+r*this._c+this._tx,n*this._b+r*this._d+this._ty,i)},_transformCoordinates:function(t,e,i){for(var n=0,r=2*i;n<r;n+=2){var s=t[n],a=t[n+1];e[n]=s*this._a+a*this._c+this._tx,e[n+1]=s*this._b+a*this._d+this._ty}return e},_transformCorners:function(t){var e=t.x,i=t.y,n=e+t.width,r=i+t.height,s=[e,i,n,i,n,r,e,r];return this._transformCoordinates(s,s,4)},_transformBounds:function(t,e,i){for(var n=this._transformCorners(t),r=n.slice(0,2),s=r.slice(),a=2;a<8;a++){var o=n[a],h=1&a;o<r[h]?r[h]=o:o>s[h]&&(s[h]=o)}return e||(e=new g),e.set(r[0],r[1],s[0]-r[0],s[1]-r[1],i)},inverseTransform:function(){return this._inverseTransform(c.read(arguments))},_inverseTransform:function(t,e,i){var n=this._a,r=this._b,s=this._c,a=this._d,o=this._tx,h=this._ty,u=n*a-r*s,l=null;if(u&&!isNaN(u)&&isFinite(o)&&isFinite(h)){var d=t.x-this._tx,f=t.y-this._ty;e||(e=new c),l=e.set((d*a-f*s)/u,(f*n-d*r)/u,i)}return l},decompose:function(){var t,e,i,n=this._a,r=this._b,s=this._c,a=this._d,o=n*a-r*s,h=Math.sqrt,u=Math.atan2,l=180/Math.PI;if(0!==n||0!==r){var d=h(n*n+r*r);t=Math.acos(n/d)*(r>0?1:-1),e=[d,o/d],i=[u(n*s+r*a,d*d),0]}else if(0!==s||0!==a){var f=h(s*s+a*a);t=Math.asin(s/f)*(a>0?1:-1),e=[o/f,f],i=[0,u(n*s+r*a,f*f)]}else t=0,i=e=[0,0];return{translation:this.getTranslation(),rotation:t*l,scaling:new c(e),skewing:new c(i[0]*l,i[1]*l)}},getValues:function(){return[this._a,this._b,this._c,this._d,this._tx,this._ty]},getTranslation:function(){return new c(this._tx,this._ty)},getScaling:function(){return(this.decompose()||{}).scaling},getRotation:function(){return(this.decompose()||{}).rotation},applyToContext:function(t){this.isIdentity()||t.transform(this._a,this._b,this._c,this._d,this._tx,this._ty)}},r.each(["a","b","c","d","tx","ty"],function(t){var e=r.capitalize(t),i="_"+t;this["get"+e]=function(){return this[i]},this["set"+e]=function(t){this[i]=t,this._changed()}},{})),m=r.extend({_class:"Line",initialize:function(t,e,i,n,r){var s=!1;arguments.length>=4?(this._px=t,this._py=e,this._vx=i,this._vy=n,s=r):(this._px=t.x,this._py=t.y,this._vx=e.x,this._vy=e.y,s=i),s||(this._vx-=this._px,this._vy-=this._py)},getPoint:function(){return new c(this._px,this._py)},getVector:function(){return new c(this._vx,this._vy)},getLength:function(){return this.getVector().getLength()},intersect:function(t,e){return m.intersect(this._px,this._py,this._vx,this._vy,t._px,t._py,t._vx,t._vy,!0,e)},getSide:function(t,e){return m.getSide(this._px,this._py,this._vx,this._vy,t.x,t.y,!0,e)},getDistance:function(t){return Math.abs(m.getSignedDistance(this._px,this._py,this._vx,this._vy,t.x,t.y,!0))},isCollinear:function(t){return c.isCollinear(this._vx,this._vy,t._vx,t._vy)},isOrthogonal:function(t){return c.isOrthogonal(this._vx,this._vy,t._vx,t._vy)},statics:{intersect:function(t,e,i,n,r,s,a,o,h,l){h||(i-=t,n-=e,a-=r,o-=s);var d=i*o-n*a;if(!u.isZero(d)){var f=t-r,_=e-s,g=(a*_-o*f)/d,v=(i*_-n*f)/d,p=1e-12,m=-p,y=1+p;if(l||m<g&&g<y&&m<v&&v<y)return l||(g=g<=0?0:g>=1?1:g),new c(t+g*i,e+g*n)}},getSide:function(t,e,i,n,r,s,a,o){a||(i-=t,n-=e);var h=r-t,u=s-e,l=h*n-u*i;return 0!==l||o||(l=(h*i+h*i)/(i*i+n*n),l>=0&&l<=1&&(l=0)),l<0?-1:l>0?1:0},getSignedDistance:function(t,e,i,n,r,s,a){return a||(i-=t,n-=e),0===i?n>0?r-t:t-r:0===n?i<0?s-e:e-s:((r-t)*n-(s-e)*i)/Math.sqrt(i*i+n*n)}}}),y=o.extend({_class:"Project",_list:"projects",_reference:"project",_compactSerialize:!0,initialize:function(t){o.call(this,!0),this._children=[],this._namedChildren={},this._activeLayer=null,this._currentStyle=new V(null,null,this),this._view=U.create(this,t||Q.getCanvas(1,1)),this._selectionItems={},this._selectionCount=0,this._updateVersion=0},_serialize:function(t,e){return r.serialize(this._children,t,!0,e)},_changed:function(t,e){if(1&t){var i=this._view;i&&(i._needsUpdate=!0,!i._requested&&i._autoUpdate&&i.requestUpdate())}var n=this._changes;if(n&&e){var r=this._changesById,s=e._id,a=r[s];a?a.flags|=t:n.push(r[s]={item:e,flags:t})}},clear:function(){for(var t=this._children,e=t.length-1;e>=0;e--)t[e].remove()},isEmpty:function(){return 0===this._children.length},remove:function ot(){return!!ot.base.call(this)&&(this._view&&this._view.remove(),!0)},getView:function(){return this._view},getCurrentStyle:function(){return this._currentStyle},setCurrentStyle:function(t){this._currentStyle.initialize(t)},getIndex:function(){return this._index},getOptions:function(){return this._scope.settings},getLayers:function(){return this._children},getActiveLayer:function(){return this._activeLayer||new b({project:this,insert:!0})},getSymbolDefinitions:function(){var t=[],e={};return this.getItems({"class":P,match:function(i){var n=i._definition,r=n._id;return e[r]||(e[r]=!0,t.push(n)),!1}}),t},getSymbols:"getSymbolDefinitions",getSelectedItems:function(){var t=this._selectionItems,e=[];for(var i in t){var n=t[i],r=n._selection;1&r&&n.isInserted()?e.push(n):r||this._updateSelection(n)}return e},_updateSelection:function(t){var e=t._id,i=this._selectionItems;t._selection?i[e]!==t&&(this._selectionCount++,i[e]=t):i[e]===t&&(this._selectionCount--,delete i[e])},selectAll:function(){for(var t=this._children,e=0,i=t.length;e<i;e++)t[e].setFullySelected(!0)},deselectAll:function(){var t=this._selectionItems;for(var e in t)t[e].setFullySelected(!1)},addLayer:function(t){return this.insertLayer(e,t)},insertLayer:function(t,e){if(e instanceof b){e._remove(!1,!0),r.splice(this._children,[e],t,0),e._setProject(this,!0);var i=e._name;i&&e.setName(i),this._changes&&e._changed(5),this._activeLayer||(this._activeLayer=e)}else e=null;return e},_insertItem:function(t,i,n,r){return i=this.insertLayer(t,i)||(this._activeLayer||this._insertItem(e,new b(w.NO_INSERT),!0,!0)).insertChild(t,i,n),r&&i.activate&&i.activate(),i},getItems:function(t){return w._getItems(this,t)},getItem:function(t){return w._getItems(this,t,null,null,!0)[0]||null},importJSON:function(t){this.activate();var e=this._activeLayer;return r.importJSON(t,e&&e.isEmpty()&&e)},removeOn:function(t){var e=this._removeSets;if(e){"mouseup"===t&&(e.mousedrag=null);var i=e[t];if(i){for(var n in i){var r=i[n];for(var s in e){var a=e[s];a&&a!=i&&delete a[r._id]}r.remove()}e[t]=null}}},draw:function(t,e,i){this._updateVersion++,t.save(),e.applyToContext(t);for(var n=this._children,s=new r({offset:new c(0,0),pixelRatio:i,viewMatrix:e.isIdentity()?null:e,matrices:[new p],updateMatrix:!0}),a=0,o=n.length;a<o;a++)n[a].draw(t,s);if(t.restore(),this._selectionCount>0){t.save(),t.strokeWidth=1;var h=this._selectionItems,u=this._scope.settings.handleSize,l=this._updateVersion;for(var d in h)h[d]._drawSelection(t,e,u,h,l);t.restore()}}}),w=r.extend(s,{statics:{extend:function ht(t){return t._serializeFields&&(t._serializeFields=r.set({},this.prototype._serializeFields,t._serializeFields)),ht.base.apply(this,arguments)},NO_INSERT:{insert:!1}},_class:"Item",_name:null,_applyMatrix:!0,_canApplyMatrix:!0,_canScaleStroke:!1,_pivot:null,_visible:!0,_blendMode:"normal",_opacity:1,_locked:!1,_guide:!1,_clipMask:!1,_selection:0,_selectBounds:!0,_selectChildren:!1,_serializeFields:{name:null,applyMatrix:null,matrix:new p,pivot:null,visible:!0,blendMode:"normal",opacity:1,locked:!1,guide:!1,clipMask:!1,selected:!1,data:{}}},new function(){var t=["onMouseDown","onMouseUp","onMouseDrag","onClick","onDoubleClick","onMouseMove","onMouseEnter","onMouseLeave"];return r.each(t,function(t){this._events[t]={install:function(t){this.getView()._countItemEvent(t,1)},uninstall:function(t){this.getView()._countItemEvent(t,-1)}}},{_events:{onFrame:{install:function(){this.getView()._animateItem(this,!0)},uninstall:function(){this.getView()._animateItem(this,!1)}},onLoad:{},onError:{}},statics:{_itemHandlers:t}})},{initialize:function(){},_initialize:function(t,i){var n=t&&r.isPlainObject(t),s=n&&t.internal===!0,a=this._matrix=new p,o=n&&t.project||paper.project,h=paper.settings;return this._id=s?null:l.get(),this._parent=this._index=null,this._applyMatrix=this._canApplyMatrix&&h.applyMatrix,i&&a.translate(i),a._owner=this,this._style=new V(o._currentStyle,this,o),s||n&&t.insert===!1||!h.insertItems&&(!n||t.insert!==!0)?this._setProject(o):(n&&t.parent||o)._insertItem(e,this,!0,!0),n&&t!==w.NO_INSERT&&r.filter(this,t,{internal:!0,insert:!0,project:!0,parent:!0}),n},_serialize:function(t,e){function i(i){for(var a in i){var o=s[a];r.equals(o,"leading"===a?1.2*i.fontSize:i[a])||(n[a]=r.serialize(o,t,"data"!==a,e))}}var n={},s=this;return i(this._serializeFields),this instanceof x||i(this._style._defaults),[this._class,n]},_changed:function(t){var i=this._symbol,n=this._parent||i,r=this._project;8&t&&(this._bounds=this._position=this._decomposed=this._globalMatrix=e),n&&40&t&&w._clearBoundsCache(n),2&t&&w._clearBoundsCache(this),r&&r._changed(t,this),i&&i._changed(t)},set:function(t){return t&&this._set(t),this},getId:function(){return this._id},getName:function(){return this._name},setName:function(t){if(this._name&&this._removeNamed(),t===+t+"")throw new Error("Names consisting only of numbers are not supported.");var i=this._getOwner();if(t&&i){var n=i._children,r=i._namedChildren;(r[t]=r[t]||[]).push(this),t in n||(n[t]=this)}this._name=t||e,this._changed(128)},getStyle:function(){return this._style},setStyle:function(t){this.getStyle().set(t)}},r.each(["locked","visible","blendMode","opacity","guide"],function(t){var e=r.capitalize(t),t="_"+t;this["get"+e]=function(){return this[t]},this["set"+e]=function(e){e!=this[t]&&(this[t]=e,this._changed("_locked"===t?128:129))}},{}),{beans:!0,getSelection:function(){return this._selection},setSelection:function(t){if(t!==this._selection){this._selection=t;var e=this._project;e&&(e._updateSelection(this),this._changed(129))}},changeSelection:function(t,e){var i=this._selection;this.setSelection(e?i|t:i&~t)},isSelected:function(){if(this._selectChildren)for(var t=this._children,e=0,i=t.length;e<i;e++)if(t[e].isSelected())return!0;return!!(1&this._selection)},setSelected:function(t){if(this._selectChildren)for(var e=this._children,i=0,n=e.length;i<n;i++)e[i].setSelected(t);this.changeSelection(1,t)},isFullySelected:function(){var t=this._children,e=!!(1&this._selection);if(t&&e){for(var i=0,n=t.length;i<n;i++)if(!t[i].isFullySelected())return!1;return!0}return e},setFullySelected:function(t){var e=this._children;if(e)for(var i=0,n=e.length;i<n;i++)e[i].setFullySelected(t);this.changeSelection(1,t)},isClipMask:function(){return this._clipMask},setClipMask:function(t){this._clipMask!=(t=!!t)&&(this._clipMask=t,t&&(this.setFillColor(null),this.setStrokeColor(null)),this._changed(129),this._parent&&this._parent._changed(1024))},getData:function(){return this._data||(this._data={}),this._data},setData:function(t){this._data=t},getPosition:function(t){var e=this._position,i=t?c:d;if(!e){var n=this._pivot;e=this._position=n?this._matrix._transformPoint(n):this.getBounds().getCenter(!0)}return new i(e.x,e.y,this,"setPosition")},setPosition:function(){this.translate(c.read(arguments).subtract(this.getPosition(!0)))},getPivot:function(t){var e=this._pivot;if(e){var i=t?c:d;e=new i(e.x,e.y,this,"setPivot")}return e},setPivot:function(){this._pivot=c.read(arguments,0,{clone:!0,readNull:!0}),this._position=e}},r.each({getStrokeBounds:{stroke:!0},getHandleBounds:{handle:!0},getInternalBounds:{internal:!0}},function(t,e){this[e]=function(e){return this.getBounds(e,t)}},{beans:!0,getBounds:function(t,e){var i=e||t instanceof p,n=r.set({},i?e:t,this._boundsOptions);n.stroke&&!this.getStrokeScaling()||(n.cacheItem=this);var s=this._getCachedBounds(i&&t,n);return 0===arguments.length?new v(s.x,s.y,s.width,s.height,this,"setBounds"):s},setBounds:function(){var t=g.read(arguments),e=this.getBounds(),i=this._matrix,n=new p,r=t.getCenter();n.translate(r),t.width==e.width&&t.height==e.height||(i.isInvertible()||(i.initialize(i._backup||(new p).translate(i.getTranslation())),e=this.getBounds()),n.scale(0!==e.width?t.width/e.width:0,0!==e.height?t.height/e.height:0)),r=e.getCenter(),n.translate(-r.x,-r.y),this.transform(n)},_getBounds:function(t,e){var i=this._children;return i&&0!==i.length?(w._updateBoundsCache(this,e.cacheItem),w._getBounds(i,t,e)):new g},_getCachedBounds:function(t,e){t=t&&t._orNullIfIdentity();var i=e.internal,n=e.cacheItem,r=i?null:this._matrix._orNullIfIdentity(),s=n&&(!t||t.equals(r))&&[e.stroke?1:0,e.handle?1:0,i?1:0].join("");if(w._updateBoundsCache(this._parent||this._symbol,n),s&&this._bounds&&s in this._bounds)return this._bounds[s].rect.clone();var a=this._getBounds(t||r,e);if(s){this._bounds||(this._bounds={});this._bounds[s]={rect:a.clone(),internal:e.internal}}return a},_getStrokeMatrix:function(t,e){var i=this.getStrokeScaling()?null:e&&e.internal?this:this._parent||this._symbol&&this._symbol._item,n=i?i.getViewMatrix().invert():t;return n&&n._shiftless()},statics:{_updateBoundsCache:function(t,e){if(t&&e){var i=e._id,n=t._boundsCache=t._boundsCache||{ids:{},list:[]};n.ids[i]||(n.list.push(e),n.ids[i]=e)}},_clearBoundsCache:function(t){var i=t._boundsCache;if(i){t._bounds=t._position=t._boundsCache=e;for(var n=0,r=i.list,s=r.length;n<s;n++){var a=r[n];a!==t&&(a._bounds=a._position=e,a._boundsCache&&w._clearBoundsCache(a))}}},_getBounds:function(t,e,i){var n=1/0,r=-n,s=n,a=r;i=i||{};for(var o=0,h=t.length;o<h;o++){var u=t[o];if(u._visible&&!u.isEmpty()){var l=u._getCachedBounds(e&&e.appended(u._matrix),i);n=Math.min(l.x,n),s=Math.min(l.y,s),r=Math.max(l.x+l.width,r),a=Math.max(l.y+l.height,a)}}return isFinite(n)?new g(n,s,r-n,a-s):new g}}}),{beans:!0,_decompose:function(){return this._decomposed||(this._decomposed=this._matrix.decompose())},getRotation:function(){var t=this._decompose();return t&&t.rotation},setRotation:function(t){var e=this.getRotation();null!=e&&null!=t&&this.rotate(t-e)},getScaling:function(t){var e=this._decompose(),i=e&&e.scaling,n=t?c:d;return i&&new n(i.x,i.y,this,"setScaling")},setScaling:function(){var t=this.getScaling(),e=c.read(arguments,0,{clone:!0,readNull:!0});t&&e&&this.scale(e.x/t.x,e.y/t.y)},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},getGlobalMatrix:function(t){var e=this._globalMatrix,i=this._project._updateVersion;if(e&&e._updateVersion!==i&&(e=null),!e){e=this._globalMatrix=this._matrix.clone();var n=this._parent;n&&e.prepend(n.getGlobalMatrix(!0)),e._updateVersion=i}return t?e:e.clone()},getViewMatrix:function(){return this.getGlobalMatrix().prepend(this.getView()._matrix)},getApplyMatrix:function(){return this._applyMatrix},setApplyMatrix:function(t){(this._applyMatrix=this._canApplyMatrix&&!!t)&&this.transform(null,!0)},getTransformContent:"#getApplyMatrix",setTransformContent:"#setApplyMatrix"},{getProject:function(){return this._project},_setProject:function(t,e){if(this._project!==t){this._project&&this._installEvents(!1),this._project=t;for(var i=this._children,n=0,r=i&&i.length;n<r;n++)i[n]._setProject(t);e=!0}e&&this._installEvents(!0)},getView:function(){return this._project._view},_installEvents:function ut(t){ut.base.call(this,t);for(var e=this._children,i=0,n=e&&e.length;i<n;i++)e[i]._installEvents(t)},getLayer:function(){for(var t=this;t=t._parent;)if(t instanceof b)return t;return null},getParent:function(){return this._parent},setParent:function(t){return t.addChild(this)},_getOwner:"#getParent",getChildren:function(){return this._children},setChildren:function(t,e){this.removeChildren(),this.addChildren(t,e)},getFirstChild:function(){return this._children&&this._children[0]||null},getLastChild:function(){return this._children&&this._children[this._children.length-1]||null},getNextSibling:function(){var t=this._getOwner();return t&&t._children[this._index+1]||null},getPreviousSibling:function(){var t=this._getOwner();return t&&t._children[this._index-1]||null},getIndex:function(){return this._index},equals:function(t){return t===this||t&&this._class===t._class&&this._style.equals(t._style)&&this._matrix.equals(t._matrix)&&this._locked===t._locked&&this._visible===t._visible&&this._blendMode===t._blendMode&&this._opacity===t._opacity&&this._clipMask===t._clipMask&&this._guide===t._guide&&this._equals(t)||!1},_equals:function(t){return r.equals(this._children,t._children)},clone:function(t){var i=new this.constructor(w.NO_INSERT),n=this._children,s=r.pick(t?t.insert:e,t===e||t===!0),a=r.pick(t?t.deep:e,!0);n&&i.copyAttributes(this),n&&!a||i.copyContent(this),n||i.copyAttributes(this),s&&i.insertAbove(this);var o=this._name,h=this._parent;if(o&&h){for(var n=h._children,u=o,l=1;n[o];)o=u+" "+l++;o!==u&&i.setName(o)}return i},copyContent:function(t){for(var e=t._children,i=0,n=e&&e.length;i<n;i++)this.addChild(e[i].clone(!1),!0)},copyAttributes:function(t,e){this.setStyle(t._style);for(var i=["_locked","_visible","_blendMode","_opacity","_clipMask","_guide"],n=0,s=i.length;n<s;n++){var a=i[n];t.hasOwnProperty(a)&&(this[a]=t[a])}e||this._matrix.initialize(t._matrix),this.setApplyMatrix(t._applyMatrix),this.setPivot(t._pivot),this.setSelection(t._selection);var o=t._data,h=t._name;this._data=o?r.clone(o):null,h&&this.setName(h)},rasterize:function(t,i){var n=this.getStrokeBounds(),s=(t||this.getView().getResolution())/72,a=n.getTopLeft().floor(),o=n.getBottomRight().ceil(),h=new f(o.subtract(a)),u=new S(w.NO_INSERT);if(!h.isZero()){var l=Q.getCanvas(h.multiply(s)),c=l.getContext("2d"),d=(new p).scale(s).translate(a.negate());c.save(),d.applyToContext(c),this.draw(c,new r({matrices:[d]})),c.restore(),u.setCanvas(l)}return u.transform((new p).translate(a.add(h.divide(2))).scale(1/s)),(i===e||i)&&u.insertAbove(this),u},contains:function(){return!!this._contains(this._matrix._inverseTransform(c.read(arguments)))},_contains:function(t){var e=this._children;if(e){for(var i=e.length-1;i>=0;i--)if(e[i].contains(t))return!0;return!1}return t.isInside(this.getInternalBounds())},isInside:function(){return g.read(arguments).contains(this.getBounds())},_asPathItem:function(){return new L.Rectangle({rectangle:this.getInternalBounds(),matrix:this._matrix,insert:!1})},intersects:function(t,e){return t instanceof w&&this._asPathItem().getIntersections(t._asPathItem(),null,e,!0).length>0}},new function(){function t(){return this._hitTest(c.read(arguments),M.getOptions(arguments))}function e(){var t=c.read(arguments),e=M.getOptions(arguments),i=e.match,n=[];return e=r.set({},e,{match:function(t){i&&!i(t)||n.push(t)}}),this._hitTest(t,e),n}function i(t,e,i,n){var r=this._children;if(r)for(var s=r.length-1;s>=0;s--){var a=r[s],o=a!==n&&a._hitTest(t,e,i);if(o)return o}return null}return y.inject({hitTest:t,hitTestAll:e,_hitTest:i}),{hitTest:t,hitTestAll:e,_hitTestChildren:i}},{_hitTest:function(t,e,i){function n(t){return!g||t&&g(t)?t:null}function s(e,i){var n=c["get"+i]();if(t.subtract(n).divide(l).length<=1)return new M(e,v,{name:r.hyphenate(i),point:n})}if(this._locked||!this._visible||this._guide&&!e.guides||this.isEmpty())return null;var a=this._matrix,o=i?i.appended(a):this.getGlobalMatrix().prepend(this.getView()._matrix),h=this.getStrokeScaling()?null:o.inverted()._shiftless(),u=Math.max(e.tolerance,1e-6),l=e._tolerancePadding=new f(L._getStrokePadding(u,h));if(t=a._inverseTransform(t),!t||!this._children&&!this.getBounds({internal:!0,stroke:!0,handle:!0}).expand(l.multiply(2))._containsPoint(t))return null;var c,d,_=!(e.guides&&!this._guide||e.selected&&!this.isSelected()||e.type&&e.type!==r.hyphenate(this._class)||e["class"]&&!(this instanceof e["class"])),g=e.match,v=this;if(_&&(e.center||e.bounds)&&this._parent){if(c=this.getInternalBounds(),e.center&&(d=s("center","Center")),!d&&e.bounds)for(var p=["TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],m=0;m<8&&!d;m++)d=s("bounds",p[m]);d=n(d)}return d||(d=this._hitTestChildren(t,e,o)||_&&n(this._hitTestSelf(t,e,o,h))||null),d&&d.point&&(d.point=a.transform(d.point)),d},_hitTestSelf:function(t,e){if(e.fill&&this.hasFill()&&this._contains(t))return new M("fill",this)},matches:function(t,e){function i(t,e){for(var n in t)if(t.hasOwnProperty(n)){var s=t[n],a=e[n];if(r.isPlainObject(s)&&r.isPlainObject(a)){if(!i(s,a))return!1}else if(!r.equals(s,a))return!1}return!0}var n=typeof t;if("object"===n){for(var s in t)if(t.hasOwnProperty(s)&&!this.matches(s,t[s]))return!1;return!0}if("function"===n)return t(this);if("match"===t)return e(this);var a=/^(empty|editable)$/.test(t)?this["is"+r.capitalize(t)]():"type"===t?r.hyphenate(this._class):this[t];if("class"===t){if("function"==typeof e)return this instanceof e;a=this._class}if("function"==typeof e)return!!e(a);if(e){if(e.test)return e.test(a);if(r.isPlainObject(e))return i(e,a)}return r.equals(a,e)},getItems:function(t){return w._getItems(this,t,this._matrix)},getItem:function(t){return w._getItems(this,t,this._matrix,null,!0)[0]||null},statics:{_getItems:function lt(t,e,i,n,s){if(!n){var a="object"==typeof e&&e,o=a&&a.overlapping,h=a&&a.inside,u=o||h,l=u&&g.read([u]);n={items:[],recursive:a&&a.recursive!==!1,inside:!!h,overlapping:!!o,rect:l,path:o&&new L.Rectangle({rectangle:l,insert:!1})},a&&(e=r.filter({},e,{recursive:!0,inside:!0,overlapping:!0}))}var c=t._children,d=n.items,l=n.rect;i=l&&(i||new p);for(var f=0,_=c&&c.length;f<_;f++){var v=c[f],m=i&&i.appended(v._matrix),y=!0;if(l){var u=v.getBounds(m);if(!l.intersects(u))continue;l.contains(u)||n.overlapping&&(u.contains(l)||n.path.intersects(v,m))||(y=!1)}if(y&&v.matches(e)&&(d.push(v),s))break;if(n.recursive!==!1&&lt(v,e,m,n,s),s&&d.length>0)break}return d}}},{importJSON:function(t){var e=r.importJSON(t,this);return e!==this?this.addChild(e):e},addChild:function(t,i){return this.insertChild(e,t,i)},insertChild:function(t,e,i){var n=e?this.insertChildren(t,[e],i):null;return n&&n[0]},addChildren:function(t,e){return this.insertChildren(this._children.length,t,e)},insertChildren:function(t,e,i,n){var s=this._children;if(s&&e&&e.length>0){e=Array.prototype.slice.apply(e);for(var a=e.length-1;a>=0;a--){var o=e[a];o&&(!n||o instanceof n)?o._remove(!1,!0):e.splice(a,1)}r.splice(s,e,t,0);for(var h=this._project,u=h._changes,a=0,l=e.length;a<l;a++){var o=e[a],c=o._name;o._parent=this,o._setProject(h,!0),c&&o.setName(c),u&&this._changed(5)}this._changed(11)}else e=null;return e},_insertItem:"#insertChild",_insertAt:function(t,e,i){var n=this;if(n!==t){var r=t&&t._getOwner();r?(n._remove(!1,!0),r._insertItem(t._index+e,n,i)):n=null}return n},insertAbove:function(t,e){return this._insertAt(t,1,e)},insertBelow:function(t,e){return this._insertAt(t,0,e)},sendToBack:function(){var t=this._getOwner();return t?t._insertItem(0,this):null},bringToFront:function(){var t=this._getOwner();return t?t._insertItem(e,this):null},appendTop:"#addChild",appendBottom:function(t){return this.insertChild(0,t)},moveAbove:"#insertAbove",moveBelow:"#insertBelow",copyTo:function(t){return t._insertItem(e,this.clone(!1))},reduce:function(t){var e=this._children;if(e&&1===e.length){var i=e[0].reduce(t);return this._parent?(i.insertAbove(this),this.remove()):i.remove(),i}return this},_removeNamed:function(){var t=this._getOwner();if(t){var e=t._children,i=t._namedChildren,n=this._name,r=i[n],s=r?r.indexOf(this):-1;s!==-1&&(e[n]==this&&delete e[n],r.splice(s,1),r.length?e[n]=r[0]:delete i[n])}},_remove:function(t,e){var i=this._getOwner(),n=this._project,s=this._index;return!!i&&(null!=s&&(n._activeLayer===this&&(n._activeLayer=this.getNextSibling()||this.getPreviousSibling()),r.splice(i._children,null,s,1)),this._name&&this._removeNamed(),this._installEvents(!1),t&&n._changes&&this._changed(5),e&&i._changed(11,this),this._parent=null,!0)},remove:function(){return this._remove(!0,!0)},replaceWith:function(t){var e=t&&t.insertBelow(this);return e&&this.remove(),e},removeChildren:function(t,e){if(!this._children)return null;t=t||0,e=r.pick(e,this._children.length);for(var i=r.splice(this._children,null,t,e-t),n=i.length-1;n>=0;n--)i[n]._remove(!0,!1);return i.length>0&&this._changed(11),i},clear:"#removeChildren",reverseChildren:function(){if(this._children){this._children.reverse();for(var t=0,e=this._children.length;t<e;t++)this._children[t]._index=t;this._changed(11)}},isEmpty:function(){return!this._children||0===this._children.length},isEditable:function(){for(var t=this;t;){if(!t._visible||t._locked)return!1;t=t._parent}return!0},hasFill:function(){return this.getStyle().hasFill()},hasStroke:function(){return this.getStyle().hasStroke()},hasShadow:function(){return this.getStyle().hasShadow()},_getOrder:function(t){function e(t){var e=[];do e.unshift(t);while(t=t._parent);return e}for(var i=e(this),n=e(t),r=0,s=Math.min(i.length,n.length);r<s;r++)if(i[r]!=n[r])return i[r]._index<n[r]._index?1:-1;return 0},hasChildren:function(){return this._children&&this._children.length>0},isInserted:function(){return!!this._parent&&this._parent.isInserted()},isAbove:function(t){return this._getOrder(t)===-1},isBelow:function(t){return 1===this._getOrder(t)},isParent:function(t){return this._parent===t},isChild:function(t){return t&&t._parent===this},isDescendant:function(t){for(var e=this;e=e._parent;)if(e===t)return!0;return!1},isAncestor:function(t){return!!t&&t.isDescendant(this)},isSibling:function(t){return this._parent===t._parent},isGroupedWith:function(t){for(var e=this._parent;e;){if(e._parent&&/^(Group|Layer|CompoundPath)$/.test(e._class)&&t.isDescendant(e))return!0;e=e._parent}return!1}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var i=(e?r:c).read(arguments),n=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](i,n||this.getPosition(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t,e,i,n){t&&t.isIdentity()&&(t=null);var r=this._matrix,s=(e||this._applyMatrix)&&(!r.isIdentity()||t||e&&i&&this._children);if(!t&&!s)return this;if(t&&(!t.isInvertible()&&r.isInvertible()&&(r._backup=r.getValues()),r.prepend(t)),s=s&&this._transformContent(r,i,n)){var a=this._pivot,o=this._style,h=o.getFillColor(!0),u=o.getStrokeColor(!0);a&&r._transformPoint(a,a,!0),h&&h.transform(r),u&&u.transform(r),r.reset(!0),n&&this._canApplyMatrix&&(this._applyMatrix=!0)}var l=this._bounds,c=this._position;this._changed(9);var d=l&&t&&t.decompose();if(d&&!d.shearing&&d.rotation%90===0){for(var f in l){var _=l[f];if(s||!_.internal){var g=_.rect;t._transformBounds(g,g)}}var v=this._boundsGetter,g=l[v&&v.getBounds||v||"getBounds"];g&&(this._position=g.getCenter(!0)),this._bounds=l}else t&&c&&(this._position=t._transformPoint(c,c));return this},_transformContent:function(t,e,i){var n=this._children;if(n){for(var r=0,s=n.length;r<s;r++)n[r].transform(t,!0,e,i);return!0}},globalToLocal:function(){return this.getGlobalMatrix(!0)._inverseTransform(c.read(arguments))},localToGlobal:function(){return this.getGlobalMatrix(!0)._transformPoint(c.read(arguments))},parentToLocal:function(){return this._matrix._inverseTransform(c.read(arguments))},localToParent:function(){return this._matrix._transformPoint(c.read(arguments))},fitBounds:function(t,e){t=g.read(arguments);var i=this.getBounds(),n=i.height/i.width,r=t.height/t.width,s=(e?n>r:n<r)?t.width/i.width:t.height/i.height,a=new g(new c,new f(i.width*s,i.height*s));a.setCenter(t.getCenter()),this.setBounds(a)}}),{_setStyles:function(t,e,i){var n=this._style;if(n.hasFill()&&(t.fillStyle=n.getFillColor().toCanvasStyle(t)),n.hasStroke()){t.strokeStyle=n.getStrokeColor().toCanvasStyle(t),t.lineWidth=n.getStrokeWidth();var r=n.getStrokeJoin(),s=n.getStrokeCap(),a=n.getMiterLimit();if(r&&(t.lineJoin=r),s&&(t.lineCap=s),a&&(t.miterLimit=a),paper.support.nativeDash){var o=n.getDashArray(),h=n.getDashOffset();o&&o.length&&("setLineDash"in t?(t.setLineDash(o),t.lineDashOffset=h):(t.mozDash=o,t.mozDashOffset=h))}}if(n.hasShadow()){var u=e.pixelRatio||1,l=i._shiftless().prepend((new p).scale(u,u)),d=l.transform(new c(n.getShadowBlur(),0)),f=l.transform(this.getShadowOffset());t.shadowColor=n.getShadowColor().toCanvasStyle(t),t.shadowBlur=d.getLength(),t.shadowOffsetX=f.x,t.shadowOffsetY=f.y}},draw:function(t,e,i){var n=this._updateVersion=this._project._updateVersion;if(this._visible&&0!==this._opacity){var r=e.matrices,s=e.viewMatrix,a=this._matrix,o=r[r.length-1].appended(a);if(o.isInvertible()){s=s?s.appended(o):o,r.push(o),e.updateMatrix&&(o._updateVersion=n,this._globalMatrix=o);var h,u,l,c=this._blendMode,d=this._opacity,f="normal"===c,_=tt.nativeModes[c],g=f&&1===d||e.dontStart||e.clip||(_||f&&d<1)&&this._canComposite(),v=e.pixelRatio||1;if(!g){var p=this.getStrokeBounds(s);if(!p.width||!p.height)return;l=e.offset,u=e.offset=p.getTopLeft().floor(),h=t,t=Q.getContext(p.getSize().ceil().add(1).multiply(v)),1!==v&&t.scale(v,v)}t.save();var m=i?i.appended(a):this._canScaleStroke&&!this.getStrokeScaling(!0)&&s,y=!g&&e.clipItem,w=!m||y;if(g?(t.globalAlpha=d,_&&(t.globalCompositeOperation=c)):w&&t.translate(-u.x,-u.y),w&&(g?a:s).applyToContext(t),y&&e.clipItem.draw(t,e.extend({clip:!0})),m){t.setTransform(v,0,0,v,0,0);var x=e.offset;x&&t.translate(-x.x,-x.y)}this._draw(t,e,s,m),t.restore(),r.pop(),e.clip&&!e.dontFinish&&t.clip(),g||(tt.process(c,t,h,d,u.subtract(l).multiply(v)),Q.release(t),e.offset=l)}}},_isUpdated:function(t){var e=this._parent;if(e instanceof N)return e._isUpdated(t);var i=this._updateVersion===t;return!i&&e&&e._visible&&e._isUpdated(t)&&(this._updateVersion=t,i=!0),i},_drawSelection:function(t,e,i,n,r){var s=this._selection,a=1&s,o=2&s||a&&this._selectBounds,h=4&s;if(this._drawSelected||(a=!1),
+(a||o||h)&&this._isUpdated(r)){var u,l=this.getSelectedColor(!0)||(u=this.getLayer())&&u.getSelectedColor(!0),c=e.appended(this.getGlobalMatrix(!0)),d=i/2;if(t.strokeStyle=t.fillStyle=l?l.toCanvasStyle(t):"#009dec",a&&this._drawSelected(t,c,n),h){var f=this.getPosition(!0),_=f.x,g=f.y;t.beginPath(),t.arc(_,g,d,0,2*Math.PI,!0),t.stroke();for(var v=[[0,-1],[1,0],[0,1],[-1,0]],p=d,m=i+1,y=0;y<4;y++){var w=v[y],x=w[0],b=w[1];t.moveTo(_+x*p,g+b*p),t.lineTo(_+x*m,g+b*m),t.stroke()}}if(o){var C=c._transformCorners(this.getInternalBounds());t.beginPath();for(var y=0;y<8;y++)t[0===y?"moveTo":"lineTo"](C[y],C[++y]);t.closePath(),t.stroke();for(var y=0;y<8;y++)t.fillRect(C[y]-d,C[++y]-d,i,i)}}},_canComposite:function(){return!1}},r.each(["down","drag","up","move"],function(t){this["removeOn"+r.capitalize(t)]=function(){var e={};return e[t]=!0,this.removeOn(e)}},{removeOn:function(t){for(var e in t)if(t[e]){var i="mouse"+e,n=this._project,r=n._removeSets=n._removeSets||{};r[i]=r[i]||{},r[i][this._id]=this}return this}})),x=w.extend({_class:"Group",_selectBounds:!1,_selectChildren:!0,_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||this.addChildren(Array.isArray(t)?t:arguments)},_changed:function ct(t){ct.base.call(this,t),1026&t&&(this._clipItem=e)},_getClipItem:function(){var t=this._clipItem;if(t===e){t=null;for(var i=this._children,n=0,r=i.length;n<r;n++)if(i[n]._clipMask){t=i[n];break}this._clipItem=t}return t},isClipped:function(){return!!this._getClipItem()},setClipped:function(t){var e=this.getFirstChild();e&&e.setClipMask(t)},_getBounds:function dt(t,e){var i=this._getClipItem();return i?i._getCachedBounds(t&&t.appended(i._matrix),r.set({},e,{stroke:!1})):dt.base.call(this,t,e)},_hitTestChildren:function ft(t,e,i){var n=this._getClipItem();return(!n||n.contains(t))&&ft.base.call(this,t,e,i,n)},_draw:function(t,e){var i=e.clip,n=!i&&this._getClipItem();e=e.extend({clipItem:n,clip:!1}),i?(t.beginPath(),e.dontStart=e.dontFinish=!0):n&&n.draw(t,e.extend({clip:!0}));for(var r=this._children,s=0,a=r.length;s<a;s++){var o=r[s];o!==n&&o.draw(t,e)}}}),b=x.extend({_class:"Layer",initialize:function(){x.apply(this,arguments)},_getOwner:function(){return this._parent||null!=this._index&&this._project},isInserted:function _t(){return this._parent?_t.base.call(this):null!=this._index},activate:function(){this._project._activeLayer=this},_hitTestSelf:function(){}}),C=w.extend({_class:"Shape",_applyMatrix:!1,_canApplyMatrix:!1,_canScaleStroke:!0,_serializeFields:{type:null,size:null,radius:null},initialize:function(t){this._initialize(t)},_equals:function(t){return this._type===t._type&&this._size.equals(t._size)&&r.equals(this._radius,t._radius)},copyContent:function(t){this.setType(t._type),this.setSize(t._size),this.setRadius(t._radius)},getType:function(){return this._type},setType:function(t){this._type=t},getShape:"#getType",setShape:"#setType",getSize:function(){var t=this._size;return new _(t.width,t.height,this,"setSize")},setSize:function(){var t=f.read(arguments);if(this._size){if(!this._size.equals(t)){var e=this._type,i=t.width,n=t.height;if("rectangle"===e){var r=f.min(this._radius,t.divide(2));this._radius.set(r.width,r.height)}else"circle"===e?(i=n=(i+n)/2,this._radius=i/2):"ellipse"===e&&this._radius.set(i/2,n/2);this._size.set(i,n),this._changed(9)}}else this._size=t.clone()},getRadius:function(){var t=this._radius;return"circle"===this._type?t:new _(t.width,t.height,this,"setRadius")},setRadius:function(t){var e=this._type;if("circle"===e){if(t===this._radius)return;var i=2*t;this._radius=t,this._size.set(i,i)}else if(t=f.read(arguments),this._radius){if(this._radius.equals(t))return;if(this._radius.set(t.width,t.height),"rectangle"===e){var i=f.max(this._size,t.multiply(2));this._size.set(i.width,i.height)}else"ellipse"===e&&this._size.set(2*t.width,2*t.height)}else this._radius=t.clone();this._changed(9)},isEmpty:function(){return!1},toPath:function(t){var i=new(L[r.capitalize(this._type)])({center:new c,size:this._size,radius:this._radius,insert:!1});return i.copyAttributes(this),paper.settings.applyMatrix&&i.setApplyMatrix(!0),(t===e||t)&&i.insertAbove(this),i},toShape:"#clone",_draw:function(t,e,i,n){var r=this._style,s=r.hasFill(),a=r.hasStroke(),o=e.dontFinish||e.clip,h=!n;if(s||a||o){var u=this._type,l=this._radius,c="circle"===u;if(e.dontStart||t.beginPath(),h&&c)t.arc(0,0,l,0,2*Math.PI,!0);else{var d=c?l:l.width,f=c?l:l.height,_=this._size,g=_.width,v=_.height;if(h&&"rectangle"===u&&0===d&&0===f)t.rect(-g/2,-v/2,g,v);else{var p=g/2,m=v/2,y=.44771525016920644,w=d*y,x=f*y,b=[-p,-m+f,-p,-m+x,-p+w,-m,-p+d,-m,p-d,-m,p-w,-m,p,-m+x,p,-m+f,p,m-f,p,m-x,p-w,m,p-d,m,-p+d,m,-p+w,m,-p,m-x,-p,m-f];n&&n.transform(b,b,32),t.moveTo(b[0],b[1]),t.bezierCurveTo(b[2],b[3],b[4],b[5],b[6],b[7]),p!==d&&t.lineTo(b[8],b[9]),t.bezierCurveTo(b[10],b[11],b[12],b[13],b[14],b[15]),m!==f&&t.lineTo(b[16],b[17]),t.bezierCurveTo(b[18],b[19],b[20],b[21],b[22],b[23]),p!==d&&t.lineTo(b[24],b[25]),t.bezierCurveTo(b[26],b[27],b[28],b[29],b[30],b[31])}}t.closePath()}o||!s&&!a||(this._setStyles(t,e,i),s&&(t.fill(r.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),a&&t.stroke())},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_getBounds:function(t,e){var i=new g(this._size).setCenter(0,0),n=this._style,r=e.stroke&&n.hasStroke()&&n.getStrokeWidth();return t&&(i=t._transformBounds(i)),r?i.expand(L._getStrokePadding(r,this._getStrokeMatrix(t,e))):i}},new function(){function t(t,e,i){var n=t._radius;if(!n.isZero())for(var r=t._size.divide(2),s=0;s<4;s++){var a=new c(1&s?1:-1,s>1?1:-1),o=a.multiply(r),h=o.subtract(a.multiply(n)),u=new g(o,h);if((i?u.expand(i):u).contains(e))return h}}function e(t,e,i,n){var r=t.divide(e);return(!n||r.quadrant===n)&&r.subtract(r.normalize()).multiply(e).divide(i).length<=1}return{_contains:function i(e){if("rectangle"===this._type){var n=t(this,e);return n?e.subtract(n).divide(this._radius).getLength()<=1:i.base.call(this,e)}return e.divide(this.size).getLength()<=.5},_hitTestSelf:function n(i,r,s,a){var o=!1,h=this._style,u=r.stroke&&h.hasStroke(),l=r.fill&&h.hasFill();if(u||l){var c=this._type,d=this._radius,f=u?h.getStrokeWidth()/2:0,_=r._tolerancePadding.add(L._getStrokePadding(f,!h.getStrokeScaling()&&a));if("rectangle"===c){var v=_.multiply(2),p=t(this,i,v);if(p)o=e(i.subtract(p),d,_,p.getQuadrant());else{var m=new g(this._size).setCenter(0,0),y=m.expand(v),w=m.expand(v.negate());o=y._containsPoint(i)&&!w._containsPoint(i)}}else o=e(i,d,_)}return o?new M(u?"stroke":"fill",this):n.base.apply(this,arguments)}}},{statics:new function(){function t(t,e,i,n,s){var a=new C(r.getNamed(s));return a._type=t,a._size=i,a._radius=n,a.translate(e)}return{Circle:function(){var e=c.readNamed(arguments,"center"),i=r.readNamed(arguments,"radius");return t("circle",e,new f(2*i),i,arguments)},Rectangle:function(){var e=g.readNamed(arguments,"rectangle"),i=f.min(f.readNamed(arguments,"radius"),e.getSize(!0).divide(2));return t("rectangle",e.getCenter(!0),e.getSize(!0),i,arguments)},Ellipse:function(){var e=C._readEllipse(arguments),i=e.radius;return t("ellipse",e.center,i.multiply(2),i,arguments)},_readEllipse:function(t){var e,i;if(r.hasNamed(t,"radius"))e=c.readNamed(t,"center"),i=f.readNamed(t,"radius");else{var n=g.readNamed(t,"rectangle");e=n.getCenter(!0),i=n.getSize(!0).divide(2)}return{center:e,radius:i}}}}}),S=w.extend({_class:"Raster",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!1,handle:!1},_serializeFields:{crossOrigin:null,source:null},initialize:function(t,i){if(!this._initialize(t,i!==e&&c.read(arguments,1))){var r="string"==typeof t?n.getElementById(t):t;r?this.setImage(r):this.setSource(t)}this._size||(this._size=new f,this._loaded=!1)},_equals:function(t){return this.getSource()===t.getSource()},copyContent:function(t){var e=t._image,i=t._canvas;if(e)this._setImage(e);else if(i){var n=Q.getCanvas(t._size);n.getContext("2d").drawImage(i,0,0),this._setImage(n)}this._crossOrigin=t._crossOrigin},getSize:function(){var t=this._size;return new _(t?t.width:0,t?t.height:0,this,"setSize")},setSize:function(){var t=f.read(arguments);if(!t.equals(this._size))if(t.width>0&&t.height>0){var e=this.getElement();this._setImage(Q.getCanvas(t)),e&&this.getContext(!0).drawImage(e,0,0,t.width,t.height)}else this._canvas&&Q.release(this._canvas),this._size=t.clone()},getWidth:function(){return this._size?this._size.width:0},setWidth:function(t){this.setSize(t,this.getHeight())},getHeight:function(){return this._size?this._size.height:0},setHeight:function(t){this.setSize(this.getWidth(),t)},getLoaded:function(){return this._loaded},isEmpty:function(){var t=this._size;return!t||0===t.width&&0===t.height},getResolution:function(){var t=this._matrix,e=new c(0,0).transform(t),i=new c(1,0).transform(t).subtract(e),n=new c(0,1).transform(t).subtract(e);return new f(72/i.getLength(),72/n.getLength())},getPpi:"#getResolution",getImage:function(){return this._image},setImage:function(t){function e(t){var e=i.getView(),n=t&&t.type||"load";e&&i.responds(n)&&(paper=e._scope,i.emit(n,new G(t)))}var i=this;this._setImage(t),this._loaded?setTimeout(e,0):t&&Z.add(t,{load:function(n){i._setImage(t),e(n)},error:e})},_setImage:function(t){this._canvas&&Q.release(this._canvas),t&&t.getContext?(this._image=null,this._canvas=t,this._loaded=!0):(this._image=t,this._canvas=null,this._loaded=!!(t&&t.src&&t.complete)),this._size=new f(t?t.naturalWidth||t.width:0,t?t.naturalHeight||t.height:0),this._context=null,this._changed(521)},getCanvas:function(){if(!this._canvas){var t=Q.getContext(this._size);try{this._image&&t.drawImage(this._image,0,0),this._canvas=t.canvas}catch(e){Q.release(t)}}return this._canvas},setCanvas:"#setImage",getContext:function(t){return this._context||(this._context=this.getCanvas().getContext("2d")),t&&(this._image=null,this._changed(513)),this._context},setContext:function(t){this._context=t},getSource:function(){var t=this._image;return t&&t.src||this.toDataURL()},setSource:function(t){var e=new i.Image,n=this._crossOrigin;n&&(e.crossOrigin=n),e.src=t,this.setImage(e)},getCrossOrigin:function(){var t=this._image;return t&&t.crossOrigin||this._crossOrigin||""},setCrossOrigin:function(t){this._crossOrigin=t;var e=this._image;e&&(e.crossOrigin=t)},getElement:function(){return this._canvas||this._loaded&&this._image}},{beans:!1,getSubCanvas:function(){var t=g.read(arguments),e=Q.getContext(t.getSize());return e.drawImage(this.getCanvas(),t.x,t.y,t.width,t.height,0,0,t.width,t.height),e.canvas},getSubRaster:function(){var t=g.read(arguments),e=new S(w.NO_INSERT);return e._setImage(this.getSubCanvas(t)),e.translate(t.getCenter().subtract(this.getSize().divide(2))),e._matrix.prepend(this._matrix),e.insertAbove(this),e},toDataURL:function(){var t=this._image,e=t&&t.src;if(/^data:/.test(e))return e;var i=this.getCanvas();return i?i.toDataURL.apply(i,arguments):null},drawImage:function(t){var e=c.read(arguments,1);this.getContext(!0).drawImage(t,e.x,e.y)},getAverageColor:function(t){var e,i;if(t?t instanceof A?(i=t,e=t.getBounds()):"object"==typeof t&&("width"in t?e=new g(t):"x"in t&&(e=new g(t.x-.5,t.y-.5,1,1))):e=this.getBounds(),!e)return null;var n=32,s=Math.min(e.width,n),a=Math.min(e.height,n),o=S._sampleContext;o?o.clearRect(0,0,n+1,n+1):o=S._sampleContext=Q.getContext(new f(n)),o.save();var h=(new p).scale(s/e.width,a/e.height).translate(-e.x,-e.y);h.applyToContext(o),i&&i.draw(o,new r({clip:!0,matrices:[h]})),this._matrix.applyToContext(o);var u=this.getElement(),l=this._size;u&&o.drawImage(u,-l.width/2,-l.height/2),o.restore();for(var c=o.getImageData(.5,.5,Math.ceil(s),Math.ceil(a)).data,d=[0,0,0],_=0,v=0,m=c.length;v<m;v+=4){var y=c[v+3];_+=y,y/=255,d[0]+=c[v]*y,d[1]+=c[v+1]*y,d[2]+=c[v+2]*y}for(var v=0;v<3;v++)d[v]/=_;return _?F.read(d):null},getPixel:function(){var t=c.read(arguments),e=this.getContext().getImageData(t.x,t.y,1,1).data;return new F("rgb",[e[0]/255,e[1]/255,e[2]/255],e[3]/255)},setPixel:function(){var t=c.read(arguments),e=F.read(arguments),i=e._convert("rgb"),n=e._alpha,r=this.getContext(!0),s=r.createImageData(1,1),a=s.data;a[0]=255*i[0],a[1]=255*i[1],a[2]=255*i[2],a[3]=null!=n?255*n:255,r.putImageData(s,t.x,t.y)},createImageData:function(){var t=f.read(arguments);return this.getContext().createImageData(t.width,t.height)},getImageData:function(){var t=g.read(arguments);return t.isEmpty()&&(t=new g(this._size)),this.getContext().getImageData(t.x,t.y,t.width,t.height)},setImageData:function(t){var e=c.read(arguments,1);this.getContext(!0).putImageData(t,e.x,e.y)},_getBounds:function(t,e){var i=new g(this._size).setCenter(0,0);return t?t._transformBounds(i):i},_hitTestSelf:function(t){if(this._contains(t)){var e=this;return new M("pixel",e,{offset:t.add(e._size.divide(2)).round(),color:{get:function(){return e.getPixel(this.offset)}}})}},_draw:function(t){var e=this.getElement();e&&(t.globalAlpha=this._opacity,t.drawImage(e,-this._size.width/2,-this._size.height/2))},_canComposite:function(){return!0}}),P=w.extend({_class:"SymbolItem",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!0},_serializeFields:{symbol:null},initialize:function(t,i){this._initialize(t,i!==e&&c.read(arguments,1))||this.setDefinition(t instanceof I?t:new I(t))},_equals:function(t){return this._definition===t._definition},copyContent:function(t){this.setDefinition(t._definition)},getDefinition:function(){return this._definition},setDefinition:function(t){this._definition=t,this._changed(9)},getSymbol:"#getDefinition",setSymbol:"#setDefinition",isEmpty:function(){return this._definition._item.isEmpty()},_getBounds:function(t,e){var i=this._definition._item;return i._getCachedBounds(i._matrix.prepended(t),e)},_hitTestSelf:function(t,e,i,n){var r=this._definition._item._hitTest(t,e,i);return r&&(r.item=this),r},_draw:function(t,e){this._definition._item.draw(t,e)}}),I=r.extend({_class:"SymbolDefinition",initialize:function(t,e){this._id=l.get(),this.project=paper.project,t&&this.setItem(t,e)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._class,this._item],t,!1,e)})},_changed:function(t){8&t&&w._clearBoundsCache(this),1&t&&this.project._changed(t)},getItem:function(){return this._item},setItem:function(t,e){t._symbol&&(t=t.clone()),this._item&&(this._item._symbol=null),this._item=t,t.remove(),t.setSelected(!1),e||t.setPosition(new c),t._symbol=this,this._changed(9)},getDefinition:"#getItem",setDefinition:"#setItem",place:function(t){return new P(this,t)},clone:function(){return new I(this._item.clone(!1))},equals:function(t){return t===this||t&&this._item.equals(t._item)||!1}}),M=r.extend({_class:"HitResult",initialize:function(t,e,i){this.type=t,this.item=e,i&&(i.enumerable=!0,this.inject(i))},statics:{getOptions:function(t){var e=t&&r.read(t);return r.set({type:null,tolerance:paper.settings.hitTolerance,fill:!e,stroke:!e,segments:!e,handles:!1,ends:!1,center:!1,bounds:!1,guides:!1,selected:!1},e)}}}),T=r.extend({_class:"Segment",beans:!0,_selection:0,initialize:function(t,i,n,r,s,a){var o,h,u,l,c=arguments.length;0===c||(1===c?t&&"point"in t?(o=t.point,h=t.handleIn,u=t.handleOut,l=t.selection):o=t:null==t||"object"==typeof t?(o=t,h=i,u=n,l=r):(o=t!==e?[t,i]:null,h=n!==e?[n,r]:null,u=s!==e?[s,a]:null)),new k(o,this,"_point"),new k(h,this,"_handleIn"),new k(u,this,"_handleOut"),l&&this.setSelection(l)},_serialize:function(t,e){var i=this._point,n=this._selection,s=n||this.hasHandles()?[i,this._handleIn,this._handleOut]:i;return n&&s.push(n),r.serialize(s,t,!0,e)},_changed:function(t){var e=this._path;if(e){var i,n=e._curves,r=this._index;n&&(t&&t!==this._point&&t!==this._handleIn||!(i=r>0?n[r-1]:e._closed?n[n.length-1]:null)||i._changed(),t&&t!==this._point&&t!==this._handleOut||!(i=n[r])||i._changed()),e._changed(25)}},getPoint:function(){return this._point},setPoint:function(){var t=c.read(arguments);this._point.set(t.x,t.y)},getHandleIn:function(){return this._handleIn},setHandleIn:function(){var t=c.read(arguments);this._handleIn.set(t.x,t.y)},getHandleOut:function(){return this._handleOut},setHandleOut:function(){var t=c.read(arguments);this._handleOut.set(t.x,t.y)},hasHandles:function(){return!this._handleIn.isZero()||!this._handleOut.isZero()},clearHandles:function(){this._handleIn.set(0,0),this._handleOut.set(0,0)},getSelection:function(){return this._selection},setSelection:function(t){var e=this._selection,i=this._path;this._selection=t=t||0,i&&t!==e&&(i._updateSelection(this,e,t),i._changed(129))},changeSelection:function(t,e){var i=this._selection;this.setSelection(e?i|t:i&~t)},isSelected:function(){return!!(7&this._selection)},setSelected:function(t){this.changeSelection(7,t)},getIndex:function(){return this._index!==e?this._index:null},getPath:function(){return this._path||null},getCurve:function(){var t=this._path,e=this._index;return t?(e>0&&!t._closed&&e===t._segments.length-1&&e--,t.getCurves()[e]||null):null},getLocation:function(){var t=this.getCurve();return t?new O(t,this===t._segment1?0:1):null},getNext:function(){var t=this._path&&this._path._segments;return t&&(t[this._index+1]||this._path._closed&&t[0])||null},smooth:function(t,i,n){var r=t||{},s=r.type,a=r.factor,o=this.getPrevious(),h=this.getNext(),u=(o||this)._point,l=this._point,d=(h||this)._point,f=u.getDistance(l),_=l.getDistance(d);if(s&&"catmull-rom"!==s){if("geometric"!==s)throw new Error("Smoothing method '"+s+"' not supported.");if(o&&h){var g=u.subtract(d),v=a===e?.4:a,p=v*f/(f+_);i||this.setHandleIn(g.multiply(p)),n||this.setHandleOut(g.multiply(p-v))}}else{var m=a===e?.5:a,y=Math.pow(f,m),w=y*y,x=Math.pow(_,m),b=x*x;if(!i&&o){var C=2*b+3*x*y+w,S=3*x*(x+y);this.setHandleIn(0!==S?new c((b*u._x+C*l._x-w*d._x)/S-l._x,(b*u._y+C*l._y-w*d._y)/S-l._y):new c)}if(!n&&h){var C=2*w+3*y*x+b,S=3*y*(y+x);this.setHandleOut(0!==S?new c((w*d._x+C*l._x-b*u._x)/S-l._x,(w*d._y+C*l._y-b*u._y)/S-l._y):new c)}}},getPrevious:function(){var t=this._path&&this._path._segments;return t&&(t[this._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._index},isLast:function(){var t=this._path;return t&&this._index===t._segments.length-1||!1},reverse:function(){var t=this._handleIn,e=this._handleOut,i=t._x,n=t._y;t.set(e._x,e._y),e.set(i,n)},reversed:function(){return new T(this._point,this._handleOut,this._handleIn)},remove:function(){return!!this._path&&!!this._path.removeSegment(this._index)},clone:function(){return new T(this._point,this._handleIn,this._handleOut)},equals:function(t){return t===this||t&&this._class===t._class&&this._point.equals(t._point)&&this._handleIn.equals(t._handleIn)&&this._handleOut.equals(t._handleOut)||!1},toString:function(){var t=["point: "+this._point];return this._handleIn.isZero()||t.push("handleIn: "+this._handleIn),this._handleOut.isZero()||t.push("handleOut: "+this._handleOut),"{ "+t.join(", ")+" }"},transform:function(t){this._transformCoordinates(t,new Array(6),!0),this._changed()},interpolate:function(t,e,i){var n=1-i,r=i,s=t._point,a=e._point,o=t._handleIn,h=e._handleIn,u=e._handleOut,l=t._handleOut;this._point.set(n*s._x+r*a._x,n*s._y+r*a._y,!0),this._handleIn.set(n*o._x+r*h._x,n*o._y+r*h._y,!0),this._handleOut.set(n*l._x+r*u._x,n*l._y+r*u._y,!0),this._changed()},_transformCoordinates:function(t,e,i){var n=this._point,r=i&&this._handleIn.isZero()?null:this._handleIn,s=i&&this._handleOut.isZero()?null:this._handleOut,a=n._x,o=n._y,h=2;return e[0]=a,e[1]=o,r&&(e[h++]=r._x+a,e[h++]=r._y+o),s&&(e[h++]=s._x+a,e[h++]=s._y+o),t&&(t._transformCoordinates(e,e,h/2),a=e[0],o=e[1],i?(n._x=a,n._y=o,h=2,r&&(r._x=e[h++]-a,r._y=e[h++]-o),s&&(s._x=e[h++]-a,s._y=e[h++]-o)):(r||(e[h++]=a,e[h++]=o),s||(e[h++]=a,e[h++]=o))),e}}),k=c.extend({initialize:function(t,i,n){var r,s,a;if(t)if((r=t[0])!==e)s=t[1];else{var o=t;(r=o.x)===e&&(o=c.read(arguments),r=o.x),s=o.y,a=o.selected}else r=s=0;this._x=r,this._y=s,this._owner=i,i[n]=this,a&&this.setSelected(!0)},set:function(t,e){return this._x=t,this._y=e,this._owner._changed(this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner._changed(this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner._changed(this)},isZero:function(){return u.isZero(this._x)&&u.isZero(this._y)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){var t=this._owner;return this===t._point?1:this===t._handleIn?2:this===t._handleOut?4:0}}),z=r.extend({_class:"Curve",initialize:function(t,e,i,n,r,s,a,o){var h,u,l,c,d,f,_=arguments.length;3===_?(this._path=t,h=e,u=i):0===_?(h=new T,u=new T):1===_?"segment1"in t?(h=new T(t.segment1),u=new T(t.segment2)):"point1"in t?(l=t.point1,d=t.handle1,f=t.handle2,c=t.point2):Array.isArray(t)&&(l=[t[0],t[1]],c=[t[6],t[7]],d=[t[2]-t[0],t[3]-t[1]],f=[t[4]-t[6],t[5]-t[7]]):2===_?(h=new T(t),u=new T(e)):4===_?(l=t,d=e,f=i,c=n):8===_&&(l=[t,e],c=[a,o],d=[i-t,n-e],f=[r-a,s-o]),this._segment1=h||new T(l,null,d),this._segment2=u||new T(c,f,null)},_serialize:function(t,e){return r.serialize(this.hasHandles()?[this.getPoint1(),this.getHandle1(),this.getHandle2(),this.getPoint2()]:[this.getPoint1(),this.getPoint2()],t,!0,e)},_changed:function(){this._length=this._bounds=e},clone:function(){return new z(this._segment1,this._segment2)},toString:function(){var t=["point1: "+this._segment1._point];return this._segment1._handleOut.isZero()||t.push("handle1: "+this._segment1._handleOut),this._segment2._handleIn.isZero()||t.push("handle2: "+this._segment2._handleIn),t.push("point2: "+this._segment2._point),"{ "+t.join(", ")+" }"},remove:function(){var t=!1;if(this._path){var e=this._segment2,i=e._handleOut;t=e.remove(),t&&this._segment1._handleOut.set(i.x,i.y)}return t},getPoint1:function(){return this._segment1._point},setPoint1:function(){var t=c.read(arguments);this._segment1._point.set(t.x,t.y)},getPoint2:function(){return this._segment2._point},setPoint2:function(){var t=c.read(arguments);this._segment2._point.set(t.x,t.y)},getHandle1:function(){return this._segment1._handleOut},setHandle1:function(){var t=c.read(arguments);this._segment1._handleOut.set(t.x,t.y)},getHandle2:function(){return this._segment2._handleIn},setHandle2:function(){var t=c.read(arguments);this._segment2._handleIn.set(t.x,t.y)},getSegment1:function(){return this._segment1},getSegment2:function(){return this._segment2},getPath:function(){return this._path},getIndex:function(){return this._segment1._index},getNext:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index+1]||this._path._closed&&t[0])||null},getPrevious:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._segment1._index},isLast:function(){var t=this._path;return t&&this._segment1._index===t._curves.length-1||!1},isSelected:function(){return this.getPoint1().isSelected()&&this.getHandle2().isSelected()&&this.getHandle2().isSelected()&&this.getPoint2().isSelected()},setSelected:function(t){this.getPoint1().setSelected(t),this.getHandle1().setSelected(t),this.getHandle2().setSelected(t),this.getPoint2().setSelected(t)},getValues:function(t){return z.getValues(this._segment1,this._segment2,t)},getPoints:function(){for(var t=this.getValues(),e=[],i=0;i<8;i+=2)e.push(new c(t[i],t[i+1]));return e},getLength:function(){return null==this._length&&(this._length=z.getLength(this.getValues(),0,1)),this._length},getArea:function(){return z.getArea(this.getValues())},getLine:function(){return new m(this._segment1._point,this._segment2._point)},getPart:function(t,e){return new z(z.getPart(this.getValues(),t,e))},getPartLength:function(t,e){return z.getLength(this.getValues(),t,e)},getIntersections:function(t){return z._getIntersections(this.getValues(),t&&t!==this?t.getValues():null,this,t,[],{})},divideAt:function(t){return this.divideAtTime(t&&t.curve===this?t.time:t)},divideAtTime:function(t,e){var i=4e-7,n=1-i,r=null;if(t>=i&&t<=n){var s=z.subdivide(this.getValues(),t),a=s[0],o=s[1],h=e||this.hasHandles(),u=this._segment1,l=this._segment2,d=this._path;h&&(u._handleOut.set(a[2]-a[0],a[3]-a[1]),l._handleIn.set(o[4]-o[6],o[5]-o[7]));var f=a[6],_=a[7],g=new T(new c(f,_),h&&new c(a[4]-f,a[5]-_),h&&new c(o[2]-f,o[3]-_));d?(d.insert(u._index+1,g),r=this.getNext()):(this._segment2=g,this._changed(),r=new z(g,l))}return r},splitAt:function(t){return this._path?this._path.splitAt(t):null},splitAtTime:function(t){return this.splitAt(this.getLocationAtTime(t))},divide:function(t,i){return this.divideAtTime(t===e?.5:i?t:this.getTimeAt(t))},split:function(t,i){return this.splitAtTime(t===e?.5:i?t:this.getTimeAt(t))},reversed:function(){return new z(this._segment2.reversed(),this._segment1.reversed())},clearHandles:function(){this._segment1._handleOut.set(0,0),this._segment2._handleIn.set(0,0)},statics:{getValues:function(t,e,i){var n=t._point,r=t._handleOut,s=e._handleIn,a=e._point,o=[n._x,n._y,n._x+r._x,n._y+r._y,a._x+s._x,a._y+s._y,a._x,a._y];return i&&i._transformCoordinates(o,o,4),o},subdivide:function(t,i){var n=t[0],r=t[1],s=t[2],a=t[3],o=t[4],h=t[5],u=t[6],l=t[7];i===e&&(i=.5);var c=1-i,d=c*n+i*s,f=c*r+i*a,_=c*s+i*o,g=c*a+i*h,v=c*o+i*u,p=c*h+i*l,m=c*d+i*_,y=c*f+i*g,w=c*_+i*v,x=c*g+i*p,b=c*m+i*w,C=c*y+i*x;return[[n,r,d,f,m,y,b,C],[b,C,w,x,v,p,u,l]]},solveCubic:function(t,e,i,n,r,s){var a=t[e],o=t[e+2],h=t[e+4],l=t[e+6],c=0;if(!(a<i&&l<i&&o<i&&h<i||a>i&&l>i&&o>i&&h>i)){var d=3*(o-a),f=3*(h-o)-d,_=l-a-d-f;c=u.solveCubic(_,f,d,a-i,n,r,s)}return c},getTimeOf:function(t,e){var i=new c(t[0],t[1]),n=new c(t[6],t[7]),r=1e-12,s=e.isClose(i,r)?0:e.isClose(n,r)?1:null;if(null!==s)return s;for(var a=[e.x,e.y],o=[],h=2e-7,u=0;u<2;u++)for(var l=z.solveCubic(t,u,a[u],o,0,1),d=0;d<l;d++)if(s=o[d],e.isClose(z.getPoint(t,s),h))return s;return e.isClose(i,h)?0:e.isClose(n,h)?1:null},getNearestTime:function(t,e){function i(i){if(i>=0&&i<=1){var n=e.getDistance(z.getPoint(t,i),!0);if(n<f)return f=n,_=i,!0}}if(z.isStraight(t)){var n=t[0],r=t[1],s=t[6],a=t[7],o=s-n,h=a-r,u=o*o+h*h;if(0===u)return 0;var l=((e.x-n)*o+(e.y-r)*h)/u;return l<1e-12?0:l>.999999999999?1:z.getTimeOf(t,new c(n+l*o,r+l*h))}for(var d=100,f=1/0,_=0,g=0;g<=d;g++)i(g/d);for(var v=1/(2*d);v>4e-7;)i(_-v)||i(_+v)||(v/=2);return _},getPart:function(t,e,i){var n=e>i;if(n){var r=e;e=i,i=r}return e>0&&(t=z.subdivide(t,e)[1]),i<1&&(t=z.subdivide(t,(i-e)/(1-e))[0]),n?[t[6],t[7],t[4],t[5],t[2],t[3],t[0],t[1]]:t},isFlatEnough:function(t,e){var i=t[0],n=t[1],r=t[2],s=t[3],a=t[4],o=t[5],h=t[6],u=t[7],l=3*r-2*i-h,c=3*s-2*n-u,d=3*a-2*h-i,f=3*o-2*u-n;return Math.max(l*l,d*d)+Math.max(c*c,f*f)<=16*e*e},getArea:function(t){var e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7];return 3*((h-i)*(n+s)-(o-e)*(r+a)+r*(e-s)-n*(i-a)+h*(s+e/3)-o*(a+i/3))/20},getBounds:function(t){for(var e=t.slice(0,2),i=e.slice(),n=[0,0],r=0;r<2;r++)z._addBounds(t[r],t[r+2],t[r+4],t[r+6],r,0,e,i,n);return new g(e[0],e[1],i[0]-e[0],i[1]-e[1])},_addBounds:function(t,e,i,n,r,s,a,o,h){function l(t,e){var i=t-e,n=t+e;i<a[r]&&(a[r]=i),n>o[r]&&(o[r]=n)}s/=2;var c=a[r]-s,d=o[r]+s;if(t<c||e<c||i<c||n<c||t>d||e>d||i>d||n>d)if(e<t!=e<n&&i<t!=i<n)l(t,s),l(n,s);else{var f=3*(e-i)-t+n,_=2*(t+i)-4*e,g=e-t,v=u.solveQuadratic(f,_,g,h),p=4e-7,m=1-p;l(n,0);for(var y=0;y<v;y++){var w=h[y],x=1-w;p<w&&w<m&&l(x*x*x*t+3*x*x*w*e+3*x*w*w*i+w*w*w*n,s)}}}}},r.each(["getBounds","getStrokeBounds","getHandleBounds"],function(t){this[t]=function(){this._bounds||(this._bounds={});var e=this._bounds[t];return e||(e=this._bounds[t]=L[t]([this._segment1,this._segment2],!1,this._path)),e.clone()}},{}),r.each({isStraight:function(t,e,i){if(e.isZero()&&i.isZero())return!0;var n=t.getVector(),r=2e-7;if(n.isZero())return!1;if(t.getDistance(e)<r&&t.getDistance(i)<r){var s=n.dot(n),a=n.dot(e)/s,o=n.dot(i)/s;return a>=0&&a<=1&&o<=0&&o>=-1}return!1},isLinear:function(t,e,i){var n=t.getVector().divide(3);return e.equals(n)&&i.negate().equals(n)}},function(t,e){this[e]=function(){var e=this._segment1,i=this._segment2;return t(new m(e._point,i._point),e._handleOut,i._handleIn)},this.statics[e]=function(e){var i=e[0],n=e[1],r=e[6],s=e[7];return t(new m(i,n,r,s),new c(e[2]-i,e[3]-n),new c(e[4]-r,e[5]-s))}},{statics:{},hasHandles:function(){return!this._segment1._handleOut.isZero()||!this._segment2._handleIn.isZero()},isCollinear:function(t){return t&&this.isStraight()&&t.isStraight()&&this.getLine().isCollinear(t.getLine())},isHorizontal:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).y)<1e-7},isVertical:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).x)<1e-7}}),{beans:!1,getLocationAt:function(t,e){return this.getLocationAtTime(e?t:this.getTimeAt(t))},getLocationAtTime:function(t){return null!=t&&t>=0&&t<=1?new O(this,t):null},getTimeAt:function(t,e){return z.getTimeAt(this.getValues(),t,e)},getParameterAt:"#getTimeAt",getOffsetAtTime:function(t){return this.getPartLength(0,t)},getLocationOf:function(){return this.getLocationAtTime(this.getTimeOf(c.read(arguments)))},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getTimeOf:function(){return z.getTimeOf(this.getValues(),c.read(arguments))},getParameterOf:"#getTimeOf",getNearestLocation:function(){var t=c.read(arguments),e=this.getValues(),i=z.getNearestTime(e,t),n=z.getPoint(e,i);return new O(this,i,n,null,t.getDistance(n))},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t}},new function(){var t=["getPoint","getTangent","getNormal","getWeightedTangent","getWeightedNormal","getCurvature"];return r.each(t,function(t){this[t+"At"]=function(e,i){var n=this.getValues();return z[t](n,i?e:z.getTimeAt(n,e))},this[t+"AtTime"]=function(e){return z[t](this.getValues(),e)}},{statics:{_evaluateMethods:t}})},new function(){function t(t){var e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7],u=9*(n-s)+3*(o-e),l=6*(e+s)-12*n,c=3*(n-e),d=9*(r-a)+3*(h-i),f=6*(i+a)-12*r,_=3*(r-i);return function(t){var e=(u*t+l)*t+c,i=(d*t+f)*t+_;return Math.sqrt(e*e+i*i)}}function i(t,e){return Math.max(2,Math.min(16,Math.ceil(32*Math.abs(e-t))))}function n(t,e,i,n){if(null==e||e<0||e>1)return null;var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],d=t[6],f=t[7],_=u.isZero;_(a-r)&&_(o-s)&&(a=r,o=s),_(h-d)&&_(l-f)&&(h=d,l=f);var g,v,p=3*(a-r),m=3*(h-a)-p,y=d-r-p-m,w=3*(o-s),x=3*(l-o)-w,b=f-s-w-x;if(0===i)g=0===e?r:1===e?d:((y*e+m)*e+p)*e+r,v=0===e?s:1===e?f:((b*e+x)*e+w)*e+s;else{var C=4e-7,S=1-C;if(e<C?(g=p,v=w):e>S?(g=3*(d-h),v=3*(f-l)):(g=(3*y*e+2*m)*e+p,v=(3*b*e+2*x)*e+w),n){0===g&&0===v&&(e<C||e>S)&&(g=h-a,v=l-o);var P=Math.sqrt(g*g+v*v);P&&(g/=P,v/=P)}if(3===i){var I=6*y*e+2*m,M=6*b*e+2*x,T=Math.pow(g*g+v*v,1.5);g=0!==T?(g*M-v*I)/T:0,v=0}}return 2===i?new c(v,(-g)):new c(g,v)}return{statics:{getLength:function(n,r,s,a){if(r===e&&(r=0),s===e&&(s=1),z.isStraight(n)){var o=n;s<1&&(o=z.subdivide(o,s)[0],r/=s),r>0&&(o=z.subdivide(o,r)[1]);var h=o[6]-o[0],l=o[7]-o[1];return Math.sqrt(h*h+l*l)}return u.integrate(a||t(n),r,s,i(r,s))},getTimeAt:function(n,r,s){function a(t){return p+=u.integrate(f,s,t,i(s,t)),s=t,p-r}if(s===e&&(s=r<0?1:0),0===r)return s;var o=Math.abs,h=1e-12,l=r>0,c=l?s:0,d=l?1:s,f=t(n),_=z.getLength(n,c,d,f),g=o(r)-_;if(o(g)<h)return l?d:c;if(g>h)return null;var v=r/_,p=0;return u.findRoot(a,f,s+v,c,d,32,1e-12)},getPoint:function(t,e){return n(t,e,0,!1)},getTangent:function(t,e){return n(t,e,1,!0)},getWeightedTangent:function(t,e){return n(t,e,1,!1)},getNormal:function(t,e){return n(t,e,2,!0)},getWeightedNormal:function(t,e){return n(t,e,2,!1)},getCurvature:function(t,e){return n(t,e,3,!1).x}}}},new function(){function t(t,e,i,n,r,s,a,o,h,u,l){var c=!l&&e.excludeStart,d=!l&&e.excludeEnd,f=4e-7,_=1-f;if(null==r&&(r=z.getTimeOf(i,s)),null!==r&&r>=(c?f:0)&&r<=(d?_:1)&&(null==h&&(h=z.getTimeOf(a,u)),null!==h&&h>=(d?f:0)&&h<=(c?_:1))){var g=e.renormalize;if(g){
+var v=g(r,h);r=v[0],h=v[1]}var p=new O(n,r,s||z.getPoint(i,r),l),m=new O(o,h,u||z.getPoint(a,h),l),y=p.getPath()===m.getPath()&&p.getIndex()>m.getIndex(),w=y?m:p,x=e.include;p._intersection=m,m._intersection=p,x&&!x(w)||O.insert(t,w,!0)}}function e(r,s,a,o,h,u,l,c,d,f,_,g,v){if(++g>=48||++v>4096)return v;var p,y,w=s[0],x=s[1],b=s[6],C=s[7],S=m.getSignedDistance,P=S(w,x,b,C,s[2],s[3]),I=S(w,x,b,C,s[4],s[5]),M=P*I>0?.75:4/9,T=M*Math.min(0,P,I),k=M*Math.max(0,P,I),O=S(w,x,b,C,r[0],r[1]),A=S(w,x,b,C,r[2],r[3]),L=S(w,x,b,C,r[4],r[5]),N=S(w,x,b,C,r[6],r[7]),B=i(O,A,L,N),E=B[0],D=B[1];if(0===P&&0===I&&0===O&&0===A&&0===L&&0===N||null==(p=n(E,D,T,k))||null==(y=n(E.reverse(),D.reverse(),T,k)))return v;var j=l+(c-l)*p,F=l+(c-l)*y;if(Math.max(f-d,F-j)<1e-9){var R=(j+F)/2,q=(d+f)/2;r=a.getValues(),s=o.getValues(),t(h,u,_?s:r,_?o:a,_?q:R,null,_?r:s,_?a:o,_?R:q,null)}else if(r=z.getPart(r,p,y),y-p>.8)if(F-j>f-d){var V=z.subdivide(r,.5),R=(j+F)/2;v=e(s,V[0],o,a,h,u,d,f,j,R,!_,g,v),v=e(s,V[1],o,a,h,u,d,f,R,F,!_,g,v)}else{var V=z.subdivide(s,.5),q=(d+f)/2;v=e(V[0],r,o,a,h,u,d,q,j,F,!_,g,v),v=e(V[1],r,o,a,h,u,q,f,j,F,!_,g,v)}else v=e(s,r,o,a,h,u,d,f,j,F,!_,g,v);return v}function i(t,e,i,n){var r,s=[0,t],a=[1/3,e],o=[2/3,i],h=[1,n],u=e-(2*t+n)/3,l=i-(t+2*n)/3;if(u*l<0)r=[[s,a,h],[s,o,h]];else{var c=u/l;r=[c>=2?[s,a,h]:c<=.5?[s,o,h]:[s,a,o,h],[s,h]]}return(u||l)<0?r.reverse():r}function n(t,e,i,n){return t[0][1]<i?r(t,!0,i):e[0][1]>n?r(e,!1,n):t[0][0]}function r(t,e,i){for(var n=t[0][0],r=t[0][1],s=1,a=t.length;s<a;s++){var o=t[s][0],h=t[s][1];if(e?h>=i:h<=i)return h===i?o:n+(i-r)*(o-n)/(h-r);n=o,r=h}return null}function s(e,i,n,r,s,a){for(var o=z.isStraight(e),h=o?i:e,l=o?e:i,c=l[0],d=l[1],f=l[6],_=l[7],g=f-c,v=_-d,p=Math.atan2(-v,g),m=Math.sin(p),y=Math.cos(p),w=[],x=0;x<8;x+=2){var b=h[x]-c,C=h[x+1]-d;w.push(b*y-C*m,b*m+C*y)}for(var S=[],P=z.solveCubic(w,1,0,S,0,1),x=0;x<P;x++){var I=S[x],M=z.getPoint(h,I),T=z.getTimeOf(l,M);if(null!==T){var k=z.getPoint(l,T),O=o?T:I,A=o?I:T;(!a.excludeEnd||A>u.CURVETIME_EPSILON)&&t(s,a,e,n,O,o?k:M,i,r,A,o?M:k)}}}function a(e,i,n,r,s,a){var o=m.intersect(e[0],e[1],e[6],e[7],i[0],i[1],i[6],i[7]);o&&t(s,a,e,n,null,o,i,r,null,o)}return{statics:{_getIntersections:function(i,n,r,o,h,u){if(!n)return z._getSelfIntersection(i,r,h,u);var l=2e-7,d=i[0],f=i[1],_=i[6],g=i[7],v=n[0],p=n[1],m=n[6],y=n[7],w=(3*i[2]+d)/4,x=(3*i[3]+f)/4,b=(3*i[4]+_)/4,C=(3*i[5]+g)/4,S=(3*n[2]+v)/4,P=(3*n[3]+p)/4,I=(3*n[4]+m)/4,M=(3*n[5]+y)/4,T=Math.min,k=Math.max;if(!(k(d,w,b,_)+l>T(v,S,I,m)&&T(d,w,b,_)-l<k(v,S,I,m)&&k(f,x,C,g)+l>T(p,P,M,y)&&T(f,x,C,g)-l<k(p,P,M,y)))return h;var O=z.getOverlaps(i,n);if(O){for(var A=0;A<2;A++){var L=O[A];t(h,u,i,r,L[0],null,n,o,L[1],null,!0)}return h}var N=z.isStraight(i),B=z.isStraight(n),E=N&&B,D=h.length;if((E?a:N||B?s:e)(i,n,r,o,h,u,0,1,0,1,0,0,0),E&&h.length>D)return h;var j=new c(d,f),F=new c(_,g),R=new c(v,p),q=new c(m,y);return j.isClose(R,l)&&t(h,u,i,r,0,j,n,o,0,R),!u.excludeStart&&j.isClose(q,l)&&t(h,u,i,r,0,j,n,o,1,q),!u.excludeEnd&&F.isClose(R,l)&&t(h,u,i,r,1,F,n,o,0,R),F.isClose(q,l)&&t(h,u,i,r,1,F,n,o,1,q),h},_getSelfIntersection:function(t,e,i,n){var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],d=t[6],f=t[7],_=new m(r,s,d,f,(!1)),g=_.getSide(new c(a,o),!0),v=_.getSide(new c(h,l),!0);if(g===v){var p=(r-h)*(o-f)+(a-d)*(l-s);if(p*g>0)return i}var y=d-3*h+3*a-r,w=h-2*a+r,x=a-r,b=f-3*l+3*o-s,C=l-2*o+s,S=o-s,P=b*x-y*S,I=b*w-y*C,M=C*x-w*S;if(P*P-4*I*M<0){var T,k=[],O=u.solveCubic(y*y+b*b,3*(y*w+b*C),2*(w*w+C*C)+y*x+b*S,w*x+C*S,k,0,1);if(O>0){for(var A=0,L=0;A<O;A++){var N=Math.abs(e.getCurvatureAtTime(k[A]));N>L&&(L=N,T=k[A])}var B=z.subdivide(t,T);n.excludeEnd=!0,n.renormalize=function(t,e){return[t*T,e*(1-T)+T]},z._getIntersections(B[0],B[1],e,e,i,n)}}return i},getOverlaps:function(t,e){function i(t){var e=t[6]-t[0],i=t[7]-t[1];return e*e+i*i}var n=Math.abs,r=4e-7,s=2e-7,a=z.isStraight(t),o=z.isStraight(e),h=a&&o,u=i(t)<i(e),l=u?e:t,d=u?t:e,f=new m(l[0],l[1],l[6],l[7]);if(f.getDistance(new c(d[0],d[1]))<s&&f.getDistance(new c(d[6],d[7]))<s)!h&&f.getDistance(new c(l[2],l[3]))<s&&f.getDistance(new c(l[4],l[5]))<s&&f.getDistance(new c(d[2],d[3]))<s&&f.getDistance(new c(d[4],d[5]))<s&&(a=o=h=!0);else if(h)return null;if(a^o)return null;for(var _=[t,e],g=[],v=0,p=0;v<2&&g.length<2;v+=0===p?0:1,p=1^p){var y=z.getTimeOf(_[1^v],new c(_[v][0===p?0:6],_[v][0===p?1:7]));if(null!=y){var w=0===v?[p,y]:[y,p];(0===g.length||n(w[0]-g[0][0])>r&&n(w[1]-g[0][1])>r)&&g.push(w)}if(1===v&&0===g.length)break}if(2!==g.length)g=null;else if(!h){var x=z.getPart(t,g[0][0],g[1][0]),b=z.getPart(e,g[0][1],g[1][1]);(n(b[2]-x[2])>s||n(b[3]-x[3])>s||n(b[4]-x[4])>s||n(b[5]-x[5])>s)&&(g=null)}return g}}}}),O=r.extend({_class:"CurveLocation",beans:!0,initialize:function(t,e,i,n,r){if(e>.9999996){var s=t.getNext();s&&(e=0,t=s)}this._setCurve(t),this._time=e,this._point=i||t.getPointAtTime(e),this._overlap=n,this._distance=r,this._intersection=this._next=this._previous=null},_setCurve:function(t){var e=t._path;this._path=e,this._version=e?e._version:0,this._curve=t,this._segment=null,this._segment1=t._segment1,this._segment2=t._segment2},_setSegment:function(t){this._setCurve(t.getCurve()),this._segment=t,this._time=t===this._segment1?0:1,this._point=t._point.clone()},getSegment:function(){var t=this.getCurve(),e=this._segment;if(!e){var i=this.getTime();0===i?e=t._segment1:1===i?e=t._segment2:null!=i&&(e=t.getPartLength(0,i)<t.getPartLength(i,1)?t._segment1:t._segment2),this._segment=e}return e},getCurve:function(){function t(t){var e=t&&t.getCurve();if(e&&null!=(i._time=e.getTimeOf(i._point)))return i._setCurve(e),i._segment=t,e}var e=this._path,i=this;return e&&e._version!==this._version&&(this._time=this._curve=this._offset=null),this._curve||t(this._segment)||t(this._segment1)||t(this._segment2.getPrevious())},getPath:function(){var t=this.getCurve();return t&&t._path},getIndex:function(){var t=this.getCurve();return t&&t.getIndex()},getTime:function(){var t=this.getCurve(),e=this._time;return t&&null==e?this._time=t.getTimeOf(this._point):e},getParameter:"#getTime",getPoint:function(){return this._point},getOffset:function(){var t=this._offset;if(null==t){t=0;var e=this.getPath(),i=this.getIndex();if(e&&null!=i)for(var n=e.getCurves(),r=0;r<i;r++)t+=n[r].getLength();this._offset=t+=this.getCurveOffset()}return t},getCurveOffset:function(){var t=this.getCurve(),e=this.getTime();return null!=e&&t&&t.getPartLength(0,e)},getIntersection:function(){return this._intersection},getDistance:function(){return this._distance},divide:function(){var t=this.getCurve(),e=null;return t&&(e=t.divideAtTime(this.getTime()),e&&this._setSegment(e._segment1)),e},split:function(){var t=this.getCurve();return t?t.splitAtTime(this.getTime()):null},equals:function(t,e){var i=this===t,n=2e-7;if(!i&&t instanceof O&&this.getPath()===t.getPath()&&this.getPoint().isClose(t.getPoint(),n)){var r=this.getCurve(),s=t.getCurve(),a=Math.abs,o=a((r.isLast()&&s.isFirst()?-1:r.getIndex())+this.getTime()-((s.isLast()&&r.isFirst()?-1:s.getIndex())+t.getTime()));i=(o<4e-7||(o=a(this.getOffset()-t.getOffset()))<n||a(this.getPath().getLength()-o)<n)&&(e||!this._intersection&&!t._intersection||this._intersection&&this._intersection.equals(t._intersection,!0))}return i},toString:function(){var t=[],e=this.getPoint(),i=h.instance;e&&t.push("point: "+e);var n=this.getIndex();null!=n&&t.push("index: "+n);var r=this.getTime();return null!=r&&t.push("time: "+i.number(r)),null!=this._distance&&t.push("distance: "+i.number(this._distance)),"{ "+t.join(", ")+" }"},isTouching:function(){var t=this._intersection;if(t&&this.getTangent().isCollinear(t.getTangent())){var e=this.getCurve(),i=t.getCurve();return!(e.isStraight()&&i.isStraight()&&e.getLine().intersect(i.getLine()))}return!1},isCrossing:function(){function t(t,e,i){return e<i?t>e&&t<i:t>e||t<i}var e=this._intersection;if(!e)return!1;var i=this.getTime(),n=e.getTime(),r=4e-7,s=1-r,a=i>r&&i<s,o=n>r&&n<s;if(a&&o)return!this.isTouching();var h=this.getCurve(),u=i<=r?h.getPrevious():h,l=e.getCurve(),c=n<=r?l.getPrevious():l;if(i>=s&&(h=h.getNext()),n>=s&&(l=l.getNext()),!(u&&h&&c&&l))return!1;var d=[];a||d.push(u.getLength(),h.getLength()),o||d.push(c.getLength(),l.getLength());var f=this.getPoint(),_=Math.min.apply(Math,d)/64,g=a?h.getTangentAtTime(i):h.getPointAt(_).subtract(f),v=a?g.negate():u.getPointAt(-_).subtract(f),p=o?l.getTangentAtTime(n):l.getPointAt(_).subtract(f),m=o?p.negate():c.getPointAt(-_).subtract(f),y=v.getAngle(),w=g.getAngle(),x=m.getAngle(),b=p.getAngle();return!!(a?t(y,x,b)^t(w,x,b)&&t(y,b,x)^t(w,b,x):t(x,y,w)^t(b,y,w)&&t(x,w,y)^t(b,w,y))},hasOverlap:function(){return!!this._overlap}},r.each(z._evaluateMethods,function(t){var e=t+"At";this[t]=function(){var t=this.getCurve(),i=this.getTime();return null!=i&&t&&t[e](i,!0)}},{preserve:!0}),new function(){function t(t,e,i){function n(i,n){for(var s=i+n;s>=-1&&s<=r;s+=n){var a=t[(s%r+r)%r];if(!e.getPoint().isClose(a.getPoint(),2e-7))break;if(e.equals(a))return a}return null}for(var r=t.length,s=0,a=r-1;s<=a;){var o,h=s+a>>>1,u=t[h];if(i&&(o=e.equals(u)?u:n(h,-1)||n(h,1)))return e._overlap&&(o._overlap=o._intersection._overlap=!0),o;var l=e.getPath(),c=u.getPath(),d=l===c?e.getIndex()+e.getTime()-(u.getIndex()+u.getTime()):l._id-c._id;d<0?a=h-1:s=h+1}return t.splice(s,0,e),e}return{statics:{insert:t,expand:function(e){for(var i=e.slice(),n=e.length-1;n>=0;n--)t(i,e[n]._intersection,!1);return i}}}}),A=w.extend({_class:"PathItem",_selectBounds:!1,_canScaleStroke:!0,initialize:function(){},statics:{create:function(t){var e=(t&&t.match(/m/gi)||[]).length>1||/z\s*\S+/i.test(t)?N:L;return new e(t)}},_asPathItem:function(){return this},setPathData:function(t){function e(t,e){var i=+n[t];return o&&(i+=h[e]),i}function i(t){return new c(e(t,"x"),e(t+1,"y"))}var n,r,s,a=t&&t.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/gi),o=!1,h=new c,u=new c;this.clear();for(var l=0,d=a&&a.length;l<d;l++){var _=a[l],g=_[0],v=g.toLowerCase();n=_.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);var p=n&&n.length;switch(o=g===v,"z"!==r||/[mz]/.test(v)||this.moveTo(h=u),v){case"m":case"l":for(var m="m"===v,y=0;y<p;y+=2)this[0===y&&m?"moveTo":"lineTo"](h=i(y));s=h,m&&(u=h);break;case"h":case"v":for(var w="h"===v?"x":"y",y=0;y<p;y++)h[w]=e(y,w),this.lineTo(h);s=h;break;case"c":for(var y=0;y<p;y+=6)this.cubicCurveTo(i(y),s=i(y+2),h=i(y+4));break;case"s":for(var y=0;y<p;y+=4)this.cubicCurveTo(/[cs]/.test(r)?h.multiply(2).subtract(s):h,s=i(y),h=i(y+2)),r=v;break;case"q":for(var y=0;y<p;y+=4)this.quadraticCurveTo(s=i(y),h=i(y+2));break;case"t":for(var y=0;y<p;y+=2)this.quadraticCurveTo(s=/[qt]/.test(r)?h.multiply(2).subtract(s):h,h=i(y)),r=v;break;case"a":for(var y=0;y<p;y+=7)this.arcTo(h=i(y+5),new f((+n[y]),(+n[y+1])),+n[y+2],+n[y+4],+n[y+3]);break;case"z":this.closePath(1e-12)}r=v}},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_contains:function(t){var e=t.isInside(this.getBounds({internal:!0,handle:!0}))&&this._getWinding(t);return!!("evenodd"===this.getFillRule()?1&e:e)},getIntersections:function(t,e,i,n){var r=this===t||!t,s=this._matrix._orNullIfIdentity(),a=r?s:(i||t._matrix)._orNullIfIdentity();if(!r&&!this.getBounds(s).touches(t.getBounds(a)))return[];for(var o,t,h=this.getCurves(),u=r?h:t.getCurves(),l=h.length,c=r?l:u.length,d=[],f=[],_=0;_<c;_++)d[_]=u[_].getValues(a);for(var _=0;_<l;_++){var g=h[_],v=r?d[_]:g.getValues(s),p=g.getPath();p!==t&&(t=p,o=[],f.push(o)),r&&z._getSelfIntersection(v,g,o,{include:e,excludeStart:1===l&&g.getPoint1().equals(g.getPoint2())});for(var m=r?_+1:0;m<c;m++){if(n&&o.length)return o;var y=u[m];z._getIntersections(v,d[m],g,y,o,{include:e,excludeStart:r&&g.getPrevious()===y,excludeEnd:r&&g.getNext()===y})}}o=[];for(var _=0,w=f.length;_<w;_++)o.push.apply(o,f[_]);return o},getCrossings:function(t){return this.getIntersections(t,function(t){return t._overlap||t.isCrossing()})},getNearestLocation:function(){for(var t=c.read(arguments),e=this.getCurves(),i=1/0,n=null,r=0,s=e.length;r<s;r++){var a=e[r].getNearestLocation(t);a._distance<i&&(i=a._distance,n=a)}return n},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t},interpolate:function(t,e,i){var n=!this._children,r=n?"_segments":"_children",s=t[r],a=e[r],o=this[r];if(!s||!a||s.length!==a.length)throw new Error("Invalid operands in interpolate() call: "+t+", "+e);var h=o.length,u=a.length;if(h<u)for(var l=n?T:L,c=h;c<u;c++)this.add(new l);else h>u&&this[n?"removeSegments":"removeChildren"](u,h);for(var c=0;c<u;c++)o[c].interpolate(s[c],a[c],i);n&&(this.setClosed(t._closed),this._changed(9))}}),L=A.extend({_class:"Path",_serializeFields:{segments:[],closed:!1},initialize:function(t){this._closed=!1,this._segments=[],this._version=0;var i=Array.isArray(t)?"object"==typeof t[0]?t:arguments:!t||t.size!==e||t.x===e&&t.point===e?null:arguments;i&&i.length>0?this.setSegments(i):(this._curves=e,this._segmentSelection=0,i||"string"!=typeof t||(this.setPathData(t),t=null)),this._initialize(!i&&t)},_equals:function(t){return this._closed===t._closed&&r.equals(this._segments,t._segments)},copyContent:function(t){this.setSegments(t._segments),this._closed=t._closed;var i=t._clockwise;i!==e&&(this._clockwise=i)},_changed:function gt(t){if(gt.base.call(this,t),8&t){if(this._length=this._area=this._clockwise=this._monoCurves=e,16&t)this._version++;else if(this._curves)for(var i=0,n=this._curves.length;i<n;i++)this._curves[i]._changed()}else 32&t&&(this._bounds=e)},getStyle:function(){var t=this._parent;return(t instanceof N?t:this)._style},getSegments:function(){return this._segments},setSegments:function(t){var i=this.isFullySelected();this._segments.length=0,this._segmentSelection=0,this._curves=e,t&&t.length>0&&this._add(T.readAll(t)),i&&this.setFullySelected(!0)},getFirstSegment:function(){return this._segments[0]},getLastSegment:function(){return this._segments[this._segments.length-1]},getCurves:function(){var t=this._curves,e=this._segments;if(!t){var i=this._countCurves();t=this._curves=new Array(i);for(var n=0;n<i;n++)t[n]=new z(this,e[n],e[n+1]||e[0])}return t},getFirstCurve:function(){return this.getCurves()[0]},getLastCurve:function(){var t=this.getCurves();return t[t.length-1]},isClosed:function(){return this._closed},setClosed:function(t){if(this._closed!=(t=!!t)){if(this._closed=t,this._curves){var e=this._curves.length=this._countCurves();t&&(this._curves[e-1]=new z(this,this._segments[e-1],this._segments[0]))}this._changed(25)}}},{beans:!0,getPathData:function(t,e){function i(e,i){e._transformCoordinates(t,g),n=g[0],r=g[1],v?(p.push("M"+_.pair(n,r)),v=!1):(o=g[2],u=g[3],o===n&&u===r&&l===s&&c===a?i||p.push("l"+_.pair(n-s,r-a)):p.push("c"+_.pair(l-s,c-a)+" "+_.pair(o-s,u-a)+" "+_.pair(n-s,r-a))),s=n,a=r,l=g[4],c=g[5]}var n,r,s,a,o,u,l,c,d=this._segments,f=d.length,_=new h(e),g=new Array(6),v=!0,p=[];if(0===f)return"";for(var m=0;m<f;m++)i(d[m]);return this._closed&&f>0&&(i(d[0],!0),p.push("z")),p.join("")},isEmpty:function(){return 0===this._segments.length},_transformContent:function(t){for(var e=this._segments,i=new Array(6),n=0,r=e.length;n<r;n++)e[n]._transformCoordinates(t,i,!0);return!0},_add:function(t,e){for(var i=this._segments,n=this._curves,r=t.length,s=null==e,e=s?i.length:e,a=0;a<r;a++){var o=t[a];o._path&&(o=t[a]=o.clone()),o._path=this,o._index=e+a,o._selection&&this._updateSelection(o,0,o._selection)}if(s)i.push.apply(i,t);else{i.splice.apply(i,[e,0].concat(t));for(var a=e+r,h=i.length;a<h;a++)i[a]._index=a}if(n){var u=this._countCurves(),l=e>0&&e+r-1===u?e-1:e,c=l,d=Math.min(l+r,u);t._curves&&(n.splice.apply(n,[l,0].concat(t._curves)),c+=t._curves.length);for(var a=c;a<d;a++)n.splice(a,0,new z(this,null,null));this._adjustCurves(l,d)}return this._changed(25),t},_adjustCurves:function(t,e){for(var i,n=this._segments,r=this._curves,s=t;s<e;s++)i=r[s],i._path=this,i._segment1=n[s],i._segment2=n[s+1]||n[0],i._changed();(i=r[this._closed&&0===t?n.length-1:t-1])&&(i._segment2=n[t]||n[0],i._changed()),(i=r[e])&&(i._segment1=n[e],i._changed())},_countCurves:function(){var t=this._segments.length;return!this._closed&&t>0?t-1:t},add:function(t){return arguments.length>1&&"number"!=typeof t?this._add(T.readAll(arguments)):this._add([T.read(arguments)])[0]},insert:function(t,e){return arguments.length>2&&"number"!=typeof e?this._add(T.readAll(arguments,1),t):this._add([T.read(arguments,1)],t)[0]},addSegment:function(){return this._add([T.read(arguments)])[0]},insertSegment:function(t){return this._add([T.read(arguments,1)],t)[0]},addSegments:function(t){return this._add(T.readAll(t))},insertSegments:function(t,e){return this._add(T.readAll(e),t)},removeSegment:function(t){return this.removeSegments(t,t+1)[0]||null},removeSegments:function(t,e,i){t=t||0,e=r.pick(e,this._segments.length);var n=this._segments,s=this._curves,a=n.length,o=n.splice(t,e-t),h=o.length;if(!h)return o;for(var u=0;u<h;u++){var l=o[u];l._selection&&this._updateSelection(l,l._selection,0),l._index=l._path=null}for(var u=t,c=n.length;u<c;u++)n[u]._index=u;if(s){for(var d=t>0&&e===a+(this._closed?1:0)?t-1:t,s=s.splice(d,h),u=s.length-1;u>=0;u--)s[u]._path=null;i&&(o._curves=s.slice(1)),this._adjustCurves(d,d)}return this._changed(25),o},clear:"#removeSegments",hasHandles:function(){for(var t=this._segments,e=0,i=t.length;e<i;e++)if(t[e].hasHandles())return!0;return!1},clearHandles:function(){for(var t=this._segments,e=0,i=t.length;e<i;e++)t[e].clearHandles()},getLength:function(){if(null==this._length){for(var t=this.getCurves(),e=0,i=0,n=t.length;i<n;i++)e+=t[i].getLength();this._length=e}return this._length},getArea:function(t){var i=t===e,n=this._area;if(!i||null==n){var r=this._segments,s=r.length,a=i?this._closed:t,o=s-1;n=0;for(var h=0,u=a?s:o;h<u;h++)n+=z.getArea(z.getValues(r[h],r[h<o?h+1:0]));i&&(this._area=n)}return n},isClockwise:function(){return this._clockwise!==e?this._clockwise:this.getArea()>=0},setClockwise:function(t){this.isClockwise()!=(t=!!t)&&this.reverse(),this._clockwise=t},isFullySelected:function(){var t=this._segments.length;return this.isSelected()&&t>0&&this._segmentSelection===7*t},setFullySelected:function(t){t&&this._selectSegments(!0),this.setSelected(t)},setSelection:function vt(t){1&t||this._selectSegments(!1),vt.base.call(this,t)},_selectSegments:function(t){var e=this._segments,i=e.length,n=t?7:0;this._segmentSelection=n*i;for(var r=0;r<i;r++)e[r]._selection=n},_updateSelection:function(t,e,i){t._selection=i;var n=this._segmentSelection+=i-e;n>0&&this.setSelected(!0)},splitAt:function(t){var e="number"==typeof t?this.getLocationAt(t):t,i=e&&e.index,n=e&&e.time,r=4e-7,s=1-r;n>=s&&(i++,n=0);var a=this.getCurves();if(i>=0&&i<a.length){n>=r&&a[i++].divideAtTime(n);var o,h=this.removeSegments(i,this._segments.length,!0);return this._closed?(this.setClosed(!1),o=this):(o=new L(w.NO_INSERT),o.insertAbove(this,!0),o.copyAttributes(this)),o._add(h,0),this.addSegment(h[0]),o}return null},split:function(t,i){var n,r=i===e?t:(n=this.getCurves()[t])&&n.getLocationAtTime(i);return null!=r?this.splitAt(r):null},join:function(t,e){var i=e||0;if(t&&t!==this){var n=t._segments,r=this.getLastSegment(),s=t.getLastSegment();if(!s)return this;r&&r._point.isClose(s._point,i)&&t.reverse();var a=t.getFirstSegment();if(r&&r._point.isClose(a._point,i))r.setHandleOut(a._handleOut),this._add(n.slice(1));else{var o=this.getFirstSegment();o&&o._point.isClose(a._point,i)&&t.reverse(),s=t.getLastSegment(),o&&o._point.isClose(s._point,i)?(o.setHandleIn(s._handleIn),this._add(n.slice(0,n.length-1),0)):this._add(n.slice())}t._closed&&this._add([n[0]]),t.remove()}var h=this.getFirstSegment(),u=this.getLastSegment();return h!==u&&h._point.isClose(u._point,i)&&(h.setHandleIn(u._handleIn),u.remove(),this.setClosed(!0)),this},reduce:function(t){for(var e=this.getCurves(),i=t&&t.simplify,n=i?2e-7:0,r=e.length-1;r>=0;r--){var s=e[r];!s.hasHandles()&&(s.getLength()<n||i&&s.isCollinear(s.getNext()))&&s.remove()}return this},reverse:function(){this._segments.reverse();for(var t=0,i=this._segments.length;t<i;t++){var n=this._segments[t],r=n._handleIn;n._handleIn=n._handleOut,n._handleOut=r,n._index=t}this._curves=null,this._clockwise!==e&&(this._clockwise=!this._clockwise),this._changed(9)},flatten:function(t){for(var e=new B(this,t||.25,256,(!0)),i=e.parts,n=i.length,r=[],s=0;s<n;s++)r.push(new T(i[s].curve.slice(0,2)));!this._closed&&n>0&&r.push(new T(i[n-1].curve.slice(6))),this.setSegments(r)},simplify:function(t){var e=new E(this).fit(t||2.5);return e&&this.setSegments(e),!!e},smooth:function(t){function i(t,e){var i=t&&t.index;if(null!=i){var r=t.path;if(r&&r!==n)throw new Error(t._class+" "+i+" of "+r+" is not part of "+n);e&&t instanceof z&&i++}else i="number"==typeof t?t:e;return Math.min(i<0&&h?i%o:i<0?i+o:i,o-1)}var n=this,r=t||{},s=r.type||"asymmetric",a=this._segments,o=a.length,h=this._closed,u=h&&r.from===e&&r.to===e,l=i(r.from,0),c=i(r.to,o-1);if(l>c)if(h)l-=o;else{var d=l;l=c,c=d}if(/^(?:asymmetric|continuous)$/.test(s)){var f="asymmetric"===s,_=Math.min,g=c-l+1,v=g-1,p=u?_(g,4):1,m=p,y=p,w=[];if(h||(m=_(1,l),y=_(1,o-c-1)),v+=m+y,v<=1)return;for(var x=0,b=l-m;x<=v;x++,b++)w[x]=a[(b<0?b+o:b)%o]._point;for(var C=w[0]._x+2*w[1]._x,S=w[0]._y+2*w[1]._y,P=2,I=v-1,M=[C],T=[S],k=[P],O=[],A=[],x=1;x<v;x++){var L=x<I,N=L?1:f?1:2,B=L?4:f?2:7,E=L?4:f?3:8,D=L?2:f?0:1,j=N/P;P=k[x]=B-j,C=M[x]=E*w[x]._x+D*w[x+1]._x-j*C,S=T[x]=E*w[x]._y+D*w[x+1]._y-j*S}O[I]=M[I]/k[I],A[I]=T[I]/k[I];for(var x=v-2;x>=0;x--)O[x]=(M[x]-O[x+1])/k[x],A[x]=(T[x]-A[x+1])/k[x];O[v]=(3*w[v]._x-O[I])/2,A[v]=(3*w[v]._y-A[I])/2;for(var x=m,F=v-y,b=l;x<=F;x++,b++){var R=a[b<0?b+o:b],q=R._point,V=O[x]-q._x,H=A[x]-q._y;(u||x<F)&&R.setHandleOut(V,H),(u||x>m)&&R.setHandleIn(-V,-H)}}else for(var x=l;x<=c;x++)a[x<0?x+o:x].smooth(r,!u&&x===l,!u&&x===c)},toShape:function(t){function i(t,e){var i=c[t],n=i.getNext(),r=c[e],s=r.getNext();return i._handleOut.isZero()&&n._handleIn.isZero()&&r._handleOut.isZero()&&s._handleIn.isZero()&&n._point.subtract(i._point).isCollinear(s._point.subtract(r._point))}function n(t){var e=c[t],i=e.getPrevious(),n=e.getNext();return i._handleOut.isZero()&&e._handleIn.isZero()&&e._handleOut.isZero()&&n._handleIn.isZero()&&e._point.subtract(i._point).isOrthogonal(n._point.subtract(e._point))}function r(t){var e=c[t],i=e.getNext(),n=e._handleOut,r=i._handleIn,s=.5522847498307936;if(n.isOrthogonal(r)){var a=e._point,o=i._point,h=new m(a,n,(!0)).intersect(new m(o,r,(!0)),!0);return h&&u.isZero(n.getLength()/h.subtract(a).getLength()-s)&&u.isZero(r.getLength()/h.subtract(o).getLength()-s)}return!1}function s(t,e){return c[t]._point.getDistance(c[e]._point)}if(!this._closed)return null;var a,o,h,l,c=this._segments;if(!this.hasHandles()&&4===c.length&&i(0,2)&&i(1,3)&&n(1)?(a=C.Rectangle,o=new f(s(0,3),s(0,1)),l=c[1]._point.add(c[2]._point).divide(2)):8===c.length&&r(0)&&r(2)&&r(4)&&r(6)&&i(1,5)&&i(3,7)?(a=C.Rectangle,o=new f(s(1,6),s(0,3)),h=o.subtract(new f(s(0,7),s(1,2))).divide(2),l=c[3]._point.add(c[4]._point).divide(2)):4===c.length&&r(0)&&r(1)&&r(2)&&r(3)&&(u.isZero(s(0,2)-s(1,3))?(a=C.Circle,h=s(0,2)/2):(a=C.Ellipse,h=new f(s(2,0)/2,s(3,1)/2)),l=c[1]._point),a){var d=this.getPosition(!0),_=new a({center:d,size:o,radius:h,insert:!1});return _.copyAttributes(this,!0),_._matrix.prepend(this._matrix),_.rotate(l.subtract(d).getAngle()+90),(t===e||t)&&_.insertAbove(this),_}return null},toPath:"#clone",_hitTestSelf:function(t,e,i,n){function r(e,i){return t.subtract(e).divide(i).length<=1}function s(t,i,n){if(!e.selected||i.isSelected()){var s=t._point;if(i!==s&&(i=i.add(s)),r(i,x))return new M(n,g,{segment:t,point:i})}}function a(t,i){return(i||e.segments)&&s(t,t._point,"segment")||!i&&e.handles&&(s(t,t._handleIn,"handle-in")||s(t,t._handleOut,"handle-out"))}function o(t){d.add(t)}function h(e){if(("round"!==u||"round"!==l)&&(d=new L({internal:!0,closed:!0}),y||e._index>0&&e._index<m-1?"round"!==u&&(e._handleIn.isZero()||e._handleOut.isZero())&&L._addBevelJoin(e,u,P,c,null,n,o,!0):"round"!==l&&L._addSquareCap(e,l,P,null,n,o,!0),!d.isEmpty())){var i;return d.contains(t)||(i=d.getNearestLocation(t))&&r(i.getPoint(),w)}return r(e._point,x)}var u,l,c,d,f,_,g=this,v=this.getStyle(),p=this._segments,m=p.length,y=this._closed,w=e._tolerancePadding,x=w,b=e.stroke&&v.hasStroke(),C=e.fill&&v.hasFill(),S=e.curves,P=b?v.getStrokeWidth()/2:C&&e.tolerance>0||S?0:null;if(null!==P&&(P>0?(u=v.getStrokeJoin(),l=v.getStrokeCap(),c=P*v.getMiterLimit(),x=x.add(L._getStrokePadding(P,n))):u=l="round"),!e.ends||e.segments||y){if(e.segments||e.handles)for(var I=0;I<m;I++)if(_=a(p[I]))return _}else if(_=a(p[0],!0)||a(p[m-1],!0))return _;if(null!==P){if(f=this.getNearestLocation(t)){var T=f.getTime();0===T||1===T&&m>1?h(f.getSegment())||(f=null):r(f.getPoint(),x)||(f=null)}if(!f&&"miter"===u&&m>1)for(var I=0;I<m;I++){var k=p[I];if(t.getDistance(k._point)<=c&&h(k)){f=k.getLocation();break}}}return!f&&C&&this._contains(t)||f&&!b&&!S?new M("fill",this):f?new M(b?"stroke":"curve",this,{location:f,point:f.getPoint()}):null}},r.each(z._evaluateMethods,function(t){this[t+"At"]=function(e){var i=this.getLocationAt(e);return i&&i[t]()}},{beans:!1,getLocationOf:function(){for(var t=c.read(arguments),e=this.getCurves(),i=0,n=e.length;i<n;i++){var r=e[i].getLocationOf(t);if(r)return r}return null},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getLocationAt:function(t){for(var e=this.getCurves(),i=0,n=0,r=e.length;n<r;n++){var s=i,a=e[n];if(i+=a.getLength(),i>t)return a.getLocationAt(t-s)}return e.length>0&&t<=this.getLength()?new O(e[e.length-1],1):null}}),new function(){function t(t,e,i,n){function r(e){var i=h[e],n=h[e+1];s==i&&a==n||(t.beginPath(),t.moveTo(s,a),t.lineTo(i,n),t.stroke(),t.beginPath(),t.arc(i,n,o,0,2*Math.PI,!0),t.fill())}for(var s,a,o=n/2,h=new Array(6),u=0,l=e.length;u<l;u++){var c=e[u],d=c._selection;if(c._transformCoordinates(i,h),s=h[0],a=h[1],2&d&&r(2),4&d&&r(4),t.fillRect(s-o,a-o,n,n),!(1&d)){var f=t.fillStyle;t.fillStyle="#ffffff",t.fillRect(s-o+1,a-o+1,n-2,n-2),t.fillStyle=f}}}function e(t,e,i){function n(e){if(i)e._transformCoordinates(i,_),r=_[0],s=_[1];else{var n=e._point;r=n._x,s=n._y}if(g)t.moveTo(r,s),g=!1;else{if(i)h=_[2],u=_[3];else{var d=e._handleIn;h=r+d._x,u=s+d._y}h===r&&u===s&&l===a&&c===o?t.lineTo(r,s):t.bezierCurveTo(l,c,h,u,r,s)}if(a=r,o=s,i)l=_[4],c=_[5];else{var d=e._handleOut;l=a+d._x,c=o+d._y}}for(var r,s,a,o,h,u,l,c,d=e._segments,f=d.length,_=new Array(6),g=!0,v=0;v<f;v++)n(d[v]);e._closed&&f>0&&n(d[0])}return{_draw:function(t,i,n,r){function s(t){return c[(t%d+d)%d]}var a=i.dontStart,o=i.dontFinish||i.clip,h=this.getStyle(),u=h.hasFill(),l=h.hasStroke(),c=h.getDashArray(),d=!paper.support.nativeDash&&l&&c&&c.length;if(a||t.beginPath(),(u||l&&!d||o)&&(e(t,this,r),this._closed&&t.closePath()),!o&&(u||l)&&(this._setStyles(t,i,n),u&&(t.fill(h.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),l)){if(d){a||t.beginPath();var f,_=new B(this,.25,32,(!1),r),g=_.length,v=-h.getDashOffset(),p=0;for(v%=g;v>0;)v-=s(p--)+s(p--);for(;v<g;)f=v+s(p++),(v>0||f>0)&&_.drawPart(t,Math.max(v,0),Math.max(f,0)),v=f+s(p++)}t.stroke()}},_drawSelected:function(i,n){i.beginPath(),e(i,this,n),i.stroke(),t(i,this._segments,n,paper.settings.handleSize)}}},new function(){function t(t){var e=t._segments;if(0===e.length)throw new Error("Use a moveTo() command first");return e[e.length-1]}return{moveTo:function(){var t=this._segments;1===t.length&&this.removeSegment(0),t.length||this._add([new T(c.read(arguments))])},moveBy:function(){throw new Error("moveBy() is unsupported on Path items.")},lineTo:function(){this._add([new T(c.read(arguments))])},cubicCurveTo:function(){var e=c.read(arguments),i=c.read(arguments),n=c.read(arguments),r=t(this);r.setHandleOut(e.subtract(r._point)),this._add([new T(n,i.subtract(n))])},quadraticCurveTo:function(){var e=c.read(arguments),i=c.read(arguments),n=t(this)._point;this.cubicCurveTo(e.add(n.subtract(e).multiply(1/3)),e.add(i.subtract(e).multiply(1/3)),i)},curveTo:function(){var e=c.read(arguments),i=c.read(arguments),n=r.pick(r.read(arguments),.5),s=1-n,a=t(this)._point,o=e.subtract(a.multiply(s*s)).subtract(i.multiply(n*n)).divide(2*n*s);if(o.isNaN())throw new Error("Cannot put a curve through points with parameter = "+n);this.quadraticCurveTo(o,i)},arcTo:function(){var e,i,n,s,a,o=t(this),h=o._point,l=c.read(arguments),d=r.peek(arguments),_=r.pick(d,!0);if("boolean"==typeof _)var g=h.add(l).divide(2),e=g.add(g.subtract(h).rotate(_?-90:90));else if(r.remain(arguments)<=2)e=l,l=c.read(arguments);else{var v=f.read(arguments),y=u.isZero;if(y(v.width)||y(v.height))return this.lineTo(l);var w=r.read(arguments),_=!!r.read(arguments),x=!!r.read(arguments),g=h.add(l).divide(2),b=h.subtract(g).rotate(-w),C=b.x,S=b.y,P=Math.abs,I=P(v.width),M=P(v.height),k=I*I,z=M*M,O=C*C,A=S*S,L=Math.sqrt(O/k+A/z);if(L>1&&(I*=L,M*=L,k=I*I,z=M*M),L=(k*z-k*A-z*O)/(k*A+z*O),P(L)<1e-12&&(L=0),L<0)throw new Error("Cannot create an arc with the given arguments");i=new c(I*S/M,-M*C/I).multiply((x===_?-1:1)*Math.sqrt(L)).rotate(w).add(g),a=(new p).translate(i).rotate(w).scale(I,M),s=a._inverseTransform(h),n=s.getDirectedAngle(a._inverseTransform(l)),!_&&n>0?n-=360:_&&n<0&&(n+=360)}if(e){var N=new m(h.add(e).divide(2),e.subtract(h).rotate(90),(!0)),B=new m(e.add(l).divide(2),l.subtract(e).rotate(90),(!0)),E=new m(h,l),D=E.getSide(e);if(i=N.intersect(B,!0),!i){if(!D)return this.lineTo(l);throw new Error("Cannot create an arc with the given arguments")}s=h.subtract(i),n=s.getDirectedAngle(l.subtract(i));var j=E.getSide(i);0===j?n=D*Math.abs(n):D===j&&(n+=n<0?360:-360)}for(var F=Math.abs(n),R=F>=360?4:Math.ceil(F/90),q=n/R,V=q*Math.PI/360,H=4/3*Math.sin(V)/(1+Math.cos(V)),Z=[],U=0;U<=R;U++){var b=l,W=null;if(U<R&&(W=s.rotate(90).multiply(H),a?(b=a._transformPoint(s),W=a._transformPoint(s.add(W)).subtract(b)):b=i.add(s)),0===U)o.setHandleOut(W);else{var G=s.rotate(-90).multiply(H);a&&(G=a._transformPoint(s.add(G)).subtract(b)),Z.push(new T(b,G,W))}s=s.rotate(q)}this._add(Z)},lineBy:function(){var e=c.read(arguments),i=t(this)._point;this.lineTo(i.add(e))},curveBy:function(){var e=c.read(arguments),i=c.read(arguments),n=r.read(arguments),s=t(this)._point;this.curveTo(s.add(e),s.add(i),n)},cubicCurveBy:function(){var e=c.read(arguments),i=c.read(arguments),n=c.read(arguments),r=t(this)._point;this.cubicCurveTo(r.add(e),r.add(i),r.add(n))},quadraticCurveBy:function(){var e=c.read(arguments),i=c.read(arguments),n=t(this)._point;this.quadraticCurveTo(n.add(e),n.add(i))},arcBy:function(){var e=t(this)._point,i=e.add(c.read(arguments)),n=r.pick(r.peek(arguments),!0);"boolean"==typeof n?this.arcTo(i,n):this.arcTo(i,e.add(c.read(arguments)))},closePath:function(t){this.setClosed(!0),this.join(this,t)}}},{_getBounds:function(t,e){var i=e.handle?"getHandleBounds":e.stroke?"getStrokeBounds":"getBounds";return L[i](this._segments,this._closed,this,t,e)},statics:{getBounds:function(t,e,i,n,r,s){function a(t){t._transformCoordinates(n,h);for(var e=0;e<2;e++)z._addBounds(u[e],u[e+4],h[e+2],h[e],e,s?s[e]:0,l,c,d);var i=u;u=h,h=i}var o=t[0];if(!o)return new g;for(var h=new Array(6),u=o._transformCoordinates(n,new Array(6)),l=u.slice(0,2),c=l.slice(),d=new Array(2),f=1,_=t.length;f<_;f++)a(t[f]);return e&&a(o),new g(l[0],l[1],c[0]-l[0],c[1]-l[1])},getStrokeBounds:function(t,e,i,n,r){function s(t){v=v.include(t)}function a(t){v=v.unite(x.setCenter(t._point.transform(n)))}function o(t,e){var i=t._handleIn,r=t._handleOut;"round"===e||!i.isZero()&&!r.isZero()&&i.isCollinear(r)?a(t):L._addBevelJoin(t,e,p,w,n,d,s)}function h(t,e){"round"===e?a(t):L._addSquareCap(t,e,p,n,d,s)}var u=i.getStyle(),l=u.hasStroke(),c=u.getStrokeWidth(),d=l&&i._getStrokeMatrix(n,r),_=l&&L._getStrokePadding(c,d),v=L.getBounds(t,e,i,n,r,_);if(!l)return v;for(var p=c/2,m=u.getStrokeJoin(),y=u.getStrokeCap(),w=p*u.getMiterLimit(),x=new g(new f(_)),b=t.length-(e?0:1),C=1;C<b;C++)o(t[C],m);return e?o(t[0],m):b>0&&(h(t[0],y),h(t[t.length-1],y)),v},_getStrokePadding:function(t,e){if(!e)return[t,t];
+var i=new c(t,0).transform(e),n=new c(0,t).transform(e),r=i.getAngleInRadians(),s=i.getLength(),a=n.getLength(),o=Math.sin(r),h=Math.cos(r),u=Math.tan(r),l=Math.atan2(a*u,s),d=Math.atan2(a,u*s);return[Math.abs(s*Math.cos(l)*h+a*Math.sin(l)*o),Math.abs(a*Math.sin(d)*h+s*Math.cos(d)*o)]},_addBevelJoin:function(t,e,i,n,r,s,a,o){var h=t.getCurve(),u=h.getPrevious(),l=h.getPointAtTime(0),d=u.getNormalAtTime(1),f=h.getNormalAtTime(0),_=d.getDirectedAngle(f)<0?-i:i;if(d.setLength(_),f.setLength(_),r&&r._transformPoint(l,l),s&&(s._transformPoint(d,d),s._transformPoint(f,f)),o&&(a(l),a(l.add(d))),"miter"===e){var g=new m(l.add(d),new c((-d.y),d.x),(!0)).intersect(new m(l.add(f),new c((-f.y),f.x),(!0)),!0);if(g&&l.getDistance(g)<=n&&(a(g),!o))return}o||a(l.add(d)),a(l.add(f))},_addSquareCap:function(t,e,i,n,r,s,a){var o=t._point,h=t.getLocation(),u=h.getNormal().multiply(i);n&&n._transformPoint(o,o),r&&r._transformPoint(u,u),a&&(s(o.subtract(u)),s(o.add(u))),"square"===e&&(o=o.add(u.rotate(0===h.getTime()?-90:90))),s(o.add(u)),s(o.subtract(u))},getHandleBounds:function(t,e,i,n,r){var s,a,o=i.getStyle(),h=r.stroke&&o.hasStroke();if(h){var u=i._getStrokeMatrix(n,r),l=o.getStrokeWidth()/2,c=l;"miter"===o.getStrokeJoin()&&(c=l*o.getMiterLimit()),"square"===o.getStrokeCap()&&(c=Math.max(c,l*Math.sqrt(2))),s=L._getStrokePadding(l,u),a=L._getStrokePadding(c,u)}for(var d=new Array(6),f=1/0,_=-f,v=f,p=_,m=0,y=t.length;m<y;m++){var w=t[m];w._transformCoordinates(n,d);for(var x=0;x<6;x+=2){var b=0===x?a:s,C=b?b[0]:0,S=b?b[1]:0,P=d[x],I=d[x+1],M=P-C,T=P+C,k=I-S,z=I+S;M<f&&(f=M),T>_&&(_=T),k<v&&(v=k),z>p&&(p=z)}}return new g(f,v,_-f,p-v)}}});L.inject({statics:new function(){function t(t,e,i){var n=r.getNamed(i),s=new L(n&&n.insert===!1&&w.NO_INSERT);return s._add(t),s._closed=e,s.set(n)}function e(e,i,r){for(var s=new Array(4),a=0;a<4;a++){var o=n[a];s[a]=new T(o._point.multiply(i).add(e),o._handleIn.multiply(i),o._handleOut.multiply(i))}return t(s,!0,r)}var i=.5522847498307936,n=[new T([-1,0],[0,i],[0,-i]),new T([0,-1],[-i,0],[i,0]),new T([1,0],[0,-i],[0,i]),new T([0,1],[i,0],[-i,0])];return{Line:function(){return t([new T(c.readNamed(arguments,"from")),new T(c.readNamed(arguments,"to"))],!1,arguments)},Circle:function(){var t=c.readNamed(arguments,"center"),i=r.readNamed(arguments,"radius");return e(t,new f(i),arguments)},Rectangle:function(){var e,n=g.readNamed(arguments,"rectangle"),r=f.readNamed(arguments,"radius",0,{readNull:!0}),s=n.getBottomLeft(!0),a=n.getTopLeft(!0),o=n.getTopRight(!0),h=n.getBottomRight(!0);if(!r||r.isZero())e=[new T(s),new T(a),new T(o),new T(h)];else{r=f.min(r,n.getSize(!0).divide(2));var u=r.width,l=r.height,c=u*i,d=l*i;e=[new T(s.add(u,0),null,[-c,0]),new T(s.subtract(0,l),[0,d]),new T(a.add(0,l),null,[0,-d]),new T(a.add(u,0),[-c,0],null),new T(o.subtract(u,0),null,[c,0]),new T(o.add(0,l),[0,-d],null),new T(h.subtract(0,l),null,[0,d]),new T(h.subtract(u,0),[c,0])]}return t(e,!0,arguments)},RoundRectangle:"#Rectangle",Ellipse:function(){var t=C._readEllipse(arguments);return e(t.center,t.radius,arguments)},Oval:"#Ellipse",Arc:function(){var t=c.readNamed(arguments,"from"),e=c.readNamed(arguments,"through"),i=c.readNamed(arguments,"to"),n=r.getNamed(arguments),s=new L(n&&n.insert===!1&&w.NO_INSERT);return s.moveTo(t),s.arcTo(e,i),s.set(n)},RegularPolygon:function(){for(var e=c.readNamed(arguments,"center"),i=r.readNamed(arguments,"sides"),n=r.readNamed(arguments,"radius"),s=360/i,a=i%3===0,o=new c(0,a?-n:n),h=a?-1:.5,u=new Array(i),l=0;l<i;l++)u[l]=new T(e.add(o.rotate((l+h)*s)));return t(u,!0,arguments)},Star:function(){for(var e=c.readNamed(arguments,"center"),i=2*r.readNamed(arguments,"points"),n=r.readNamed(arguments,"radius1"),s=r.readNamed(arguments,"radius2"),a=360/i,o=new c(0,(-1)),h=new Array(i),u=0;u<i;u++)h[u]=new T(e.add(o.rotate(a*u).multiply(u%2?s:n)));return t(h,!0,arguments)}}}});var N=A.extend({_class:"CompoundPath",_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||("string"==typeof t?this.setPathData(t):this.addChildren(Array.isArray(t)?t:arguments))},insertChildren:function pt(t,i,n){for(var r=i.length-1;r>=0;r--){var s=i[r];s instanceof N&&(i=i.slice(),i.splice.apply(i,[r,1].concat(s.removeChildren())),s.remove())}i=pt.base.call(this,t,i,n,L);for(var r=0,a=!n&&i&&i.length;r<a;r++){var s=i[r];s._clockwise===e&&s.setClockwise(0===s._index)}return i},reduce:function mt(t){for(var e=this._children,i=e.length-1;i>=0;i--){var n=e[i].reduce(t);n.isEmpty()&&n.remove()}if(0===e.length){var n=new L(w.NO_INSERT);return n.copyAttributes(this),n.insertAbove(this),this.remove(),n}return mt.base.call(this)},isClockwise:function(){var t=this.getFirstChild();return t&&t.isClockwise()},setClockwise:function(t){this.isClockwise()^!!t&&this.reverse()},getFirstSegment:function(){var t=this.getFirstChild();return t&&t.getFirstSegment()},getLastSegment:function(){var t=this.getLastChild();return t&&t.getLastSegment()},getCurves:function(){for(var t=this._children,e=[],i=0,n=t.length;i<n;i++)e.push.apply(e,t[i].getCurves());return e},getFirstCurve:function(){var t=this.getFirstChild();return t&&t.getFirstCurve()},getLastCurve:function(){var t=this.getLastChild();return t&&t.getFirstCurve()},getArea:function(){for(var t=this._children,e=0,i=0,n=t.length;i<n;i++)e+=t[i].getArea();return e}},{beans:!0,getPathData:function(t,e){for(var i=this._children,n=[],r=0,s=i.length;r<s;r++){var a=i[r],o=a._matrix;n.push(a.getPathData(t&&!o.isIdentity()?t.appended(o):t,e))}return n.join(" ")}},{_hitTestChildren:function yt(t,e,i){return yt.base.call(this,t,e["class"]===L||"path"===e.type?e:r.set({},e,{fill:!1}),i)},_draw:function(t,e,i,n){var r=this._children;if(0!==r.length){e=e.extend({dontStart:!0,dontFinish:!0}),t.beginPath();for(var s=0,a=r.length;s<a;s++)r[s].draw(t,e,n);if(!e.clip){this._setStyles(t,e,i);var o=this._style;o.hasFill()&&(t.fill(o.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),o.hasStroke()&&t.stroke()}}},_drawSelected:function(t,e,i){for(var n=this._children,r=0,s=n.length;r<s;r++){var a=n[r],o=a._matrix;i[a._id]||a._drawSelected(t,o.isIdentity()?e:e.appended(o))}}},new function(){function t(t,e){var i=t._children;if(e&&0===i.length)throw new Error("Use a moveTo() command first");return i[i.length-1]}return r.each(["lineTo","cubicCurveTo","quadraticCurveTo","curveTo","arcTo","lineBy","cubicCurveBy","quadraticCurveBy","curveBy","arcBy"],function(e){this[e]=function(){var i=t(this,!0);i[e].apply(i,arguments)}},{moveTo:function(){var e=t(this),i=e&&e.isEmpty()?e:new L(w.NO_INSERT);i!==e&&this.addChild(i),i.moveTo.apply(i,arguments)},moveBy:function(){var e=t(this,!0),i=e&&e.getLastSegment(),n=c.read(arguments);this.moveTo(i?n.add(i._point):n)},closePath:function(e){t(this,!0).closePath(e)}})},r.each(["reverse","flatten","simplify","smooth"],function(t){this[t]=function(e){for(var i,n=this._children,r=0,s=n.length;r<s;r++)i=n[r][t](e)||i;return i}},{}));A.inject(new function(){function t(t,e){var i=t.clone(!1).reduce({simplify:!0}).transform(null,!0,!0);return e?i.resolveCrossings():i}function e(t,e,i,n,r){var s=new t(w.NO_INSERT);return s.addChildren(e,!0),i&&(s=s.reduce({simplify:!0})),s.insertAbove(r&&n.isSibling(r)&&n.getIndex()<r.getIndex()?r:n),s.copyAttributes(n,!0),s}function i(i,r,s){function o(t){for(var e=0,i=t.length;e<i;e++){var n=t[e];g.push.apply(g,n._segments),v.push.apply(v,n._getMonoCurves()),n._overlapsOnly=n._validOverlapsOnly=!0}}var u=d[s];if(u[s]=!0,!i._children&&!i._closed)return n(i,r,u);var c=t(i,!0),f=r&&i!==r&&t(r,!0);f&&(u.subtract||u.exclude)^(f.isClockwise()^c.isClockwise())&&f.reverse();var _=a(O.expand(c.getCrossings(f))),g=[],v=[];o(c._children||[c]),f&&o(f._children||[f]);for(var p=0,m=_.length;p<m;p++)h(_[p]._segment,c,f,v,u);for(var p=0,m=g.length;p<m;p++){var y=g[p],w=y._intersection;if(null==y._winding&&h(y,c,f,v,u),!w||!w._overlap){var x=y._path;x._overlapsOnly=!1,u[y._winding]&&(x._validOverlapsOnly=!1)}}return e(N,l(g,u),!0,i,r)}function n(i,n,r){function s(t){if(o.contains(t.getPointAt(t.getLength()/2))^u)return l.unshift(t),!0}if(!n||!n._children&&!n._closed||!r.subtract&&!r.intersect)return null;for(var a=t(i,!1),o=t(n,!1),h=a.getCrossings(o),u=r.subtract,l=[],c=h.length-1;c>=0;c--){var d=h[c].split();d&&(s(d)&&d.getFirstSegment().setHandleIn(0,0),a.getLastSegment().setHandleOut(0,0))}return s(a),e(x,l,!1,i,n)}function s(t,e){for(var i=t;i;){if(i===e)return;i=i._previous}for(;t._next&&t._next!==e;)t=t._next;if(!t._next){for(;e._previous;)e=e._previous;t._next=e,e._previous=t}}function a(t,e){for(var i,n,r=e&&[],a=4e-7,o=1-a,h=!1,u=[],l=t.length-1;l>=0;l--){var c=t[l];if(e){if(!e(c))continue;r.unshift(c)}var d,f=c._curve,_=c._time,g=_;if(f!==i?h=!f.hasHandles():n>=a&&n<=o&&(_/=n),_<a)d=f._segment1;else if(_>o)d=f._segment2;else{var v=f.divideAtTime(_,!0);h&&u.push(f,v),d=v._segment1}c._setSegment(d);var p=d._intersection,m=c._intersection;if(p){s(p,m);for(var y=p;y;)s(y._intersection,p),y=y._next}else d._intersection=m;i=f,n=g}for(var l=0,w=u.length;l<w;l++)u[l].clearHandles();return r||t}function o(t,e,i){var n=2e-7,r=t.x,s=t.y,a=0,h=0,u=e.length,l=[],d=Math.abs;if(i){for(var f=-(1/0),_=1/0,g=s-n,v=s+n,p=0;p<u;p++)for(var m=e[p].values,y=z.solveCubic(m,0,r,l,0,1),w=y-1;w>=0;w--){var x=z.getPoint(m,l[w]).y;x<g&&x>f?f=x:x>v&&x<_&&(_=x)}f=(f+s)/2,_=(_+s)/2,f>-(1/0)&&(a=o(new c(r,f),e).winding),_<1/0&&(h=o(new c(r,_),e).winding)}else{for(var b,C,S=r-n,P=r+n,I=0,M=0,T=!1,p=0;p<u;p++){var k=e[p],O=k.winding,m=k.values,A=m[1],L=m[7];if(k.last&&(b=k.last.winding,C=k.last.values[6],T=!1),s>=A&&s<=L||s>=L&&s<=A)if(O){var N=s===A?m[0]:s===L?m[6]:1===z.solveCubic(m,1,s,l,0,1)?z.getPoint(m,l[0]).x:null;null!=N&&(N>=S&&N<=P?T=!0:s===A&&O===b||s===A&&(r-N)*(r-C)<0||(N<S?a+=O:N>P&&(h+=O))),b=O,C=m[6]}else(r-m[0])*(r-m[6])<=0&&(T=!0);T&&(p>=u-1||e[p+1].last)&&(I+=1,M-=1)}0===a&&0===h&&(a=I,h=M)}return{winding:Math.max(d(a),d(h)),contour:!a^!h}}function h(t,e,i,n,r){var s,a=[],h=t,u=0;do{var l=t.getCurve(),c=l.getLength();a.push({segment:t,curve:l,length:c}),u+=c,t=t.getNext()}while(t&&!t._intersection&&t!==h);for(var c=u/2,d=0,f=a.length;d<f;d++){var _=a[d],g=_.length;if(c<=g){var l=_.curve,v=l._path,p=v._parent,m=l.getTimeAt(c),y=l.getPointAtTime(m),w=Math.abs(l.getTangentAtTime(m).y)<1e-7;p instanceof N&&(v=p),s=r.subtract&&i&&(v===e&&i._getWinding(y,w)||v===i&&!e._getWinding(y,w))?{winding:0}:o(y,n,w);break}c-=g}for(var d=a.length-1;d>=0;d--){var x=a[d].segment;x._winding=s.winding,x._contour=s.contour}}function l(t,e){function i(t,i){return!(!t||t._visited||!(!e||e[t._winding]||!i&&e.unite&&t._contour))}function n(t){return t===a||t===o}function s(t,r){if(!t._next)return t;for(;t;){var s=t._segment,a=s.getNext(),o=a&&a._intersection;if(s!==r&&(n(s)||n(a)||!s._visited&&!a._visited&&(!e||i(s)&&(i(a)||o&&i(o._segment)))))return t;t=t._next}return null}for(var a,o,h=[],l=0,c=t.length;l<c;l++){var d,f=null,_=!1,g=t[l],v=g._intersection;if(!g._visited&&g._path._overlapsOnly){var p=g._path,m=v._segment._path,y=p._segments,x=m._segments;if(r.equals(y,x)){(e.unite||e.intersect)&&p.getArea()&&h.push(p.clone(!1));for(var b=0,C=y.length;b<C;b++)y[b]._visited=x[b]._visited=!0}}if(i(g,!0)&&(g._path._validOverlapsOnly||!v||!v._overlap)){for(a=o=null;;){v=v&&s(v,g)||v;var S=v&&v._segment;if(n(g)?_=!0:S&&(n(S)?(_=!0,g=S):i(S,i(g,!0))&&(e&&(e.intersect||e.subtract)&&(g._visited=!0),g=S)),_||g._visited){g._visited=!0;break}if(g._path._validOverlapsOnly&&!i(g))break;f||(f=new L(w.NO_INSERT),a=g,o=S);var P=g.getNext();f.add(new T(g._point,d,P&&g._handleOut)),g._visited=!0,g=P||g._path.getFirstSegment(),d=P&&P._handleIn,v=g._intersection}if(_)f.firstSegment.setHandleIn(d),f.setClosed(!0);else if(f){var I=f.getArea(!0);Math.abs(I)>=2e-7&&console.error("Boolean operation resulted in open path","segments =",f._segments.length,"length =",f.getLength(),"area=",I),f=null}f&&(f._segments.length>8||!u.isZero(f.getArea()))&&(h.push(f),f=null)}}return h}var d={unite:{1:!0},intersect:{2:!0},subtract:{1:!0},exclude:{1:!0}};return{_getWinding:function(t,e){return o(t,this._getMonoCurves(),e).winding},unite:function(t){return i(this,t,"unite")},intersect:function(t){return i(this,t,"intersect")},subtract:function(t){return i(this,t,"subtract")},exclude:function(t){return i(this,t,"exclude")},divide:function(t){return e(x,[this.subtract(t),this.intersect(t)],!0,this,t)},resolveCrossings:function(){function t(t){var e=t&&t._intersection;return e&&e._overlap}var e=this._children,i=e||[this],n=!1,s=!1,o=this.getIntersections(null,function(t){return t._overlap&&(n=!0)||t.isCrossing()&&(s=!0)});if(o=O.expand(o),n)for(var h=a(o,function(t){return t._overlap}),u=h.length-1;u>=0;u--){var c=h[u]._segment,d=c.getPrevious(),f=c.getNext();if(c._path&&t(d)&&t(f)){c.remove(),d._handleOut.set(0,0),f._handleIn.set(0,0);var _=d.getCurve();_.isStraight()&&0===_.getLength()&&d.remove()}}s&&(a(o,n&&function(t){var e=t.getCurve(),i=t._intersection._curve,n=t._segment;return!!(e&&i&&e._path&&i._path)||void(n&&(n._intersection=null))}),i=l(r.each(i,function(t){this.push.apply(this,t._segments)},[])));var g,v=i.length;if(v>1){i=i.slice().sort(function(t,e){return e.getBounds().getArea()-t.getBounds().getArea()});for(var p=i[0],m=[p],y={},x="nonzero"===this.getFillRule(),b=x&&r.each(i,function(t){this.push(t.isClockwise()?1:-1)},[]),u=1;u<v;u++){for(var C=i[u],S=C.getInteriorPoint(),P=!1,I=null,M=!1,T=u-1;T>=0&&!I;T--)if(i[T].contains(S)){if(x&&!P&&(b[u]+=b[T],b[u]&&b[T])){M=y[u]=!0;break}P=!0,I=!y[T]&&i[T]}M||(C.setClockwise(I?!I.isClockwise():p.isClockwise()),m.push(C))}i=m,v=m.length}return v>1&&e?(i!==e&&this.setChildren(i,!0),g=this):1!==v||e||(i[0]!==this&&this.setSegments(i[0].removeSegments()),g=this),g||(g=new N(w.NO_INSERT),g.addChildren(i,!0),g=g.reduce(),g.copyAttributes(this),this.replaceWith(g)),g}}}),L.inject({_getMonoCurves:function(){function t(t){var e=t[1],r=t[7],s=Math.abs((e-r)/(t[0]-t[6]))<2e-7?0:e>r?-1:1,a={values:t,winding:s};n.push(a),s&&(i=a)}function e(e){if(0!==z.getLength(e)){var i=e[1],n=e[3],r=e[5],s=e[7];if(z.isStraight(e)||i>=n==n>=r&&n>=r==r>=s)t(e);else{var a=3*(n-r)-i+s,o=2*(i+r)-4*n,h=n-i,l=4e-7,c=1-l,d=[],f=u.solveQuadratic(a,o,h,d,l,c);if(f<1)t(e);else{d.sort();var _=d[0],g=z.subdivide(e,_);t(g[0]),f>1&&(_=(d[1]-_)/(1-_),g=z.subdivide(g[1],_),t(g[0])),t(g[1])}}}}var i,n=this._monoCurves;if(!n){n=this._monoCurves=[];for(var r=this.getCurves(),s=this._segments,a=0,o=r.length;a<o;a++)e(r[a].getValues());if(!this._closed&&s.length>1){var h=s[s.length-1]._point,l=s[0]._point,c=h._x,d=h._y,f=l._x,_=l._y;e([c,d,c,d,f,_,f,_])}n.length>0&&(n[0].last=i)}return n},getInteriorPoint:function(){var t=this.getBounds(),e=t.getCenter(!0);if(!this.contains(e)){for(var i=this._getMonoCurves(),n=[],r=e.y,s=[],a=0,o=i.length;a<o;a++){var h=i[a].values;if(1===i[a].winding&&r>h[1]&&r<=h[7]||r>=h[7]&&r<h[1])for(var u=z.solveCubic(h,1,r,n,0,1),l=u-1;l>=0;l--)s.push(z.getPoint(h,n[l]).x)}s.sort(function(t,e){return t-e}),e.x=(s[0]+s[1])/2}return e}}),N.inject({_getMonoCurves:function(){for(var t=this._children,e=[],i=0,n=t.length;i<n;i++)e.push.apply(e,t[i]._getMonoCurves());return e}});var B=r.extend({_class:"PathIterator",initialize:function(t,e,i,n,r){function s(t,e){var i=z.getValues(t,e,r);h.push(i),a(i,t._index,0,1)}function a(t,i,r,s){if(!(s-r>c)||n&&z.isStraight(t)||z.isFlatEnough(t,e||.25)){var o=t[6]-t[0],h=t[7]-t[1],d=Math.sqrt(o*o+h*h);d>0&&(l+=d,u.push({offset:l,curve:t,index:i,time:s}))}else{var f=z.subdivide(t,.5),_=(r+s)/2;a(f[0],i,r,_),a(f[1],i,_,s)}}for(var o,h=[],u=[],l=0,c=1/(i||32),d=t._segments,f=d[0],_=1,g=d.length;_<g;_++)o=d[_],s(f,o),f=o;t._closed&&s(o,d[0]),this.curves=h,this.parts=u,this.length=l,this.index=0},_get:function(t){for(var e,i=this.index;e=i,!(0===i||this.parts[--i].offset<t););for(var n=this.parts.length;e<n;e++){var r=this.parts[e];if(r.offset>=t){this.index=e;var s=this.parts[e-1],a=s&&s.index===r.index?s.time:0,o=s?s.offset:0;return{index:r.index,time:a+(r.time-a)*(t-o)/(r.offset-o)}}}var r=this.parts[this.parts.length-1];return{index:r.index,time:1}},drawPart:function(t,e,i){for(var n=this._get(e),r=this._get(i),s=n.index,a=r.index;s<=a;s++){var o=z.getPart(this.curves[s],s===n.index?n.time:0,s===r.index?r.time:1);s===n.index&&t.moveTo(o[0],o[1]),t.bezierCurveTo.apply(t,o.slice(2))}}},r.each(z._evaluateMethods,function(t){this[t+"At"]=function(e){var i=this._get(e);return z[t](this.curves[i.index],i.time)}},{})),E=r.extend({initialize:function(t){for(var e,i=this.points=[],n=t._segments,r=t._closed,s=0,a=n.length;s<a;s++){var o=n[s].point;e&&e.equals(o)||i.push(e=o.clone())}r&&(i.unshift(i[i.length-1]),i.push(i[1])),this.closed=r},fit:function(t){var e=this.points,i=e.length,n=null;return i>0&&(n=[new T(e[0])],i>1&&(this.fitCubic(n,t,0,i-1,e[1].subtract(e[0]),e[i-2].subtract(e[i-1])),this.closed&&(n.shift(),n.pop()))),n},fitCubic:function(t,e,i,n,r,s){var a=this.points;if(n-i===1){var o=a[i],h=a[n],u=o.getDistance(h)/3;return void this.addCurve(t,[o,o.add(r.normalize(u)),h.add(s.normalize(u)),h])}for(var l,c=this.chordLengthParameterize(i,n),d=Math.max(e,e*e),f=!0,_=0;_<=4;_++){var g=this.generateBezier(i,n,c,r,s),v=this.findMaxError(i,n,g,c);if(v.error<e&&f)return void this.addCurve(t,g);if(l=v.index,v.error>=d)break;f=this.reparameterize(i,n,c,g),d=v.error}var p=a[l-1].subtract(a[l+1]);this.fitCubic(t,e,i,l,r,p),this.fitCubic(t,e,l,n,p.negate(),s)},addCurve:function(t,e){var i=t[t.length-1];i.setHandleOut(e[1].subtract(e[0])),t.push(new T(e[3],e[2].subtract(e[3])))},generateBezier:function(t,e,i,n,r){for(var s=1e-12,a=Math.abs,o=this.points,h=o[t],u=o[e],l=[[0,0],[0,0]],c=[0,0],d=0,f=e-t+1;d<f;d++){var _=i[d],g=1-_,v=3*_*g,p=g*g*g,m=v*g,y=v*_,w=_*_*_,x=n.normalize(m),b=r.normalize(y),C=o[t+d].subtract(h.multiply(p+m)).subtract(u.multiply(y+w));l[0][0]+=x.dot(x),l[0][1]+=x.dot(b),l[1][0]=l[0][1],l[1][1]+=b.dot(b),c[0]+=x.dot(C),c[1]+=b.dot(C)}var S,P,I=l[0][0]*l[1][1]-l[1][0]*l[0][1];if(a(I)>s){var M=l[0][0]*c[1]-l[1][0]*c[0],T=c[0]*l[1][1]-c[1]*l[0][1];S=T/I,P=M/I}else{var k=l[0][0]+l[0][1],z=l[1][0]+l[1][1];S=P=a(k)>s?c[0]/k:a(z)>s?c[1]/z:0}var O,A,L=u.getDistance(h),N=s*L;if(S<N||P<N)S=P=L/3;else{var B=u.subtract(h);O=n.normalize(S),A=r.normalize(P),O.dot(B)-A.dot(B)>L*L&&(S=P=L/3,O=A=null)}return[h,h.add(O||n.normalize(S)),u.add(A||r.normalize(P)),u]},reparameterize:function(t,e,i,n){for(var r=t;r<=e;r++)i[r-t]=this.findRoot(n,this.points[r],i[r-t]);for(var r=1,s=i.length;r<s;r++)if(i[r]<=i[r-1])return!1;return!0},findRoot:function(t,e,i){for(var n=[],r=[],s=0;s<=2;s++)n[s]=t[s+1].subtract(t[s]).multiply(3);for(var s=0;s<=1;s++)r[s]=n[s+1].subtract(n[s]).multiply(2);var a=this.evaluate(3,t,i),o=this.evaluate(2,n,i),h=this.evaluate(1,r,i),u=a.subtract(e),l=o.dot(o)+u.dot(h);return Math.abs(l)<1e-6?i:i-u.dot(o)/l},evaluate:function(t,e,i){for(var n=e.slice(),r=1;r<=t;r++)for(var s=0;s<=t-r;s++)n[s]=n[s].multiply(1-i).add(n[s+1].multiply(i));return n[0]},chordLengthParameterize:function(t,e){for(var i=[0],n=t+1;n<=e;n++)i[n-t]=i[n-t-1]+this.points[n].getDistance(this.points[n-1]);for(var n=1,r=e-t;n<=r;n++)i[n]/=i[r];return i},findMaxError:function(t,e,i,n){for(var r=Math.floor((e-t+1)/2),s=0,a=t+1;a<e;a++){var o=this.evaluate(3,i,n[a-t]),h=o.subtract(this.points[a]),u=h.x*h.x+h.y*h.y;u>=s&&(s=u,r=a)}return{error:s,index:r}}}),D=w.extend({_class:"TextItem",_applyMatrix:!1,_canApplyMatrix:!1,_serializeFields:{content:null},_boundsOptions:{stroke:!1,handle:!1},initialize:function(t){this._content="",this._lines=[];var i=t&&r.isPlainObject(t)&&t.x===e&&t.y===e;this._initialize(i&&t,!i&&c.read(arguments))},_equals:function(t){return this._content===t._content},copyContent:function(t){this.setContent(t._content)},getContent:function(){return this._content},setContent:function(t){this._content=""+t,this._lines=this._content.split(/\r\n|\n|\r/gm),this._changed(265)},isEmpty:function(){return!this._content},getCharacterStyle:"#getStyle",setCharacterStyle:"#setStyle",getParagraphStyle:"#getStyle",setParagraphStyle:"#setStyle"}),j=D.extend({_class:"PointText",initialize:function(){D.apply(this,arguments)},getPoint:function(){var t=this._matrix.getTranslation();return new d(t.x,t.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.translate(t.subtract(this._matrix.getTranslation()))},_draw:function(t,e,i){if(this._content){this._setStyles(t,e,i);var n=this._lines,r=this._style,s=r.hasFill(),a=r.hasStroke(),o=r.getLeading(),h=t.shadowColor;t.font=r.getFontStyle(),t.textAlign=r.getJustification();for(var u=0,l=n.length;u<l;u++){t.shadowColor=h;var c=n[u];s&&(t.fillText(c,0,0),t.shadowColor="rgba(0,0,0,0)"),a&&t.strokeText(c,0,0),t.translate(0,o)}}},_getBounds:function(t,e){var i=this._style,n=this._lines,r=n.length,s=i.getJustification(),a=i.getLeading(),o=this.getView().getTextWidth(i.getFontStyle(),n),h=0;"left"!==s&&(h-=o/("center"===s?2:1));var u=new g(h,r?-.75*a:0,o,r*a);return t?t._transformBounds(u,u):u}}),F=r.extend(new function(){function t(t){var n,r=t.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/);if(r){n=[0,0,0];for(var s=0;s<3;s++){var o=r[s+1];n[s]=parseInt(1==o.length?o+o:o,16)/255}}else if(r=t.match(/^rgba?\((.*)\)$/)){n=r[1].split(",");for(var s=0,h=n.length;s<h;s++){var o=+n[s];n[s]=s<3?o/255:o}}else if(i){var u=a[t];if(!u){e||(e=Q.getContext(1,1),e.globalCompositeOperation="copy"),e.fillStyle="rgba(0,0,0,0)",e.fillStyle=t,e.fillRect(0,0,1,1);var l=e.getImageData(0,0,1,1).data;u=a[t]=[l[0]/255,l[1]/255,l[2]/255]}n=u.slice()}else n=[0,0,0];return n}var e,n={gray:["gray"],rgb:["red","green","blue"],hsb:["hue","saturation","brightness"],hsl:["hue","saturation","lightness"],gradient:["gradient","origin","destination","highlight"]},s={},a={},o=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]],u={"rgb-hsb":function(t,e,i){var n=Math.max(t,e,i),r=Math.min(t,e,i),s=n-r,a=0===s?0:60*(n==t?(e-i)/s+(e<i?6:0):n==e?(i-t)/s+2:(t-e)/s+4);return[a,0===n?0:s/n,n]},"hsb-rgb":function(t,e,i){t=(t/60%6+6)%6;var n=Math.floor(t),r=t-n,n=o[n],s=[i,i*(1-e),i*(1-e*r),i*(1-e*(1-r))];return[s[n[0]],s[n[1]],s[n[2]]]},"rgb-hsl":function(t,e,i){var n=Math.max(t,e,i),r=Math.min(t,e,i),s=n-r,a=0===s,o=a?0:60*(n==t?(e-i)/s+(e<i?6:0):n==e?(i-t)/s+2:(t-e)/s+4),h=(n+r)/2,u=a?0:h<.5?s/(n+r):s/(2-n-r);return[o,u,h]},"hsl-rgb":function(t,e,i){if(t=(t/360%1+1)%1,0===e)return[i,i,i];for(var n=[t+1/3,t,t-1/3],r=i<.5?i*(1+e):i+e-i*e,s=2*i-r,a=[],o=0;o<3;o++){var h=n[o];h<0&&(h+=1),h>1&&(h-=1),a[o]=6*h<1?s+6*(r-s)*h:2*h<1?r:3*h<2?s+(r-s)*(2/3-h)*6:s}return a},"rgb-gray":function(t,e,i){return[.2989*t+.587*e+.114*i]},"gray-rgb":function(t){return[t,t,t]},"gray-hsb":function(t){return[0,0,t]},"gray-hsl":function(t){return[0,0,t]},"gradient-rgb":function(){return[]},"rgb-gradient":function(){return[]}};return r.each(n,function(t,e){s[e]=[],r.each(t,function(t,i){var a=r.capitalize(t),o=/^(hue|saturation)$/.test(t),h=s[e][i]="gradient"===t?function(t){var e=this._components[0];return t=R.read(Array.isArray(t)?t:arguments,0,{readNull:!0}),e!==t&&(e&&e._removeOwner(this),t&&t._addOwner(this)),t}:"gradient"===e?function(){return c.read(arguments,0,{readNull:"highlight"===t,clone:!0})}:function(t){return null==t||isNaN(t)?0:t};this["get"+a]=function(){return this._type===e||o&&/^hs[bl]$/.test(this._type)?this._components[i]:this._convert(e)[i]},this["set"+a]=function(t){this._type===e||o&&/^hs[bl]$/.test(this._type)||(this._components=this._convert(e),this._properties=n[e],this._type=e),this._components[i]=h.call(this,t),this._changed()}},this)},{_class:"Color",_readIndex:!0,initialize:function l(e){var i,r,a,o,h=Array.prototype.slice,u=arguments,c=this.__read,d=0;Array.isArray(e)&&(u=e,e=u[0]);var f=null!=e&&typeof e;if("string"===f&&e in n&&(i=e,e=u[1],Array.isArray(e)?(r=e,a=u[2]):(c&&(d=1),u=h.call(u,1),f=typeof e)),!r){if(o="number"===f?u:"object"===f&&null!=e.length?e:null){i||(i=o.length>=3?"rgb":"gray");var _=n[i].length;a=o[_],c&&(d+=o===arguments?_+(null!=a?1:0):1),o.length>_&&(o=h.call(o,0,_))}else if("string"===f)i="rgb",r=t(e),4===r.length&&(a=r[3],r.length--);else if("object"===f)if(e.constructor===l){if(i=e._type,r=e._components.slice(),a=e._alpha,"gradient"===i)for(var g=1,v=r.length;g<v;g++){var p=r[g];p&&(r[g]=p.clone())}}else if(e.constructor===R)i="gradient",o=u;else{i="hue"in e?"lightness"in e?"hsl":"hsb":"gradient"in e||"stops"in e||"radial"in e?"gradient":"gray"in e?"gray":"rgb";var m=n[i],y=s[i];this._components=r=[];for(var g=0,v=m.length;g<v;g++){var w=e[m[g]];null==w&&0===g&&"gradient"===i&&"stops"in e&&(w={stops:e.stops,radial:e.radial}),w=y[g].call(this,w),null!=w&&(r[g]=w)}a=e.alpha}c&&i&&(d=1)}if(this._type=i||"rgb",!r){this._components=r=[];for(var y=s[this._type],g=0,v=y.length;g<v;g++){var w=y[g].call(this,o&&o[g]);null!=w&&(r[g]=w)}}this._components=r,this._properties=n[this._type],this._alpha=a,c&&(this.__read=d)},_set:"#initialize",_serialize:function(t,e){var i=this.getComponents();return r.serialize(/^(gray|rgb)$/.test(this._type)?i:[this._type].concat(i),t,!0,e)},_changed:function(){this._canvasStyle=null,this._owner&&this._owner._changed(65)},_convert:function(t){var e;return this._type===t?this._components.slice():(e=u[this._type+"-"+t])?e.apply(this,this._components):u["rgb-"+t].apply(this,u[this._type+"-rgb"].apply(this,this._components))},convert:function(t){return new F(t,this._convert(t),this._alpha)},getType:function(){return this._type},setType:function(t){this._components=this._convert(t),this._properties=n[t],this._type=t},getComponents:function(){var t=this._components.slice();return null!=this._alpha&&t.push(this._alpha),t},getAlpha:function(){return null!=this._alpha?this._alpha:1},setAlpha:function(t){this._alpha=null==t?null:Math.min(Math.max(t,0),1),this._changed()},hasAlpha:function(){return null!=this._alpha},equals:function(t){var e=r.isPlainValue(t,!0)?F.read(arguments):t;return e===this||e&&this._class===e._class&&this._type===e._type&&this._alpha===e._alpha&&r.equals(this._components,e._components)||!1},toString:function(){for(var t=this._properties,e=[],i="gradient"===this._type,n=h.instance,r=0,s=t.length;r<s;r++){var a=this._components[r];null!=a&&e.push(t[r]+": "+(i?a:n.number(a)))}return null!=this._alpha&&e.push("alpha: "+n.number(this._alpha)),"{ "+e.join(", ")+" }"},toCSS:function(t){function e(t){return Math.round(255*(t<0?0:t>1?1:t))}var i=this._convert("rgb"),n=t||null==this._alpha?1:this._alpha;return i=[e(i[0]),e(i[1]),e(i[2])],n<1&&i.push(n<0?0:n),t?"#"+((1<<24)+(i[0]<<16)+(i[1]<<8)+i[2]).toString(16).slice(1):(4==i.length?"rgba(":"rgb(")+i.join(",")+")"},toCanvasStyle:function(t){if(this._canvasStyle)return this._canvasStyle;if("gradient"!==this._type)return this._canvasStyle=this.toCSS();var e,i=this._components,n=i[0],r=n._stops,s=i[1],a=i[2];if(n._radial){var o=a.getDistance(s),h=i[3];if(h){var u=h.subtract(s);u.getLength()>o&&(h=s.add(u.normalize(o-.1)))}var l=h||s;e=t.createRadialGradient(l.x,l.y,0,s.x,s.y,o)}else e=t.createLinearGradient(s.x,s.y,a.x,a.y);for(var c=0,d=r.length;c<d;c++){var f=r[c];e.addColorStop(f._offset||c/(d-1),f._color.toCanvasStyle())}return this._canvasStyle=e},transform:function(t){if("gradient"===this._type){for(var e=this._components,i=1,n=e.length;i<n;i++){var r=e[i];t._transformPoint(r,r,!0)}this._changed()}},statics:{_types:n,random:function(){var t=Math.random;return new F(t(),t(),t())}}})},new function(){var t={add:function(t,e){return t+e},subtract:function(t,e){return t-e},multiply:function(t,e){return t*e},divide:function(t,e){return t/e}};return r.each(t,function(t,e){this[e]=function(e){e=F.read(arguments);for(var i=this._type,n=this._components,r=e._convert(i),s=0,a=n.length;s<a;s++)r[s]=t(n[s],r[s]);return new F(i,r,null!=this._alpha?t(this._alpha,e.getAlpha()):null)}},{})}),R=r.extend({_class:"Gradient",initialize:function(t,e){this._id=l.get(),t&&this._set(t)&&(t=e=null),this._stops||this.setStops(t||["white","black"]),null==this._radial&&this.setRadial("string"==typeof e&&"radial"===e||e||!1)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._stops,this._radial],t,!0,e)})},_changed:function(){for(var t=0,e=this._owners&&this._owners.length;t<e;t++)this._owners[t]._changed()},_addOwner:function(t){this._owners||(this._owners=[]),this._owners.push(t)},_removeOwner:function(t){var i=this._owners?this._owners.indexOf(t):-1;i!=-1&&(this._owners.splice(i,1),0===this._owners.length&&(this._owners=e))},clone:function(){for(var t=[],e=0,i=this._stops.length;e<i;e++)t[e]=this._stops[e].clone();return new R(t,this._radial)},getStops:function(){return this._stops},setStops:function(t){if(t.length<2)throw new Error("Gradient stop list needs to contain at least two stops.");var i=this._stops;if(i)for(var n=0,r=i.length;n<r;n++)i[n]._owner=e;i=this._stops=q.readAll(t,0,{clone:!0});for(var n=0,r=i.length;n<r;n++)i[n]._owner=this;this._changed()},getRadial:function(){return this._radial},setRadial:function(t){this._radial=t,this._changed()},equals:function(t){if(t===this)return!0;if(t&&this._class===t._class){var e=this._stops,i=t._stops,n=e.length;if(n===i.length){for(var r=0;r<n;r++)if(!e[r].equals(i[r]))return!1;return!0}}return!1}}),q=r.extend({_class:"GradientStop",initialize:function(t,i){var n=t,r=i;"object"==typeof t&&i===e&&(Array.isArray(t)&&"number"!=typeof t[0]?(n=t[0],r=t[1]):("color"in t||"offset"in t||"rampPoint"in t)&&(n=t.color,r=t.offset||t.rampPoint||0)),this.setColor(n),this.setOffset(r)},clone:function(){return new q(this._color.clone(),this._offset)},_serialize:function(t,e){var i=this._color,n=this._offset;return r.serialize(null==n?[i]:[i,n],t,!0,e)},_changed:function(){this._owner&&this._owner._changed(65)},getOffset:function(){return this._offset},setOffset:function(t){this._offset=t,this._changed()},getRampPoint:"#getOffset",setRampPoint:"#setOffset",getColor:function(){return this._color},setColor:function(){var t=F.read(arguments,0,{clone:!0});t&&(t._owner=this),this._color=t,this._changed()},equals:function(t){return t===this||t&&this._class===t._class&&this._color.equals(t._color)&&this._offset==t._offset||!1}}),V=r.extend(new function(){var t={fillColor:null,fillRule:"nonzero",strokeColor:null,strokeWidth:1,strokeCap:"butt",strokeJoin:"miter",strokeScaling:!0,miterLimit:10,dashOffset:0,dashArray:[],shadowColor:null,shadowBlur:0,shadowOffset:new c,selectedColor:null},i=r.set({},t,{fontFamily:"sans-serif",fontWeight:"normal",fontSize:12,leading:null,justification:"left"}),n=r.set({},i,{fillColor:new F}),s={strokeWidth:97,strokeCap:97,strokeJoin:97,strokeScaling:105,miterLimit:97,fontFamily:9,fontWeight:9,fontSize:9,font:9,leading:9,justification:9},a={beans:!0},o={_class:"Style",beans:!0,initialize:function(e,r,s){this._values={},this._owner=r,this._project=r&&r._project||s||paper.project,this._defaults=!r||r instanceof x?i:r instanceof D?n:t,e&&this.set(e)}};return r.each(i,function(t,i){var n=/Color$/.test(i),h="shadowOffset"===i,u=r.capitalize(i),l=s[i],d="set"+u,f="get"+u;o[d]=function(t){var r=this._owner,s=r&&r._children;if(s&&s.length>0&&!(r instanceof N))for(var a=0,o=s.length;a<o;a++)s[a]._style[d](t);else if(i in this._defaults){var h=this._values[i];h!==t&&(n&&(h&&h._owner!==e&&(h._owner=e),t&&t.constructor===F&&(t._owner&&(t=t.clone()),t._owner=r)),this._values[i]=t,r&&r._changed(l||65))}},o[f]=function(t){var s,a=this._owner,o=a&&a._children;if(i in this._defaults&&(!o||0===o.length||t||a instanceof N)){var s=this._values[i];if(s===e)s=this._defaults[i],s&&s.clone&&(s=s.clone());else{var u=n?F:h?c:null;!u||s&&s.constructor===u||(this._values[i]=s=u.read([s],0,{readNull:!0,clone:!0}),s&&n&&(s._owner=a))}}else if(o)for(var l=0,d=o.length;l<d;l++){var _=o[l]._style[f]();if(0===l)s=_;else if(!r.equals(s,_))return e}return s},a[f]=function(t){return this._style[f](t)},a[d]=function(t){this._style[d](t)}}),r.each({Font:"FontFamily",WindingRule:"FillRule"},function(t,e){var i="get"+e,n="set"+e;o[i]=a[i]="#get"+t,o[n]=a[n]="#set"+t}),w.inject(a),o},{set:function(t){var e=t instanceof V,i=e?t._values:t;if(i)for(var n in i)if(n in this._defaults){var r=i[n];
+this[n]=r&&e&&r.clone?r.clone():r}},equals:function(t){return t===this||t&&this._class===t._class&&r.equals(this._values,t._values)||!1},hasFill:function(){var t=this.getFillColor();return!!t&&t.alpha>0},hasStroke:function(){var t=this.getStrokeColor();return!!t&&t.alpha>0&&this.getStrokeWidth()>0},hasShadow:function(){var t=this.getShadowColor();return!!t&&t.alpha>0&&(this.getShadowBlur()>0||!this.getShadowOffset().isZero())},getView:function(){return this._project._view},getFontStyle:function(){var t=this.getFontSize();return this.getFontWeight()+" "+t+(/[a-z]/i.test(t+"")?" ":"px ")+this.getFontFamily()},getFont:"#getFontFamily",setFont:"#setFontFamily",getLeading:function wt(){var t=wt.base.call(this),e=this.getFontSize();return/pt|em|%|px/.test(e)&&(e=this.getView().getPixelSize(e)),null!=t?t:1.2*e}}),H=new function(){function t(t,e,i,n){for(var r=["","webkit","moz","Moz","ms","o"],s=e[0].toUpperCase()+e.substring(1),a=0;a<6;a++){var o=r[a],h=o?o+s:e;if(h in t){if(!i)return t[h];t[h]=n;break}}}return{getStyles:function(t){var e=t&&9!==t.nodeType?t.ownerDocument:t,i=e&&e.defaultView;return i&&i.getComputedStyle(t,"")},getBounds:function(t,e){var i,n=t.ownerDocument,r=n.body,s=n.documentElement;try{i=t.getBoundingClientRect()}catch(a){i={left:0,top:0,width:0,height:0}}var o=i.left-(s.clientLeft||r.clientLeft||0),h=i.top-(s.clientTop||r.clientTop||0);if(!e){var u=n.defaultView;o+=u.pageXOffset||s.scrollLeft||r.scrollLeft,h+=u.pageYOffset||s.scrollTop||r.scrollTop}return new g(o,h,i.width,i.height)},getViewportBounds:function(t){var e=t.ownerDocument,i=e.defaultView,n=e.documentElement;return new g(0,0,i.innerWidth||n.clientWidth,i.innerHeight||n.clientHeight)},getOffset:function(t,e){return H.getBounds(t,e).getPoint()},getSize:function(t){return H.getBounds(t,!0).getSize()},isInvisible:function(t){return H.getSize(t).equals(new f(0,0))},isInView:function(t){return!H.isInvisible(t)&&H.getViewportBounds(t).intersects(H.getBounds(t,!0))},isInserted:function(t){return n.body.contains(t)},getPrefixed:function(e,i){return e&&t(e,i)},setPrefixed:function(e,i,n){if("object"==typeof i)for(var r in i)t(e,r,!0,i[r]);else t(e,i,!0,n)}}},Z={add:function(t,e){if(t)for(var i in e)for(var n=e[i],r=i.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.addEventListener(r[s],n,!1)},remove:function(t,e){if(t)for(var i in e)for(var n=e[i],r=i.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.removeEventListener(r[s],n,!1)},getPoint:function(t){var e=t.targetTouches?t.targetTouches.length?t.targetTouches[0]:t.changedTouches[0]:t;return new c(e.pageX||e.clientX+n.documentElement.scrollLeft,e.pageY||e.clientY+n.documentElement.scrollTop)},getTarget:function(t){return t.target||t.srcElement},getRelatedTarget:function(t){return t.relatedTarget||t.toElement},getOffset:function(t,e){return Z.getPoint(t).subtract(H.getOffset(e||Z.getTarget(t)))}};Z.requestAnimationFrame=new function(){function t(){var e=s;s=[];for(var i=0,a=e.length;i<a;i++)e[i]();r=n&&s.length,r&&n(t)}var e,n=H.getPrefixed(i,"requestAnimationFrame"),r=!1,s=[];return function(i){s.push(i),n?r||(n(t),r=!0):e||(e=setInterval(t,1e3/60))}};var U=r.extend(s,{_class:"View",initialize:function xt(t,e){function r(t){return e[t]||parseInt(e.getAttribute(t),10)}function s(){var t=H.getSize(e);return t.isNaN()||t.isZero()?new f(r("width"),r("height")):t}var o;if(i&&e){this._id=e.getAttribute("id"),null==this._id&&e.setAttribute("id",this._id="view-"+xt._id++),Z.add(e,this._viewEvents);var h="none";if(H.setPrefixed(e.style,{userDrag:h,userSelect:h,touchCallout:h,contentZooming:h,tapHighlightColor:"rgba(0,0,0,0)"}),a.hasAttribute(e,"resize")){var u=this;Z.add(i,this._windowEvents={resize:function(){u.setViewSize(s())}})}if(o=s(),a.hasAttribute(e,"stats")&&"undefined"!=typeof Stats){this._stats=new Stats;var l=this._stats.domElement,c=l.style,d=H.getOffset(e);c.position="absolute",c.left=d.x+"px",c.top=d.y+"px",n.body.appendChild(l)}}else o=new f(e),e=null;this._project=t,this._scope=t._scope,this._element=e,this._pixelRatio||(this._pixelRatio=i&&i.devicePixelRatio||1),this._setElementSize(o.width,o.height),this._viewSize=o,xt._views.push(this),xt._viewsById[this._id]=this,(this._matrix=new p)._owner=this,this._zoom=1,xt._focused||(xt._focused=this),this._frameItems={},this._frameItemCount=0,this._itemEvents={"native":{},virtual:{}},this._autoUpdate=!paper.agent.node,this._needsUpdate=!1},remove:function(){if(!this._project)return!1;U._focused===this&&(U._focused=null),U._views.splice(U._views.indexOf(this),1),delete U._viewsById[this._id];var t=this._project;return t._view===this&&(t._view=null),Z.remove(this._element,this._viewEvents),Z.remove(i,this._windowEvents),this._element=this._project=null,this.off("frame"),this._animate=!1,this._frameItems={},!0},_events:r.each(w._itemHandlers.concat(["onResize","onKeyDown","onKeyUp"]),function(t){this[t]={}},{onFrame:{install:function(){this.play()},uninstall:function(){this.pause()}}}),_animate:!1,_time:0,_count:0,getAutoUpdate:function(){return this._autoUpdate},setAutoUpdate:function(t){this._autoUpdate=t,t&&this.requestUpdate()},update:function(){},draw:function(){this.update()},requestUpdate:function(){if(!this._requested){var t=this;Z.requestAnimationFrame(function(){if(t._requested=!1,t._animate){t.requestUpdate();var e=t._element;H.getPrefixed(n,"hidden")&&"true"!==a.getAttribute(e,"keepalive")||!H.isInView(e)||t._handleFrame()}t._autoUpdate&&t.update()}),this._requested=!0}},play:function(){this._animate=!0,this.requestUpdate()},pause:function(){this._animate=!1},_handleFrame:function(){paper=this._scope;var t=Date.now()/1e3,e=this._last?t-this._last:0;this._last=t,this.emit("frame",new r({delta:e,time:this._time+=e,count:this._count++})),this._stats&&this._stats.update()},_animateItem:function(t,e){var i=this._frameItems;e?(i[t._id]={item:t,time:0,count:0},1===++this._frameItemCount&&this.on("frame",this._handleFrameItems)):(delete i[t._id],0===--this._frameItemCount&&this.off("frame",this._handleFrameItems))},_handleFrameItems:function(t){for(var e in this._frameItems){var i=this._frameItems[e];i.item.emit("frame",new r(t,{time:i.time+=t.delta,count:i.count++}))}},_changed:function(){this._project._changed(2049),this._bounds=null},getElement:function(){return this._element},getPixelRatio:function(){return this._pixelRatio},getResolution:function(){return 72*this._pixelRatio},getViewSize:function(){var t=this._viewSize;return new _(t.width,t.height,this,"setViewSize")},setViewSize:function(){var t=f.read(arguments),e=t.width,i=t.height,n=t.subtract(this._viewSize);n.isZero()||(this._setElementSize(e,i),this._viewSize.set(e,i),this.emit("resize",{size:t,delta:n}),this._changed(),this._autoUpdate&&this.requestUpdate())},_setElementSize:function(t,e){var i=this._element;i&&(i.width!==t&&(i.width=t),i.height!==e&&(i.height=e))},getBounds:function(){return this._bounds||(this._bounds=this._matrix.inverted()._transformBounds(new g(new c,this._viewSize))),this._bounds},getSize:function(){return this.getBounds().getSize()},getCenter:function(){return this.getBounds().getCenter()},setCenter:function(){var t=c.read(arguments);this.translate(this.getCenter().subtract(t))},getZoom:function(){return this._zoom},setZoom:function(t){this.transform((new p).scale(t/this._zoom,this.getCenter())),this._zoom=t},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},isVisible:function(){return H.isInView(this._element)},isInserted:function(){return H.isInserted(this._element)},getPixelSize:function(t){var e,i=this._element;if(i){var r=i.parentNode,s=n.createElement("div");s.style.fontSize=t,r.appendChild(s),e=parseFloat(H.getStyles(s).fontSize),r.removeChild(s)}else e=parseFloat(e);return e},getTextWidth:function(t,e){return 0}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var i=(e?r:c).read(arguments),n=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](i,n||this.getCenter(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t){this._matrix.append(t)},scrollBy:function(){this.translate(c.read(arguments).negate())}}),{projectToView:function(){return this._matrix._transformPoint(c.read(arguments))},viewToProject:function(){return this._matrix._inverseTransform(c.read(arguments))},getEventPoint:function(t){return this.viewToProject(Z.getOffset(t,this._element))}},{statics:{_views:[],_viewsById:{},_id:0,create:function(t,e){n&&"string"==typeof e&&(e=n.getElementById(e));var r=i?W:U;return new r(t,e)}}},new function(){function t(t){var e=Z.getTarget(t);return e.getAttribute&&U._viewsById[e.getAttribute("id")]}function e(){var t=U._focused;if(!t||!t.isVisible())for(var e=0,i=U._views.length;e<i;e++)if((t=U._views[e]).isVisible()){U._focused=h=t;break}}function r(t,e,i){t._handleMouseEvent("mousemove",e,i)}function s(t,e,i,n,r,s,a){function o(t,i){if(t.responds(i)){if(h||(h=new Y(i,n,r,e||t,s?r.subtract(s):null)),t.emit(i,h)&&(I=!0,h.prevented&&(M=!0),h.stopped))return u=!0}else{var a=T[i];if(a)return o(t,a)}}for(var h,u=!1;t&&t!==a&&!o(t,i);)t=t._parent;return u}function a(t,e,i,n,r,a){return t._project.removeOn(i),M=I=!1,b&&s(b,null,i,n,r,a)||e&&e!==b&&!e.isDescendant(b)&&s(e,null,T[i]||i,n,r,a,b)||s(t,b||e||t,i,n,r,a)}if(i){var o,h,u,l,c,d=!1,f=!1,_=i.navigator;_.pointerEnabled||_.msPointerEnabled?(u="pointerdown MSPointerDown",l="pointermove MSPointerMove",c="pointerup pointercancel MSPointerUp MSPointerCancel"):(u="touchstart",l="touchmove",c="touchend touchcancel","ontouchstart"in i&&_.userAgent.match(/mobile|tablet|ip(ad|hone|od)|android|silk/i)||(u+=" mousedown",l+=" mousemove",c+=" mouseup"));var g={},v={mouseout:function(t){var e=U._focused,i=Z.getRelatedTarget(t);if(e&&(!i||"HTML"===i.nodeName)){var n=Z.getOffset(t,e._element),s=n.x,a=Math.abs,o=a(s),h=1<<25,u=o-h;n.x=a(u)<o?u*(s<0?-1:1):s,r(e,t,e.viewToProject(n))}},scroll:e};g[u]=function(e){var i=U._focused=t(e);d||(d=!0,i._handleMouseEvent("mousedown",e))},v[l]=function(i){var n=U._focused;if(!f){var s=t(i);s?n!==s&&(n&&r(n,i),o||(o=n),n=U._focused=h=s):h&&h===n&&(o&&!o.isInserted()&&(o=null),n=U._focused=o,o=null,e())}n&&r(n,i)},v[u]=function(){f=!0},v[c]=function(t){var e=U._focused;e&&d&&e._handleMouseEvent("mouseup",t),f=d=!1},Z.add(n,v),Z.add(i,{load:e});var p,m,y,w,x,b,C,S,P,I=!1,M=!1,T={doubleclick:"click",mousedrag:"mousemove"},k=!1,z={mousedown:{mousedown:1,mousedrag:1,click:1,doubleclick:1},mouseup:{mouseup:1,mousedrag:1,click:1,doubleclick:1},mousemove:{mousedrag:1,mousemove:1,mouseenter:1,mouseleave:1}};return{_viewEvents:g,_handleMouseEvent:function(t,e,i){function n(t){return r.virtual[t]||l.responds(t)||u&&u.responds(t)}var r=this._itemEvents,o=r["native"][t],h="mousemove"===t,u=this._scope.tool,l=this;h&&d&&n("mousedrag")&&(t="mousedrag"),i||(i=this.getEventPoint(e));var c=this.getBounds().contains(i),f=o&&c&&l._project.hitTest(i,{tolerance:0,fill:!0,stroke:!0}),_=f&&f.item||null,g=!1,v={};v[t.substr(5)]=!0,o&&_!==x&&(x&&s(x,null,"mouseleave",e,i),_&&s(_,null,"mouseenter",e,i),x=_),k^c&&(s(this,null,c?"mouseenter":"mouseleave",e,i),p=c?this:null,g=!0),!c&&!v.drag||i.equals(y)||(a(this,_,h?t:"mousemove",e,i,y),g=!0),k=c,(v.down&&c||v.up&&m)&&(a(this,_,t,e,i,m),v.down?(P=_===C&&Date.now()-S<300,w=C=_,b=!M&&_,m=i):v.up&&(M||_!==w||(S=Date.now(),a(this,_,P?"doubleclick":"click",e,i,m),P=!1),w=b=null),k=!1,g=!0),y=i,g&&u&&(I=u._handleMouseEvent(t,e,i,v)||I),(I&&!v.move||v.down&&n("mouseup"))&&e.preventDefault()},_handleKeyEvent:function(t,e,i,n){function r(r){r.responds(t)&&(paper=a,r.emit(t,s=s||new J(t,e,i,n)))}var s,a=this._scope,o=a.tool;this.isVisible()&&(r(this),o&&o.responds(t)&&r(o))},_countItemEvent:function(t,e){var i=this._itemEvents,n=i["native"],r=i.virtual;for(var s in z)n[s]=(n[s]||0)+(z[s][t]||0)*e;r[t]=(r[t]||0)+e},statics:{updateFocus:e}}}}),W=U.extend({_class:"CanvasView",initialize:function(t,e){if(!(e instanceof i.HTMLCanvasElement)){var n=f.read(arguments,1);if(n.isZero())throw new Error("Cannot create CanvasView with the provided argument: "+[].slice.call(arguments,1));e=Q.getCanvas(n)}var r=this._context=e.getContext("2d");if(r.save(),this._pixelRatio=1,!/^off|false$/.test(a.getAttribute(e,"hidpi"))){var s=i.devicePixelRatio||1,o=H.getPrefixed(r,"backingStorePixelRatio")||1;this._pixelRatio=s/o}U.call(this,t,e),this._needsUpdate=!0},remove:function bt(){return this._context.restore(),bt.base.call(this)},_setElementSize:function Ct(t,e){var i=this._pixelRatio;if(Ct.base.call(this,t*i,e*i),1!==i){var n=this._element,r=this._context;if(!a.hasAttribute(n,"resize")){var s=n.style;s.width=t+"px",s.height=e+"px"}r.restore(),r.save(),r.scale(i,i)}},getPixelSize:function St(t){var e,i=paper.agent;if(i&&i.firefox)e=St.base.call(this,t);else{var n=this._context,r=n.font;n.font=t+" serif",e=parseFloat(n.font),n.font=r}return e},getTextWidth:function(t,e){var i=this._context,n=i.font,r=0;i.font=t;for(var s=0,a=e.length;s<a;s++)r=Math.max(r,i.measureText(e[s]).width);return i.font=n,r},update:function(){if(!this._needsUpdate)return!1;var t=this._project,e=this._context,i=this._viewSize;return e.clearRect(0,0,i.width+1,i.height+1),t&&t.draw(e,this._matrix,this._pixelRatio),this._needsUpdate=!1,!0}}),G=r.extend({_class:"Event",initialize:function(t){this.event=t,this.type=t&&t.type},prevented:!1,stopped:!1,preventDefault:function(){this.prevented=!0,this.event.preventDefault()},stopPropagation:function(){this.stopped=!0,this.event.stopPropagation()},stop:function(){this.stopPropagation(),this.preventDefault()},getTimeStamp:function(){return this.event.timeStamp},getModifiers:function(){return X.modifiers}}),J=G.extend({_class:"KeyEvent",initialize:function(t,e,i,n){this.type=t,this.event=e,this.key=i,this.character=n},toString:function(){return"{ type: '"+this.type+"', key: '"+this.key+"', character: '"+this.character+"', modifiers: "+this.getModifiers()+" }"}}),X=new function(){function t(t){var e=t.key||t.keyIdentifier;return e=/^U\+/.test(e)?String.fromCharCode(parseInt(e.substr(2),16)):/^Arrow[A-Z]/.test(e)?e.substr(5):"Unidentified"===e?String.fromCharCode(t.keyCode):e,o[e]||(e.length>1?r.hyphenate(e):e.toLowerCase())}function e(t,i,n,a){var o,h=U._focused;if(u[i]=t,t?l[i]=n:delete l[i],i.length>1&&(o=r.camelize(i))in c){c[o]=t;var d=paper&&paper.agent;if("meta"===o&&d&&d.mac)if(t)s={};else{for(var f in s)f in l&&e(!1,f,s[f],a);s=null}}else t&&s&&(s[i]=n);h&&h._handleKeyEvent(t?"keydown":"keyup",a,i,n)}var s,a,o={"\t":"tab"," ":"space","\b":"backspace","\x7f":"delete",Spacebar:"space",Del:"delete",Win:"meta",Esc:"escape"},h={tab:"\t",space:" ",enter:"\r"},u={},l={},c=new r({shift:!1,control:!1,alt:!1,meta:!1,capsLock:!1,space:!1}).inject({option:{get:function(){return this.alt}},command:{get:function(){var t=paper&&paper.agent;return t&&t.mac?this.meta:this.control}}});return Z.add(n,{keydown:function(i){var n=t(i),r=paper&&paper.agent;n.length>1||r&&r.chrome&&(i.altKey||r.mac&&i.metaKey||!r.mac&&i.ctrlKey)?e(!0,n,h[n]||(n.length>1?"":n),i):a=n},keypress:function(i){if(a){var n=t(i),r=i.charCode,s=r>=32?String.fromCharCode(r):n.length>1?"":n;n!==a&&(n=s.toLowerCase()),e(!0,n,s,i),a=null}},keyup:function(i){var n=t(i);n in l&&e(!1,n,l[n],i)}}),Z.add(i,{blur:function(t){for(var i in l)e(!1,i,l[i],t)}}),{modifiers:c,isDown:function(t){return!!u[t]}}},Y=G.extend({_class:"MouseEvent",initialize:function(t,e,i,n,r){this.type=t,this.event=e,this.point=i,this.target=n,this.delta=r},toString:function(){return"{ type: '"+this.type+"', point: "+this.point+", target: "+this.target+(this.delta?", delta: "+this.delta:"")+", modifiers: "+this.getModifiers()+" }"}}),$=G.extend({_class:"ToolEvent",_item:null,initialize:function(t,e,i){this.tool=t,this.type=e,this.event=i},_choosePoint:function(t,e){return t?t:e?e.clone():null},getPoint:function(){return this._choosePoint(this._point,this.tool._point)},setPoint:function(t){this._point=t},getLastPoint:function(){return this._choosePoint(this._lastPoint,this.tool._lastPoint)},setLastPoint:function(t){this._lastPoint=t},getDownPoint:function(){return this._choosePoint(this._downPoint,this.tool._downPoint)},setDownPoint:function(t){this._downPoint=t},getMiddlePoint:function(){return!this._middlePoint&&this.tool._lastPoint?this.tool._point.add(this.tool._lastPoint).divide(2):this._middlePoint},setMiddlePoint:function(t){this._middlePoint=t},getDelta:function(){return!this._delta&&this.tool._lastPoint?this.tool._point.subtract(this.tool._lastPoint):this._delta},setDelta:function(t){this._delta=t},getCount:function(){return this.tool[/^mouse(down|up)$/.test(this.type)?"_downCount":"_moveCount"]},setCount:function(t){this.tool[/^mouse(down|up)$/.test(this.type)?"downCount":"count"]=t},getItem:function(){if(!this._item){var t=this.tool._scope.project.hitTest(this.getPoint());if(t){for(var e=t.item,i=e._parent;/^(Group|CompoundPath)$/.test(i._class);)e=i,i=i._parent;this._item=e}}return this._item},setItem:function(t){this._item=t},toString:function(){return"{ type: "+this.type+", point: "+this.getPoint()+", count: "+this.getCount()+", modifiers: "+this.getModifiers()+" }"}}),K=(o.extend({_class:"Tool",_list:"tools",_reference:"tool",_events:["onMouseDown","onMouseUp","onMouseDrag","onMouseMove","onActivate","onDeactivate","onEditOptions","onKeyDown","onKeyUp"],initialize:function(t){o.call(this),this._moveCount=-1,this._downCount=-1,this._set(t)},getMinDistance:function(){return this._minDistance},setMinDistance:function(t){this._minDistance=t,null!=t&&null!=this._maxDistance&&t>this._maxDistance&&(this._maxDistance=t)},getMaxDistance:function(){return this._maxDistance},setMaxDistance:function(t){this._maxDistance=t,null!=this._minDistance&&null!=t&&t<this._minDistance&&(this._minDistance=t)},getFixedDistance:function(){return this._minDistance==this._maxDistance?this._minDistance:null},setFixedDistance:function(t){this._minDistance=this._maxDistance=t},_handleMouseEvent:function(t,e,i,n){function r(t,e){var r=i,s=a?c._point:c._downPoint||r;if(a){if(c._moveCount&&r.equals(s))return!1;if(s&&(null!=t||null!=e)){var o=r.subtract(s),h=o.getLength();if(h<(t||0))return!1;e&&(r=s.add(o.normalize(Math.min(h,e))))}c._moveCount++}return c._point=r,c._lastPoint=s||r,n.down&&(c._moveCount=-1,c._downPoint=r,c._downCount++),!0}function s(){o&&(l=c.emit(t,new $(c,t,e))||l)}paper=this._scope,n.drag&&!this.responds(t)&&(t="mousemove");var a=n.move||n.drag,o=this.responds(t),h=this.minDistance,u=this.maxDistance,l=!1,c=this;if(n.down)r(),s();else if(n.up)r(null,u),s();else if(o)for(;r(h,u);)s();return l}}),{request:function(t){var e=new i.XMLHttpRequest;return e.open((t.method||"get").toUpperCase(),t.url,r.pick(t.async,!0)),t.mimeType&&e.overrideMimeType(t.mimeType),e.onload=function(){var i=e.status;0===i||200===i?t.onLoad&&t.onLoad.call(e,e.responseText):e.onerror()},e.onerror=function(){var i=e.status,n='Could not load "'+t.url+'" (Status: '+i+")";if(!t.onError)throw new Error(n);t.onError(n,i)},e.send(null)}}),Q={canvases:[],getCanvas:function(t,e){if(!i)return null;var r,s=!0;"object"==typeof t&&(e=t.height,t=t.width),this.canvases.length?r=this.canvases.pop():(r=n.createElement("canvas"),s=!1);var a=r.getContext("2d");if(!a)throw new Error("Canvas "+r+" is unable toprovide a 2D context.");return r.width===t&&r.height===e?s&&a.clearRect(0,0,t+1,e+1):(r.width=t,r.height=e),a.save(),r},getContext:function(t,e){var i=this.getCanvas(t,e);return i?i.getContext("2d"):null},release:function(t){var e=t&&t.canvas?t.canvas:t;e&&e.getContext&&(e.getContext("2d").restore(),this.canvases.push(e))}},tt=new function(){function t(t,e,i){return.2989*t+.587*e+.114*i}function e(e,i,n,r){var s=r-t(e,i,n);f=e+s,_=i+s,g=n+s;var r=t(f,_,g),a=v(f,_,g),o=p(f,_,g);if(a<0){var h=r-a;f=r+(f-r)*r/h,_=r+(_-r)*r/h,g=r+(g-r)*r/h}if(o>255){var u=255-r,l=o-r;f=r+(f-r)*u/l,_=r+(_-r)*u/l,g=r+(g-r)*u/l}}function i(t,e,i){return p(t,e,i)-v(t,e,i)}function n(t,e,i,n){var r,s=[t,e,i],a=p(t,e,i),o=v(t,e,i);o=o===t?0:o===e?1:2,a=a===t?0:a===e?1:2,r=0===v(o,a)?1===p(o,a)?2:1:0,s[a]>s[o]?(s[r]=(s[r]-s[o])*n/(s[a]-s[o]),s[a]=n):s[r]=s[a]=0,s[o]=0,f=s[0],_=s[1],g=s[2]}var s,a,o,h,u,l,c,d,f,_,g,v=Math.min,p=Math.max,m=Math.abs,y={multiply:function(){f=u*s/255,_=l*a/255,g=c*o/255},screen:function(){f=u+s-u*s/255,_=l+a-l*a/255,g=c+o-c*o/255},overlay:function(){f=u<128?2*u*s/255:255-2*(255-u)*(255-s)/255,_=l<128?2*l*a/255:255-2*(255-l)*(255-a)/255,g=c<128?2*c*o/255:255-2*(255-c)*(255-o)/255},"soft-light":function(){var t=s*u/255;f=t+u*(255-(255-u)*(255-s)/255-t)/255,t=a*l/255,_=t+l*(255-(255-l)*(255-a)/255-t)/255,t=o*c/255,g=t+c*(255-(255-c)*(255-o)/255-t)/255},"hard-light":function(){f=s<128?2*s*u/255:255-2*(255-s)*(255-u)/255,_=a<128?2*a*l/255:255-2*(255-a)*(255-l)/255,g=o<128?2*o*c/255:255-2*(255-o)*(255-c)/255},"color-dodge":function(){f=0===u?0:255===s?255:v(255,255*u/(255-s)),_=0===l?0:255===a?255:v(255,255*l/(255-a)),g=0===c?0:255===o?255:v(255,255*c/(255-o))},"color-burn":function(){f=255===u?255:0===s?0:p(0,255-255*(255-u)/s),_=255===l?255:0===a?0:p(0,255-255*(255-l)/a),g=255===c?255:0===o?0:p(0,255-255*(255-c)/o)},darken:function(){f=u<s?u:s,_=l<a?l:a,g=c<o?c:o},lighten:function(){f=u>s?u:s,_=l>a?l:a,g=c>o?c:o},difference:function(){f=u-s,f<0&&(f=-f),_=l-a,_<0&&(_=-_),g=c-o,g<0&&(g=-g)},exclusion:function(){f=u+s*(255-u-u)/255,_=l+a*(255-l-l)/255,g=c+o*(255-c-c)/255},hue:function(){n(s,a,o,i(u,l,c)),e(f,_,g,t(u,l,c))},saturation:function(){n(u,l,c,i(s,a,o)),e(f,_,g,t(u,l,c))},luminosity:function(){e(u,l,c,t(s,a,o))},color:function(){e(s,a,o,t(u,l,c))},add:function(){f=v(u+s,255),_=v(l+a,255),g=v(c+o,255)},subtract:function(){f=p(u-s,0),_=p(l-a,0),g=p(c-o,0)},average:function(){f=(u+s)/2,_=(l+a)/2,g=(c+o)/2},negation:function(){f=255-m(255-s-u),_=255-m(255-a-l),g=255-m(255-o-c)}},w=this.nativeModes=r.each(["source-over","source-in","source-out","source-atop","destination-over","destination-in","destination-out","destination-atop","lighter","darker","copy","xor"],function(t){this[t]=!0},{}),x=Q.getContext(1,1);x&&(r.each(y,function(t,e){var i="darken"===e,n=!1;x.save();try{x.fillStyle=i?"#300":"#a00",x.fillRect(0,0,1,1),x.globalCompositeOperation=e,x.globalCompositeOperation===e&&(x.fillStyle=i?"#a00":"#300",x.fillRect(0,0,1,1),n=x.getImageData(0,0,1,1).data[0]!==i?170:51)}catch(r){}x.restore(),w[e]=n}),Q.release(x)),this.process=function(t,e,i,n,r){var v=e.canvas,p="normal"===t;if(p||w[t])i.save(),i.setTransform(1,0,0,1,0,0),i.globalAlpha=n,p||(i.globalCompositeOperation=t),i.drawImage(v,r.x,r.y),i.restore();else{var m=y[t];if(!m)return;for(var x=i.getImageData(r.x,r.y,v.width,v.height),b=x.data,C=e.getImageData(0,0,v.width,v.height).data,S=0,P=b.length;S<P;S+=4){s=C[S],u=b[S],a=C[S+1],l=b[S+1],o=C[S+2],c=b[S+2],h=C[S+3],d=b[S+3],m();var I=h*n/255,M=1-I;b[S]=I*f+M*u,b[S+1]=I*_+M*l,b[S+2]=I*g+M*c,b[S+3]=h*n+M*d}i.putImageData(x,r.x,r.y)}}},et=new function(){function t(t,e,s){return i(n.createElementNS(r,t),e,s)}function e(t,e){var i=o[e],n=i?t.getAttributeNS(i,e):t.getAttribute(e);return"null"===n?null:n}function i(t,e,i){for(var n in e){var r=e[n],s=o[n];"number"==typeof r&&i&&(r=i.number(r)),s?t.setAttributeNS(s,n,r):t.setAttribute(n,r)}return t}var r="http://www.w3.org/2000/svg",s="http://www.w3.org/2000/xmlns",a="http://www.w3.org/1999/xlink",o={href:a,xlink:s,xmlns:s+"/","xmlns:xlink":s+"/"};return{svg:r,xmlns:s,xlink:a,create:t,get:e,set:i}},it=r.each({fillColor:["fill","color"],fillRule:["fill-rule","string"],strokeColor:["stroke","color"],strokeWidth:["stroke-width","number"],strokeCap:["stroke-linecap","string"],strokeJoin:["stroke-linejoin","string"],strokeScaling:["vector-effect","lookup",{"true":"none","false":"non-scaling-stroke"},function(t,e){return!e&&(t instanceof A||t instanceof C||t instanceof D)}],miterLimit:["stroke-miterlimit","number"],dashArray:["stroke-dasharray","array"],dashOffset:["stroke-dashoffset","number"],fontFamily:["font-family","string"],fontWeight:["font-weight","string"],fontSize:["font-size","number"],justification:["text-anchor","lookup",{left:"start",center:"middle",right:"end"}],opacity:["opacity","number"],blendMode:["mix-blend-mode","style"]},function(t,e){var i=r.capitalize(e),n=t[2];this[e]={type:t[1],property:e,attribute:t[0],toSVG:n,fromSVG:n&&r.each(n,function(t,e){this[t]=e},{}),exportFilter:t[3],get:"get"+i,set:"set"+i}},{});return new function(){function t(t,e,i){var n=new r,s=t.getTranslation();if(e){t=t._shiftless();var a=t._inverseTransform(s);n[i?"cx":"x"]=a.x,n[i?"cy":"y"]=a.y,s=null}if(!t.isIdentity()){var o=t.decompose();if(o){var h=[],l=o.rotation,c=o.scaling,d=o.skewing;s&&!s.isZero()&&h.push("translate("+S.point(s)+")"),l&&h.push("rotate("+S.number(l)+")"),u.isZero(c.x-1)&&u.isZero(c.y-1)||h.push("scale("+S.point(c)+")"),d&&d.x&&h.push("skewX("+S.number(d.x)+")"),d&&d.y&&h.push("skewY("+S.number(d.y)+")"),n.transform=h.join(" ")}else n.transform="matrix("+t.getValues().join(",")+")"}return n}function e(e,i){for(var n=t(e._matrix),r=e._children,s=et.create("g",n,S),a=0,o=r.length;a<o;a++){var h=r[a],u=b(h,i);if(u)if(h.isClipMask()){var l=et.create("clipPath");l.appendChild(u),m(h,l,"clip"),et.set(s,{"clip-path":"url(#"+l.id+")"})}else s.appendChild(u)}return s}function n(e,i){var n=t(e._matrix,!0),r=e.getSize(),s=e.getImage();return n.x-=r.width/2,n.y-=r.height/2,n.width=r.width,n.height=r.height,n.href=i.embedImages===!1&&s&&s.src||e.toDataURL(),et.create("image",n,S)}function s(e,i){var n=i.matchShapes;if(n){var r=e.toShape(!1);if(r)return a(r,i)}var s,o=e._segments,h=o.length,u=t(e._matrix);if(n&&h>=2&&!e.hasHandles())if(h>2){s=e._closed?"polygon":"polyline";for(var l=[],c=0;c<h;c++)l.push(S.point(o[c]._point));u.points=l.join(" ")}else{s="line";var d=o[0]._point,f=o[1]._point;u.set({x1:d.x,y1:d.y,x2:f.x,y2:f.y})}else s="path",u.d=e.getPathData(null,i.precision);return et.create(s,u,S)}function a(e){var i=e._type,n=e._radius,r=t(e._matrix,!0,"rectangle"!==i);if("rectangle"===i){i="rect";var s=e._size,a=s.width,o=s.height;r.x-=a/2,r.y-=o/2,r.width=a,r.height=o,n.isZero()&&(n=null)}return n&&("circle"===i?r.r=n:(r.rx=n.width,r.ry=n.height)),et.create(i,r,S)}function o(e,i){var n=t(e._matrix),r=e.getPathData(null,i.precision);return r&&(n.d=r),et.create("path",n,S)}function c(e,i){var n=t(e._matrix,!0),r=e._definition,s=v(r,"symbol"),a=r._item,o=a.getBounds();return s||(s=et.create("symbol",{viewBox:S.rectangle(o)}),s.appendChild(b(a,i)),m(r,s,"symbol")),n.href="#"+s.id,n.x+=o.x,n.y+=o.y,n.width=o.width,n.height=o.height,n.overflow="visible",et.create("use",n,S)}function d(t){var e=v(t,"color");if(!e){var i,n=t.getGradient(),r=n._radial,s=t.getOrigin(),a=t.getDestination();if(r){i={cx:s.x,cy:s.y,r:s.getDistance(a)};var o=t.getHighlight();o&&(i.fx=o.x,i.fy=o.y)}else i={x1:s.x,y1:s.y,x2:a.x,y2:a.y};i.gradientUnits="userSpaceOnUse",e=et.create((r?"radial":"linear")+"Gradient",i,S);for(var h=n._stops,u=0,l=h.length;u<l;u++){var c=h[u],d=c._color,f=d.getAlpha();i={offset:c._offset||u/(l-1)},d&&(i["stop-color"]=d.toCSS(!0)),f<1&&(i["stop-opacity"]=f),e.appendChild(et.create("stop",i,S))}m(t,e,"color")}return"url(#"+e.id+")"}function f(e){var i=et.create("text",t(e._matrix,!0),S);return i.textContent=e._content,i}function _(t,e,i){var n={},s=!i&&t.getParent(),a=[];return null!=t._name&&(n.id=t._name),r.each(it,function(e){var i=e.get,o=e.type,h=t[i]();if(e.exportFilter?e.exportFilter(t,h):!s||!r.equals(s[i](),h)){if("color"===o&&null!=h){var u=h.getAlpha();u<1&&(n[e.attribute+"-opacity"]=u)}"style"===o?a.push(e.attribute+": "+h):n[e.attribute]=null==h?"none":"color"===o?h.gradient?d(h,t):h.toCSS(!0):"array"===o?h.join(","):"lookup"===o?e.toSVG[h]:h}}),a.length&&(n.style=a.join(";")),1===n.opacity&&delete n.opacity,t._visible||(n.visibility="hidden"),et.set(e,n,S)}function v(t,e){P||(P={ids:{},svgs:{}});var i=t._id||t.__id||(t.__id=l.get("svg"));return t&&P.svgs[e+"-"+i]}function m(t,e,i){P||v();var n=P.ids[i]=(P.ids[i]||0)+1;e.id=i+"-"+n,P.svgs[i+"-"+(t._id||t.__id)]=e}function x(t,e){var n=t,r=null;if(P){n="svg"===t.nodeName.toLowerCase()&&t;for(var s in P.svgs)r||(n||(n=et.create("svg"),n.appendChild(t)),r=n.insertBefore(et.create("defs"),n.firstChild)),r.appendChild(P.svgs[s]);P=null}return e.asString?(new i.XMLSerializer).serializeToString(n):n}function b(t,e,i){var n=I[t._class],r=n&&n(t,e);if(r){var s=e.onExport;s&&(r=s(t,r,e)||r);var a=JSON.stringify(t._data);a&&"{}"!==a&&"null"!==a&&r.setAttribute("data-paper-data",a)}return r&&_(t,r,i)}function C(t){return t||(t={}),S=new h(t.precision),t}var S,P,I={Group:e,Layer:e,Raster:n,Path:s,Shape:a,CompoundPath:o,SymbolItem:c,PointText:f};w.inject({exportSVG:function(t){return t=C(t),x(b(this,t,!0),t)}}),y.inject({exportSVG:function(e){e=C(e);var i=this._children,n=this.getView(),s=r.pick(e.bounds,"view"),a=e.matrix||"view"===s&&n._matrix,o=a&&p.read([a]),h="view"===s?new g([0,0],n.getViewSize()):"content"===s?w._getBounds(i,o,{stroke:!0}):g.read([s],0,{readNull:!0}),u={version:"1.1",xmlns:et.svg,"xmlns:xlink":et.xlink};h&&(u.width=h.width,u.height=h.height,(h.x||h.y)&&(u.viewBox=S.rectangle(h)));var l=et.create("svg",u,S),c=l;o&&!o.isIdentity()&&(c=l.appendChild(et.create("g",t(o),S)));for(var d=0,f=i.length;d<f;d++)c.appendChild(b(i[d],e,!0));return x(l,e)}})},new function(){function t(t,e,i,n,r){var s=et.get(t,e),a=null==s?n?null:i?"":0:i?s:parseFloat(s);return/%\s*$/.test(s)?a/100*(r?1:k[/x|^width/.test(e)?"width":"height"]):a}function s(e,i,n,r,s){return i=t(e,i||"x",!1,r,s),n=t(e,n||"y",!1,r,s),!r||null!=i&&null!=n?new c(i,n):null}function a(e,i,n,r,s){return i=t(e,i||"width",!1,r,s),n=t(e,n||"height",!1,r,s),!r||null!=i&&null!=n?new f(i,n):null}function o(t,e,i){return"none"===t?null:"number"===e?parseFloat(t):"array"===e?t?t.split(/[\s,]+/g).map(parseFloat):[]:"color"===e?P(t)||t:"lookup"===e?i[t]:t}function h(t,e,i,n){var r=t.childNodes,s="clippath"===e,a="defs"===e,o=new x,h=o._project,u=h._currentStyle,l=[];if(s||a||(o=b(o,t,n),h._currentStyle=o._style.clone()),n)for(var c=t.querySelectorAll("defs"),d=0,f=c.length;d<f;d++)M(c[d],i,!1);for(var d=0,f=r.length;d<f;d++){var _,g=r[d];1!==g.nodeType||/^defs$/i.test(g.nodeName)||!(_=M(g,i,!1))||_ instanceof I||l.push(_)}return o.addChildren(l),s&&(o=b(o.reduce(),t,n)),h._currentStyle=u,(s||a)&&(o.remove(),o=null),o}function u(t,e){for(var i=t.getAttribute("points").match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),n=[],r=0,s=i.length;r<s;r+=2)n.push(new c(parseFloat(i[r]),parseFloat(i[r+1])));var a=new L(n);return"polygon"===e&&a.closePath(),a}function l(t){return A.create(t.getAttribute("d"))}function d(e,i){var n,r=(t(e,"href",!0)||"").substring(1),a="radialgradient"===i;if(r)n=z[r].getGradient(),n._radial^a&&(n=n.clone(),n._radial=a);else{for(var o=e.childNodes,h=[],u=0,l=o.length;u<l;u++){var c=o[u];1===c.nodeType&&h.push(b(new q,c))}n=new R(h,a)}var d,f,_,g="userSpaceOnUse"!==t(e,"gradientUnits",!0);a?(d=s(e,"cx","cy",!1,g),f=d.add(t(e,"r",!1,!1,g),0),_=s(e,"fx","fy",!0,g)):(d=s(e,"x1","y1",!1,g),f=s(e,"x2","y2",!1,g));var v=b(new F(n,d,f,_),e);return v._scaleToBounds=g,null}function _(t,e,i,n){if(t.transform){for(var r=(n.getAttribute(i)||"").split(/\)\s*/g),s=new p,a=0,o=r.length;a<o;a++){var h=r[a];if(!h)break;for(var u=h.split(/\(\s*/),l=u[0],c=u[1].split(/[\s,]+/g),d=0,f=c.length;d<f;d++)c[d]=parseFloat(c[d]);switch(l){case"matrix":s.append(new p(c[0],c[1],c[2],c[3],c[4],c[5]));break;case"rotate":s.rotate(c[0],c[1],c[2]);break;case"translate":s.translate(c[0],c[1]);break;case"scale":s.scale(c);break;case"skewX":s.skew(c[0],0);break;case"skewY":s.skew(0,c[0])}}t.transform(s)}}function v(t,e,i){var n="fill-opacity"===i?"getFillColor":"getStrokeColor",r=t[n]&&t[n]();r&&r.setAlpha(parseFloat(e))}function m(t,i,n){var s=t.attributes[i],a=s&&s.value;if(!a){var o=r.camelize(i);a=t.style[o],a||n.node[o]===n.parent[o]||(a=n.node[o])}return a?"none"===a?null:a:e}function b(t,i,n){var s=i.parentNode,a={node:H.getStyles(i)||{},parent:!n&&!/^defs$/i.test(s.tagName)&&H.getStyles(s)||{}};return r.each(N,function(n,r){var s=m(i,r,a);t=s!==e&&n(t,s,r,i,a)||t;
+}),t}function P(t){var e=t&&t.match(/\((?:["'#]*)([^"')]+)/),n=e&&z[e[1].replace(i.location.href.split("#")[0]+"#","")];return n&&n._scaleToBounds&&(n=n.clone(),n._scaleToBounds=!0),n}function M(t,e,i){var s,o,h,u=t.nodeName.toLowerCase(),l="#document"!==u,c=n.body;i&&l&&(k=a(t,null,null,!0)||paper.getView().getSize(),s=et.create("svg",{style:"stroke-width: 1px; stroke-miterlimit: 10"}),o=t.parentNode,h=t.nextSibling,s.appendChild(t),c.appendChild(s));var d=paper.settings,f=d.applyMatrix,_=d.insertItems;d.applyMatrix=!1,d.insertItems=!1;var g=O[u],v=g&&g(t,u,e,i)||null;if(d.insertItems=_,d.applyMatrix=f,v){!l||v instanceof x||(v=b(v,t,i));var p=e.onImport,m=l&&t.getAttribute("data-paper-data");p&&(v=p(t,v,e)||v),e.expandShapes&&v instanceof C&&(v.remove(),v=v.toPath()),m&&(v._data=JSON.parse(m))}return s&&(c.removeChild(s),o&&(h?o.insertBefore(t,h):o.appendChild(t))),i&&(z={},v&&r.pick(e.applyMatrix,f)&&v.matrix.apply(!0,!0)),v}function T(t,r,s){function a(n){try{var a="object"==typeof n?n:(new i.DOMParser).parseFromString(n,"image/svg+xml");if(!a.nodeName)throw a=null,new Error("Unsupported SVG source: "+t);paper=h,u=M(a,r,!0),r&&r.insert===!1||s._insertItem(e,u);var l=r.onLoad;l&&l(u,n)}catch(c){o(c)}}function o(t,e){var i=r.onError;if(!i)throw new Error(t);i(t,e)}if(!t)return null;r="function"==typeof r?{onLoad:r}:r||{};var h=paper,u=null;if("string"!=typeof t||/^.*</.test(t)){if("undefined"!=typeof File&&t instanceof File){var l=new FileReader;return l.onload=function(){a(l.result)},l.onerror=function(){o(l.error)},l.readAsText(t)}a(t)}else{var c=n.getElementById(t);c?a(c):K.request({url:t,async:!0,onLoad:a,onError:o})}return u}var k,z={},O={"#document":function(t,e,i,n){for(var r=t.childNodes,s=0,a=r.length;s<a;s++){var o=r[s];if(1===o.nodeType)return M(o,i,n)}},g:h,svg:h,clippath:h,polygon:u,polyline:u,path:l,lineargradient:d,radialgradient:d,image:function(e){var i=new S(t(e,"href",!0));return i.on("load",function(){var t=a(e);this.setSize(t);var i=this._matrix._transformPoint(s(e).add(t.divide(2)));this.translate(i)}),i},symbol:function(t,e,i,n){return new I(h(t,e,i,n),(!0))},defs:h,use:function(e){var i=(t(e,"href",!0)||"").substring(1),n=z[i],r=s(e);return n?n instanceof I?n.place(r):n.clone().translate(r):null},circle:function(e){return new C.Circle(s(e,"cx","cy"),t(e,"r"))},ellipse:function(t){return new C.Ellipse({center:s(t,"cx","cy"),radius:a(t,"rx","ry")})},rect:function(t){return new C.Rectangle(new g(s(t),a(t)),a(t,"rx","ry"))},line:function(t){return new L.Line(s(t,"x1","y1"),s(t,"x2","y2"))},text:function(t){var e=new j(s(t).add(s(t,"dx","dy")));return e.setContent(t.textContent.trim()||""),e}},N=r.set(r.each(it,function(t){this[t.attribute]=function(e,i){if(e[t.set]&&(e[t.set](o(i,t.type,t.fromSVG)),"color"===t.type)){var n=e[t.get]();if(n){if(n._scaleToBounds){var r=e.getBounds();n.transform((new p).translate(r.getPoint()).scale(r.getSize()))}e instanceof C&&n.transform((new p).translate(e.getPosition(!0).negate()))}}}},{}),{id:function(t,e){z[e]=t,t.setName&&t.setName(e)},"clip-path":function(t,e){var i=P(e);if(i){if(i=i.clone(),i.setClipMask(!0),!(t instanceof x))return new x(i,t);t.insertChild(0,i)}},gradientTransform:_,transform:_,"fill-opacity":v,"stroke-opacity":v,visibility:function(t,e){t.setVisible&&t.setVisible("visible"===e)},display:function(t,e){t.setVisible&&t.setVisible(null!==e)},"stop-color":function(t,e){t.setColor&&t.setColor(e)},"stop-opacity":function(t,e){t._color&&t._color.setAlpha(parseFloat(e))},offset:function(t,e){if(t.setOffset){var i=e.match(/(.*)%$/);t.setOffset(i?i[1]/100:parseFloat(e))}},viewBox:function(t,e,i,n,r){var s,h,u=new g(o(e,"array")),l=a(n,null,null,!0);if(t instanceof x){var c=l?l.divide(u.getSize()):1,h=(new p).scale(c).translate(u.getPoint().negate());s=t}else t instanceof I&&(l&&u.setSize(l),s=t._item);if(s){if("visible"!==m(n,"overflow",r)){var d=new C.Rectangle(u);d.setClipMask(!0),s.addChild(d)}h&&s.transform(h)}}});w.inject({importSVG:function(t,e){return T(t,e,this)}}),y.inject({importSVG:function(t,e){return this.activate(),T(t,e,this)}})},paper=new(a.inject(r.exports,{enumerable:!0,Base:r,Numerical:u,Key:X,DomEvent:Z,DomElement:H,document:n,window:i,Symbol:I,PlacedSymbol:P})),paper.agent.node&&require("./node/extend")(paper),"function"==typeof define&&define.amd?define("paper",paper):"object"==typeof module&&module&&(module.exports=paper),paper}.call(this,"object"==typeof self?self:null);
\ No newline at end of file
diff --git a/dist/paper-full.js b/dist/paper-full.js
new file mode 100644
index 00000000..ccf6965c
--- /dev/null
+++ b/dist/paper-full.js
@@ -0,0 +1,14623 @@
+/*!
+ * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
+ * http://scratchdisk.com/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ *
+ * Date: Sat Jul 9 20:56:58 2016 +0200
+ *
+ ***
+ *
+ * Straps.js - Class inheritance library with support for bean-style accessors
+ *
+ * Copyright (c) 2006 - 2016 Juerg Lehni
+ * http://scratchdisk.com/
+ *
+ * Distributed under the MIT license.
+ *
+ ***
+ *
+ * Acorn.js
+ * http://marijnhaverbeke.nl/acorn/
+ *
+ * Acorn is a tiny, fast JavaScript parser written in JavaScript,
+ * created by Marijn Haverbeke and released under an MIT license.
+ *
+ */
+
+var paper = function(self, undefined) {
+
+var window = self ? self.window : require('./node/window'),
+	document = window && window.document;
+
+self = self || window;
+
+var Base = new function() {
+	var hidden = /^(statics|enumerable|beans|preserve)$/,
+
+		forEach = [].forEach || function(iter, bind) {
+			for (var i = 0, l = this.length; i < l; i++)
+				iter.call(bind, this[i], i, this);
+		},
+
+		forIn = function(iter, bind) {
+			for (var i in this)
+				if (this.hasOwnProperty(i))
+					iter.call(bind, this[i], i, this);
+		},
+
+		create = Object.create || function(proto) {
+			return { __proto__: proto };
+		},
+
+		describe = Object.getOwnPropertyDescriptor || function(obj, name) {
+			var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
+			return get
+					? { get: get, set: obj.__lookupSetter__(name),
+						enumerable: true, configurable: true }
+					: obj.hasOwnProperty(name)
+						? { value: obj[name], enumerable: true,
+							configurable: true, writable: true }
+						: null;
+		},
+
+		_define = Object.defineProperty || function(obj, name, desc) {
+			if ((desc.get || desc.set) && obj.__defineGetter__) {
+				if (desc.get)
+					obj.__defineGetter__(name, desc.get);
+				if (desc.set)
+					obj.__defineSetter__(name, desc.set);
+			} else {
+				obj[name] = desc.value;
+			}
+			return obj;
+		},
+
+		define = function(obj, name, desc) {
+			delete obj[name];
+			return _define(obj, name, desc);
+		};
+
+	function inject(dest, src, enumerable, beans, preserve) {
+		var beansNames = {};
+
+		function field(name, val) {
+			val = val || (val = describe(src, name))
+					&& (val.get ? val : val.value);
+			if (typeof val === 'string' && val[0] === '#')
+				val = dest[val.substring(1)] || val;
+			var isFunc = typeof val === 'function',
+				res = val,
+				prev = preserve || isFunc && !val.base
+						? (val && val.get ? name in dest : dest[name])
+						: null,
+				bean;
+			if (!preserve || !prev) {
+				if (isFunc && prev)
+					val.base = prev;
+				if (isFunc && beans !== false
+						&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
+					beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
+				if (!res || isFunc || !res.get || typeof res.get !== 'function'
+						|| !Base.isPlainObject(res))
+					res = { value: res, writable: true };
+				if ((describe(dest, name)
+						|| { configurable: true }).configurable) {
+					res.configurable = true;
+					res.enumerable = enumerable;
+				}
+				define(dest, name, res);
+			}
+		}
+		if (src) {
+			for (var name in src) {
+				if (src.hasOwnProperty(name) && !hidden.test(name))
+					field(name);
+			}
+			for (var name in beansNames) {
+				var part = beansNames[name],
+					set = dest['set' + part],
+					get = dest['get' + part] || set && dest['is' + part];
+				if (get && (beans === true || get.length === 0))
+					field(name, { get: get, set: set });
+			}
+		}
+		return dest;
+	}
+
+	function each(obj, iter, bind) {
+		if (obj)
+			('length' in obj && !obj.getLength
+					&& typeof obj.length === 'number'
+				? forEach
+				: forIn).call(obj, iter, bind = bind || obj);
+		return bind;
+	}
+
+	function set(obj, args, start) {
+		for (var i = start, l = args.length; i < l; i++) {
+			var props = args[i];
+			for (var key in props)
+				if (props.hasOwnProperty(key))
+					obj[key] = props[key];
+		}
+		return obj;
+	}
+
+	return inject(function Base() {
+		set(this, arguments, 0);
+	}, {
+		inject: function(src) {
+			if (src) {
+				var statics = src.statics === true ? src : src.statics,
+					beans = src.beans,
+					preserve = src.preserve;
+				if (statics !== src)
+					inject(this.prototype, src, src.enumerable, beans, preserve);
+				inject(this, statics, true, beans, preserve);
+			}
+			for (var i = 1, l = arguments.length; i < l; i++)
+				this.inject(arguments[i]);
+			return this;
+		},
+
+		extend: function() {
+			var base = this,
+				ctor,
+				proto;
+			for (var i = 0, obj, l = arguments.length;
+					i < l && !(ctor && proto); i++) {
+				obj = arguments[i];
+				ctor = ctor || obj.initialize;
+				proto = proto || obj.prototype;
+			}
+			ctor = ctor || function() {
+				base.apply(this, arguments);
+			};
+			proto = ctor.prototype = proto || create(this.prototype);
+			define(proto, 'constructor',
+					{ value: ctor, writable: true, configurable: true });
+			inject(ctor, this, true);
+			if (arguments.length)
+				this.inject.apply(ctor, arguments);
+			ctor.base = base;
+			return ctor;
+		}
+	}, true).inject({
+		inject: function() {
+			for (var i = 0, l = arguments.length; i < l; i++) {
+				var src = arguments[i];
+				if (src)
+					inject(this, src, src.enumerable, src.beans, src.preserve);
+			}
+			return this;
+		},
+
+		extend: function() {
+			var res = create(this);
+			return res.inject.apply(res, arguments);
+		},
+
+		each: function(iter, bind) {
+			return each(this, iter, bind);
+		},
+
+		set: function() {
+			return set(this, arguments, 0);
+		},
+
+		clone: function() {
+			return new this.constructor(this);
+		},
+
+		statics: {
+			each: each,
+			create: create,
+			define: define,
+			describe: describe,
+
+			set: function(obj) {
+				return set(obj, arguments, 1);
+			},
+
+			clone: function(obj) {
+				return set(new obj.constructor(), arguments, 0);
+			},
+
+			isPlainObject: function(obj) {
+				var ctor = obj != null && obj.constructor;
+				return ctor && (ctor === Object || ctor === Base
+						|| ctor.name === 'Object');
+			},
+
+			pick: function(a, b) {
+				return a !== undefined ? a : b;
+			}
+		}
+	});
+};
+
+if (typeof module !== 'undefined')
+	module.exports = Base;
+
+Base.inject({
+	toString: function() {
+		return this._id != null
+			?  (this._class || 'Object') + (this._name
+				? " '" + this._name + "'"
+				: ' @' + this._id)
+			: '{ ' + Base.each(this, function(value, key) {
+				if (!/^_/.test(key)) {
+					var type = typeof value;
+					this.push(key + ': ' + (type === 'number'
+							? Formatter.instance.number(value)
+							: type === 'string' ? "'" + value + "'" : value));
+				}
+			}, []).join(', ') + ' }';
+	},
+
+	getClassName: function() {
+		return this._class || '';
+	},
+
+	importJSON: function(json) {
+		return Base.importJSON(json, this);
+	},
+
+	exportJSON: function(options) {
+		return Base.exportJSON(this, options);
+	},
+
+	toJSON: function() {
+		return Base.serialize(this);
+	},
+
+	_set: function(props) {
+		if (props && Base.isPlainObject(props))
+			return Base.filter(this, props);
+	},
+
+	statics: {
+
+		exports: {
+			enumerable: true
+		},
+
+		extend: function extend() {
+			var res = extend.base.apply(this, arguments),
+				name = res.prototype._class;
+			if (name && !Base.exports[name])
+				Base.exports[name] = res;
+			return res;
+		},
+
+		equals: function(obj1, obj2) {
+			if (obj1 === obj2)
+				return true;
+			if (obj1 && obj1.equals)
+				return obj1.equals(obj2);
+			if (obj2 && obj2.equals)
+				return obj2.equals(obj1);
+			if (obj1 && obj2
+					&& typeof obj1 === 'object' && typeof obj2 === 'object') {
+				if (Array.isArray(obj1) && Array.isArray(obj2)) {
+					var length = obj1.length;
+					if (length !== obj2.length)
+						return false;
+					while (length--) {
+						if (!Base.equals(obj1[length], obj2[length]))
+							return false;
+					}
+				} else {
+					var keys = Object.keys(obj1),
+						length = keys.length;
+					if (length !== Object.keys(obj2).length)
+						return false;
+					while (length--) {
+						var key = keys[length];
+						if (!(obj2.hasOwnProperty(key)
+								&& Base.equals(obj1[key], obj2[key])))
+							return false;
+					}
+				}
+				return true;
+			}
+			return false;
+		},
+
+		read: function(list, start, options, length) {
+			if (this === Base) {
+				var value = this.peek(list, start);
+				list.__index++;
+				return value;
+			}
+			var proto = this.prototype,
+				readIndex = proto._readIndex,
+				index = start || readIndex && list.__index || 0;
+			if (!length)
+				length = list.length - index;
+			var obj = list[index];
+			if (obj instanceof this
+				|| options && options.readNull && obj == null && length <= 1) {
+				if (readIndex)
+					list.__index = index + 1;
+				return obj && options && options.clone ? obj.clone() : obj;
+			}
+			obj = Base.create(this.prototype);
+			if (readIndex)
+				obj.__read = true;
+			obj = obj.initialize.apply(obj, index > 0 || length < list.length
+				? Array.prototype.slice.call(list, index, index + length)
+				: list) || obj;
+			if (readIndex) {
+				list.__index = index + obj.__read;
+				obj.__read = undefined;
+			}
+			return obj;
+		},
+
+		peek: function(list, start) {
+			return list[list.__index = start || list.__index || 0];
+		},
+
+		remain: function(list) {
+			return list.length - (list.__index || 0);
+		},
+
+		readAll: function(list, start, options) {
+			var res = [],
+				entry;
+			for (var i = start || 0, l = list.length; i < l; i++) {
+				res.push(Array.isArray(entry = list[i])
+						? this.read(entry, 0, options)
+						: this.read(list, i, options, 1));
+			}
+			return res;
+		},
+
+		readNamed: function(list, name, start, options, length) {
+			var value = this.getNamed(list, name),
+				hasObject = value !== undefined;
+			if (hasObject) {
+				var filtered = list._filtered;
+				if (!filtered) {
+					filtered = list._filtered = Base.create(list[0]);
+					filtered._filtering = list[0];
+				}
+				filtered[name] = undefined;
+			}
+			return this.read(hasObject ? [value] : list, start, options, length);
+		},
+
+		getNamed: function(list, name) {
+			var arg = list[0];
+			if (list._hasObject === undefined)
+				list._hasObject = list.length === 1 && Base.isPlainObject(arg);
+			if (list._hasObject)
+				return name ? arg[name] : list._filtered || arg;
+		},
+
+		hasNamed: function(list, name) {
+			return !!this.getNamed(list, name);
+		},
+
+		filter: function(dest, source, exclude) {
+			var keys = Object.keys(source._filtering || source);
+			for (var i = 0, l = keys.length; i < l; i++) {
+				var key = keys[i];
+				if (!(exclude && exclude[key])) {
+					var value = source[key];
+					if (value !== undefined)
+						dest[key] = value;
+				}
+			}
+			return dest;
+		},
+
+		isPlainValue: function(obj, asString) {
+			return this.isPlainObject(obj) || Array.isArray(obj)
+					|| asString && typeof obj === 'string';
+		},
+
+		serialize: function(obj, options, compact, dictionary) {
+			options = options || {};
+
+			var isRoot = !dictionary,
+				res;
+			if (isRoot) {
+				options.formatter = new Formatter(options.precision);
+				dictionary = {
+					length: 0,
+					definitions: {},
+					references: {},
+					add: function(item, create) {
+						var id = '#' + item._id,
+							ref = this.references[id];
+						if (!ref) {
+							this.length++;
+							var res = create.call(item),
+								name = item._class;
+							if (name && res[0] !== name)
+								res.unshift(name);
+							this.definitions[id] = res;
+							ref = this.references[id] = [id];
+						}
+						return ref;
+					}
+				};
+			}
+			if (obj && obj._serialize) {
+				res = obj._serialize(options, dictionary);
+				var name = obj._class;
+				if (name && !obj._compactSerialize && (isRoot || !compact)
+						&& res[0] !== name) {
+					res.unshift(name);
+				}
+			} else if (Array.isArray(obj)) {
+				res = [];
+				for (var i = 0, l = obj.length; i < l; i++)
+					res[i] = Base.serialize(obj[i], options, compact,
+							dictionary);
+			} else if (Base.isPlainObject(obj)) {
+				res = {};
+				var keys = Object.keys(obj);
+				for (var i = 0, l = keys.length; i < l; i++) {
+					var key = keys[i];
+					res[key] = Base.serialize(obj[key], options, compact,
+							dictionary);
+				}
+			} else if (typeof obj === 'number') {
+				res = options.formatter.number(obj, options.precision);
+			} else {
+				res = obj;
+			}
+			return isRoot && dictionary.length > 0
+					? [['dictionary', dictionary.definitions], res]
+					: res;
+		},
+
+		deserialize: function(json, create, _data, _setDictionary, _isRoot) {
+			var res = json,
+				isFirst = !_data,
+				hasDictionary = isFirst && json && json.length
+					&& json[0][0] === 'dictionary';
+			_data = _data || {};
+			if (Array.isArray(json)) {
+				var type = json[0],
+					isDictionary = type === 'dictionary';
+				if (json.length == 1 && /^#/.test(type)) {
+					return _data.dictionary[type];
+				}
+				type = Base.exports[type];
+				res = [];
+				for (var i = type ? 1 : 0, l = json.length; i < l; i++) {
+					res.push(Base.deserialize(json[i], create, _data,
+							isDictionary, hasDictionary));
+				}
+				if (type) {
+					var args = res;
+					if (create) {
+						res = create(type, args, isFirst || _isRoot);
+					} else {
+						res = Base.create(type.prototype);
+						type.apply(res, args);
+					}
+				}
+			} else if (Base.isPlainObject(json)) {
+				res = {};
+				if (_setDictionary)
+					_data.dictionary = res;
+				for (var key in json)
+					res[key] = Base.deserialize(json[key], create, _data);
+			}
+			return hasDictionary ? res[1] : res;
+		},
+
+		exportJSON: function(obj, options) {
+			var json = Base.serialize(obj, options);
+			return options && options.asString === false
+					? json
+					: JSON.stringify(json);
+		},
+
+		importJSON: function(json, target) {
+			return Base.deserialize(
+					typeof json === 'string' ? JSON.parse(json) : json,
+					function(ctor, args, isRoot) {
+						var useTarget = isRoot && target
+								&& target.constructor === ctor,
+							obj = useTarget ? target
+								: Base.create(ctor.prototype);
+						if (args.length === 1 && obj instanceof Item
+								&& (useTarget || !(obj instanceof Layer))) {
+							var arg = args[0];
+							if (Base.isPlainObject(arg))
+								arg.insert = false;
+						}
+						(useTarget ? obj._set : ctor).apply(obj, args);
+						if (useTarget)
+							target = null;
+						return obj;
+					});
+		},
+
+		splice: function(list, items, index, remove) {
+			var amount = items && items.length,
+				append = index === undefined;
+			index = append ? list.length : index;
+			if (index > list.length)
+				index = list.length;
+			for (var i = 0; i < amount; i++)
+				items[i]._index = index + i;
+			if (append) {
+				list.push.apply(list, items);
+				return [];
+			} else {
+				var args = [index, remove];
+				if (items)
+					args.push.apply(args, items);
+				var removed = list.splice.apply(list, args);
+				for (var i = 0, l = removed.length; i < l; i++)
+					removed[i]._index = undefined;
+				for (var i = index + amount, l = list.length; i < l; i++)
+					list[i]._index = i;
+				return removed;
+			}
+		},
+
+		capitalize: function(str) {
+			return str.replace(/\b[a-z]/g, function(match) {
+				return match.toUpperCase();
+			});
+		},
+
+		camelize: function(str) {
+			return str.replace(/-(.)/g, function(all, chr) {
+				return chr.toUpperCase();
+			});
+		},
+
+		hyphenate: function(str) {
+			return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
+		}
+	}
+});
+
+var Emitter = {
+	on: function(type, func) {
+		if (typeof type !== 'string') {
+			Base.each(type, function(value, key) {
+				this.on(key, value);
+			}, this);
+		} else {
+			var types = this._eventTypes,
+				entry = types && types[type],
+				handlers = this._callbacks = this._callbacks || {};
+			handlers = handlers[type] = handlers[type] || [];
+			if (handlers.indexOf(func) === -1) {
+				handlers.push(func);
+				if (entry && entry.install && handlers.length === 1)
+					entry.install.call(this, type);
+			}
+		}
+		return this;
+	},
+
+	off: function(type, func) {
+		if (typeof type !== 'string') {
+			Base.each(type, function(value, key) {
+				this.off(key, value);
+			}, this);
+			return;
+		}
+		var types = this._eventTypes,
+			entry = types && types[type],
+			handlers = this._callbacks && this._callbacks[type],
+			index;
+		if (handlers) {
+			if (!func || (index = handlers.indexOf(func)) !== -1
+					&& handlers.length === 1) {
+				if (entry && entry.uninstall)
+					entry.uninstall.call(this, type);
+				delete this._callbacks[type];
+			} else if (index !== -1) {
+				handlers.splice(index, 1);
+			}
+		}
+		return this;
+	},
+
+	once: function(type, func) {
+		return this.on(type, function() {
+			func.apply(this, arguments);
+			this.off(type, func);
+		});
+	},
+
+	emit: function(type, event) {
+		var handlers = this._callbacks && this._callbacks[type];
+		if (!handlers)
+			return false;
+		var args = [].slice.call(arguments, 1),
+			setTarget = event && event.target && !event.currentTarget;
+		handlers = handlers.slice();
+		if (setTarget)
+			event.currentTarget = this;
+		for (var i = 0, l = handlers.length; i < l; i++) {
+			if (handlers[i].apply(this, args) === false) {
+				if (event && event.stop)
+					event.stop();
+				break;
+		   }
+		}
+		if (setTarget)
+			delete event.currentTarget;
+		return true;
+	},
+
+	responds: function(type) {
+		return !!(this._callbacks && this._callbacks[type]);
+	},
+
+	attach: '#on',
+	detach: '#off',
+	fire: '#emit',
+
+	_installEvents: function(install) {
+		var types = this._eventTypes,
+			handlers = this._callbacks,
+			key = install ? 'install' : 'uninstall';
+		if (types) {
+			for (var type in handlers) {
+				if (handlers[type].length > 0) {
+					var entry = types[type],
+						func = entry && entry[key];
+					if (func)
+						func.call(this, type);
+				}
+		}
+		}
+	},
+
+	statics: {
+		inject: function inject(src) {
+			var events = src._events;
+			if (events) {
+				var types = {};
+				Base.each(events, function(entry, key) {
+					var isString = typeof entry === 'string',
+						name = isString ? entry : key,
+						part = Base.capitalize(name),
+						type = name.substring(2).toLowerCase();
+					types[type] = isString ? {} : entry;
+					name = '_' + name;
+					src['get' + part] = function() {
+						return this[name];
+					};
+					src['set' + part] = function(func) {
+						var prev = this[name];
+						if (prev)
+							this.off(type, prev);
+						if (func)
+							this.on(type, func);
+						this[name] = func;
+					};
+				});
+				src._eventTypes = types;
+			}
+			return inject.base.apply(this, arguments);
+		}
+	}
+};
+
+var PaperScope = Base.extend({
+	_class: 'PaperScope',
+
+	initialize: function PaperScope() {
+		paper = this;
+		this.settings = new Base({
+			applyMatrix: true,
+			insertItems: true,
+			handleSize: 4,
+			hitTolerance: 0
+		});
+		this.project = null;
+		this.projects = [];
+		this.tools = [];
+		this.palettes = [];
+		this._id = PaperScope._id++;
+		PaperScope._scopes[this._id] = this;
+		var proto = PaperScope.prototype;
+		if (!this.support) {
+			var ctx = CanvasProvider.getContext(1, 1) || {};
+			proto.support = {
+				nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
+				nativeBlendModes: BlendMode.nativeModes
+			};
+			CanvasProvider.release(ctx);
+		}
+		if (!this.agent) {
+			var user = self.navigator.userAgent.toLowerCase(),
+				os = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],
+				platform = os === 'darwin' ? 'mac' : os,
+				agent = proto.agent = proto.browser = { platform: platform };
+			if (platform)
+				agent[platform] = true;
+			user.replace(
+				/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,
+				function(all, n, v1, v2, rv) {
+					if (!agent.chrome) {
+						var v = n === 'opera' ? v2 :
+								/^(node|trident)$/.test(n) ? rv : v1;
+						agent.version = v;
+						agent.versionNumber = parseFloat(v);
+						n = n === 'trident' ? 'msie' : n;
+						agent.name = n;
+						agent[n] = true;
+					}
+				}
+			);
+			if (agent.chrome)
+				delete agent.webkit;
+			if (agent.atom)
+				delete agent.chrome;
+		}
+	},
+
+	version: "0.10.2",
+
+	getView: function() {
+		var project = this.project;
+		return project && project._view;
+	},
+
+	getPaper: function() {
+		return this;
+	},
+
+	execute: function(code, options) {
+		paper.PaperScript.execute(code, this, options);
+		View.updateFocus();
+	},
+
+	install: function(scope) {
+		var that = this;
+		Base.each(['project', 'view', 'tool'], function(key) {
+			Base.define(scope, key, {
+				configurable: true,
+				get: function() {
+					return that[key];
+				}
+			});
+		});
+		for (var key in this)
+			if (!/^_/.test(key) && this[key])
+				scope[key] = this[key];
+	},
+
+	setup: function(element) {
+		paper = this;
+		this.project = new Project(element);
+		return this;
+	},
+
+	createCanvas: function(width, height) {
+		return CanvasProvider.getCanvas(width, height);
+	},
+
+	activate: function() {
+		paper = this;
+	},
+
+	clear: function() {
+		var projects = this.projects,
+			tools = this.tools,
+			palettes = this.palettes;
+		for (var i = projects.length - 1; i >= 0; i--)
+			projects[i].remove();
+		for (var i = tools.length - 1; i >= 0; i--)
+			tools[i].remove();
+		for (var i = palettes.length - 1; i >= 0; i--)
+			palettes[i].remove();
+	},
+
+	remove: function() {
+		this.clear();
+		delete PaperScope._scopes[this._id];
+	},
+
+	statics: new function() {
+		function handleAttribute(name) {
+			name += 'Attribute';
+			return function(el, attr) {
+				return el[name](attr) || el[name]('data-paper-' + attr);
+			};
+		}
+
+		return {
+			_scopes: {},
+			_id: 0,
+
+			get: function(id) {
+				return this._scopes[id] || null;
+			},
+
+			getAttribute: handleAttribute('get'),
+			hasAttribute: handleAttribute('has')
+		};
+	}
+});
+
+var PaperScopeItem = Base.extend(Emitter, {
+
+	initialize: function(activate) {
+		this._scope = paper;
+		this._index = this._scope[this._list].push(this) - 1;
+		if (activate || !this._scope[this._reference])
+			this.activate();
+	},
+
+	activate: function() {
+		if (!this._scope)
+			return false;
+		var prev = this._scope[this._reference];
+		if (prev && prev !== this)
+			prev.emit('deactivate');
+		this._scope[this._reference] = this;
+		this.emit('activate', prev);
+		return true;
+	},
+
+	isActive: function() {
+		return this._scope[this._reference] === this;
+	},
+
+	remove: function() {
+		if (this._index == null)
+			return false;
+		Base.splice(this._scope[this._list], null, this._index, 1);
+		if (this._scope[this._reference] == this)
+			this._scope[this._reference] = null;
+		this._scope = null;
+		return true;
+	},
+
+	getView: function() {
+		return this._scope.getView();
+	}
+});
+
+var Formatter = Base.extend({
+	initialize: function(precision) {
+		this.precision = Base.pick(precision, 5);
+		this.multiplier = Math.pow(10, this.precision);
+	},
+
+	number: function(val) {
+		return this.precision < 16
+				? Math.round(val * this.multiplier) / this.multiplier : val;
+	},
+
+	pair: function(val1, val2, separator) {
+		return this.number(val1) + (separator || ',') + this.number(val2);
+	},
+
+	point: function(val, separator) {
+		return this.number(val.x) + (separator || ',') + this.number(val.y);
+	},
+
+	size: function(val, separator) {
+		return this.number(val.width) + (separator || ',')
+				+ this.number(val.height);
+	},
+
+	rectangle: function(val, separator) {
+		return this.point(val, separator) + (separator || ',')
+				+ this.size(val, separator);
+	}
+});
+
+Formatter.instance = new Formatter();
+
+var Numerical = new function() {
+
+	var abscissas = [
+		[  0.5773502691896257645091488],
+		[0,0.7745966692414833770358531],
+		[  0.3399810435848562648026658,0.8611363115940525752239465],
+		[0,0.5384693101056830910363144,0.9061798459386639927976269],
+		[  0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],
+		[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],
+		[  0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],
+		[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],
+		[  0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],
+		[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],
+		[  0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],
+		[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],
+		[  0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],
+		[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],
+		[  0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]
+	];
+
+	var weights = [
+		[1],
+		[0.8888888888888888888888889,0.5555555555555555555555556],
+		[0.6521451548625461426269361,0.3478548451374538573730639],
+		[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],
+		[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],
+		[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],
+		[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],
+		[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],
+		[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],
+		[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],
+		[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],
+		[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],
+		[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],
+		[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],
+		[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]
+	];
+
+	var abs = Math.abs,
+		sqrt = Math.sqrt,
+		pow = Math.pow,
+		log2 = Math.log2 || function(x) {
+			return Math.log(x) * Math.LOG2E;
+		},
+		EPSILON = 1e-12,
+		MACHINE_EPSILON = 1.12e-16;
+
+	function clamp(value, min, max) {
+		return value < min ? min : value > max ? max : value;
+	}
+
+	function getDiscriminant(a, b, c) {
+		function split(v) {
+			var x = v * 134217729,
+				y = v - x,
+				hi = y + x,
+				lo = v - hi;
+			return [hi, lo];
+		}
+
+		var D = b * b - a * c,
+			E = b * b + a * c;
+		if (abs(D) * 3 < E) {
+			var ad = split(a),
+				bd = split(b),
+				cd = split(c),
+				p = b * b,
+				dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
+				q = a * c,
+				dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
+						+ ad[1] * cd[1];
+			D = (p - q) + (dp - dq);
+		}
+		return D;
+	}
+
+	function getNormalizationFactor() {
+		var norm = Math.max.apply(Math, arguments);
+		return norm && (norm < 1e-8 || norm > 1e8)
+				? pow(2, -Math.round(log2(norm)))
+				: 0;
+	}
+
+	return {
+		TOLERANCE: 1e-6,
+		EPSILON: EPSILON,
+		MACHINE_EPSILON: MACHINE_EPSILON,
+		CURVETIME_EPSILON: 4e-7,
+		GEOMETRIC_EPSILON: 2e-7,
+		WINDING_EPSILON: 2e-7,
+		TRIGONOMETRIC_EPSILON: 1e-7,
+		CLIPPING_EPSILON: 1e-9,
+		KAPPA: 4 * (sqrt(2) - 1) / 3,
+
+		isZero: function(val) {
+			return val >= -EPSILON && val <= EPSILON;
+		},
+
+		clamp: clamp,
+
+		integrate: function(f, a, b, n) {
+			var x = abscissas[n - 2],
+				w = weights[n - 2],
+				A = (b - a) * 0.5,
+				B = A + a,
+				i = 0,
+				m = (n + 1) >> 1,
+				sum = n & 1 ? w[i++] * f(B) : 0;
+			while (i < m) {
+				var Ax = A * x[i];
+				sum += w[i++] * (f(B + Ax) + f(B - Ax));
+			}
+			return A * sum;
+		},
+
+		findRoot: function(f, df, x, a, b, n, tolerance) {
+			for (var i = 0; i < n; i++) {
+				var fx = f(x),
+					dx = fx / df(x),
+					nx = x - dx;
+				if (abs(dx) < tolerance)
+					return nx;
+				if (fx > 0) {
+					b = x;
+					x = nx <= a ? (a + b) * 0.5 : nx;
+				} else {
+					a = x;
+					x = nx >= b ? (a + b) * 0.5 : nx;
+				}
+			}
+			return x;
+		},
+
+		solveQuadratic: function(a, b, c, roots, min, max) {
+			var x1, x2 = Infinity;
+			if (abs(a) < EPSILON) {
+				if (abs(b) < EPSILON)
+					return abs(c) < EPSILON ? -1 : 0;
+				x1 = -c / b;
+			} else {
+				b *= -0.5;
+				var D = getDiscriminant(a, b, c);
+				if (D && abs(D) < MACHINE_EPSILON) {
+					var f = getNormalizationFactor(abs(a), abs(b), abs(c));
+					if (f) {
+						a *= f;
+						b *= f;
+						c *= f;
+						D = getDiscriminant(a, b, c);
+					}
+				}
+				if (D >= -MACHINE_EPSILON) {
+					var Q = D < 0 ? 0 : sqrt(D),
+						R = b + (b < 0 ? -Q : Q);
+					if (R === 0) {
+						x1 = c / a;
+						x2 = -x1;
+					} else {
+						x1 = R / a;
+						x2 = c / R;
+					}
+				}
+			}
+			var count = 0,
+				boundless = min == null,
+				minB = min - EPSILON,
+				maxB = max + EPSILON;
+			if (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))
+				roots[count++] = boundless ? x1 : clamp(x1, min, max);
+			if (x2 !== x1
+					&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))
+				roots[count++] = boundless ? x2 : clamp(x2, min, max);
+			return count;
+		},
+
+		solveCubic: function(a, b, c, d, roots, min, max) {
+			var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),
+				x, b1, c2, qd, q;
+			if (f) {
+				a *= f;
+				b *= f;
+				c *= f;
+				d *= f;
+			}
+
+			function evaluate(x0) {
+				x = x0;
+				var tmp = a * x;
+				b1 = tmp + b;
+				c2 = b1 * x + c;
+				qd = (tmp + b1) * x + c2;
+				q = c2 * x + d;
+			}
+
+			if (abs(a) < EPSILON) {
+				a = b;
+				b1 = c;
+				c2 = d;
+				x = Infinity;
+			} else if (abs(d) < EPSILON) {
+				b1 = b;
+				c2 = c;
+				x = 0;
+			} else {
+				evaluate(-(b / a) / 3);
+				var t = q / a,
+					r = pow(abs(t), 1/3),
+					s = t < 0 ? -1 : 1,
+					td = -qd / a,
+					rd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,
+					x0 = x - s * rd;
+				if (x0 !== x) {
+					do {
+						evaluate(x0);
+						x0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);
+					} while (s * x0 > s * x);
+					if (abs(a) * x * x > abs(d / x)) {
+						c2 = -d / x;
+						b1 = (c2 - c) / x;
+					}
+				}
+			}
+			var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),
+				boundless = min == null;
+			if (isFinite(x) && (count === 0
+					|| count > 0 && x !== roots[0] && x !== roots[1])
+					&& (boundless || x > min - EPSILON && x < max + EPSILON))
+				roots[count++] = boundless ? x : clamp(x, min, max);
+			return count;
+		}
+	};
+};
+
+var UID = {
+	_id: 1,
+	_pools: {},
+
+	get: function(name) {
+		if (name) {
+			var pool = this._pools[name];
+			if (!pool)
+				pool = this._pools[name] = { _id: 1 };
+			return pool._id++;
+		} else {
+			return this._id++;
+		}
+	}
+};
+
+var Point = Base.extend({
+	_class: 'Point',
+	_readIndex: true,
+
+	initialize: function Point(arg0, arg1) {
+		var type = typeof arg0;
+		if (type === 'number') {
+			var hasY = typeof arg1 === 'number';
+			this.x = arg0;
+			this.y = hasY ? arg1 : arg0;
+			if (this.__read)
+				this.__read = hasY ? 2 : 1;
+		} else if (type === 'undefined' || arg0 === null) {
+			this.x = this.y = 0;
+			if (this.__read)
+				this.__read = arg0 === null ? 1 : 0;
+		} else {
+			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
+			if (Array.isArray(obj)) {
+				this.x = obj[0];
+				this.y = obj.length > 1 ? obj[1] : obj[0];
+			} else if ('x' in obj) {
+				this.x = obj.x;
+				this.y = obj.y;
+			} else if ('width' in obj) {
+				this.x = obj.width;
+				this.y = obj.height;
+			} else if ('angle' in obj) {
+				this.x = obj.length;
+				this.y = 0;
+				this.setAngle(obj.angle);
+			} else {
+				this.x = this.y = 0;
+				if (this.__read)
+					this.__read = 0;
+			}
+			if (this.__read)
+				this.__read = 1;
+		}
+	},
+
+	set: function(x, y) {
+		this.x = x;
+		this.y = y;
+		return this;
+	},
+
+	equals: function(point) {
+		return this === point || point
+				&& (this.x === point.x && this.y === point.y
+					|| Array.isArray(point)
+						&& this.x === point[0] && this.y === point[1])
+				|| false;
+	},
+
+	clone: function() {
+		return new Point(this.x, this.y);
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';
+	},
+
+	_serialize: function(options) {
+		var f = options.formatter;
+		return [f.number(this.x), f.number(this.y)];
+	},
+
+	getLength: function() {
+		return Math.sqrt(this.x * this.x + this.y * this.y);
+	},
+
+	setLength: function(length) {
+		if (this.isZero()) {
+			var angle = this._angle || 0;
+			this.set(
+				Math.cos(angle) * length,
+				Math.sin(angle) * length
+			);
+		} else {
+			var scale = length / this.getLength();
+			if (Numerical.isZero(scale))
+				this.getAngle();
+			this.set(
+				this.x * scale,
+				this.y * scale
+			);
+		}
+	},
+	getAngle: function() {
+		return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;
+	},
+
+	setAngle: function(angle) {
+		this.setAngleInRadians.call(this, angle * Math.PI / 180);
+	},
+
+	getAngleInDegrees: '#getAngle',
+	setAngleInDegrees: '#setAngle',
+
+	getAngleInRadians: function() {
+		if (!arguments.length) {
+			return this.isZero()
+					? this._angle || 0
+					: this._angle = Math.atan2(this.y, this.x);
+		} else {
+			var point = Point.read(arguments),
+				div = this.getLength() * point.getLength();
+			if (Numerical.isZero(div)) {
+				return NaN;
+			} else {
+				var a = this.dot(point) / div;
+				return Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);
+			}
+		}
+	},
+
+	setAngleInRadians: function(angle) {
+		this._angle = angle;
+		if (!this.isZero()) {
+			var length = this.getLength();
+			this.set(
+				Math.cos(angle) * length,
+				Math.sin(angle) * length
+			);
+		}
+	},
+
+	getQuadrant: function() {
+		return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
+	}
+}, {
+	beans: false,
+
+	getDirectedAngle: function() {
+		var point = Point.read(arguments);
+		return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;
+	},
+
+	getDistance: function() {
+		var point = Point.read(arguments),
+			x = point.x - this.x,
+			y = point.y - this.y,
+			d = x * x + y * y,
+			squared = Base.read(arguments);
+		return squared ? d : Math.sqrt(d);
+	},
+
+	normalize: function(length) {
+		if (length === undefined)
+			length = 1;
+		var current = this.getLength(),
+			scale = current !== 0 ? length / current : 0,
+			point = new Point(this.x * scale, this.y * scale);
+		if (scale >= 0)
+			point._angle = this._angle;
+		return point;
+	},
+
+	rotate: function(angle, center) {
+		if (angle === 0)
+			return this.clone();
+		angle = angle * Math.PI / 180;
+		var point = center ? this.subtract(center) : this,
+			sin = Math.sin(angle),
+			cos = Math.cos(angle);
+		point = new Point(
+			point.x * cos - point.y * sin,
+			point.x * sin + point.y * cos
+		);
+		return center ? point.add(center) : point;
+	},
+
+	transform: function(matrix) {
+		return matrix ? matrix._transformPoint(this) : this;
+	},
+
+	add: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x + point.x, this.y + point.y);
+	},
+
+	subtract: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x - point.x, this.y - point.y);
+	},
+
+	multiply: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x * point.x, this.y * point.y);
+	},
+
+	divide: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x / point.x, this.y / point.y);
+	},
+
+	modulo: function() {
+		var point = Point.read(arguments);
+		return new Point(this.x % point.x, this.y % point.y);
+	},
+
+	negate: function() {
+		return new Point(-this.x, -this.y);
+	},
+
+	isInside: function() {
+		return Rectangle.read(arguments).contains(this);
+	},
+
+	isClose: function() {
+		var point = Point.read(arguments),
+			tolerance = Base.read(arguments);
+		return this.getDistance(point) <= tolerance;
+	},
+
+	isCollinear: function() {
+		var point = Point.read(arguments);
+		return Point.isCollinear(this.x, this.y, point.x, point.y);
+	},
+
+	isColinear: '#isCollinear',
+
+	isOrthogonal: function() {
+		var point = Point.read(arguments);
+		return Point.isOrthogonal(this.x, this.y, point.x, point.y);
+	},
+
+	isZero: function() {
+		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
+	},
+
+	isNaN: function() {
+		return isNaN(this.x) || isNaN(this.y);
+	},
+
+	dot: function() {
+		var point = Point.read(arguments);
+		return this.x * point.x + this.y * point.y;
+	},
+
+	cross: function() {
+		var point = Point.read(arguments);
+		return this.x * point.y - this.y * point.x;
+	},
+
+	project: function() {
+		var point = Point.read(arguments),
+			scale = point.isZero() ? 0 : this.dot(point) / point.dot(point);
+		return new Point(
+			point.x * scale,
+			point.y * scale
+		);
+	},
+
+	statics: {
+		min: function() {
+			var point1 = Point.read(arguments),
+				point2 = Point.read(arguments);
+			return new Point(
+				Math.min(point1.x, point2.x),
+				Math.min(point1.y, point2.y)
+			);
+		},
+
+		max: function() {
+			var point1 = Point.read(arguments),
+				point2 = Point.read(arguments);
+			return new Point(
+				Math.max(point1.x, point2.x),
+				Math.max(point1.y, point2.y)
+			);
+		},
+
+		random: function() {
+			return new Point(Math.random(), Math.random());
+		},
+
+		isCollinear: function(x1, y1, x2, y2) {
+			return Math.abs(x1 * y2 - y1 * x2)
+					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
+						* 1e-7;
+		},
+
+		isOrthogonal: function(x1, y1, x2, y2) {
+			return Math.abs(x1 * x2 + y1 * y2)
+					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
+						* 1e-7;
+		}
+	}
+}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
+	var op = Math[key];
+	this[key] = function() {
+		return new Point(op(this.x), op(this.y));
+	};
+}, {}));
+
+var LinkedPoint = Point.extend({
+	initialize: function Point(x, y, owner, setter) {
+		this._x = x;
+		this._y = y;
+		this._owner = owner;
+		this._setter = setter;
+	},
+
+	set: function(x, y, _dontNotify) {
+		this._x = x;
+		this._y = y;
+		if (!_dontNotify)
+			this._owner[this._setter](this);
+		return this;
+	},
+
+	getX: function() {
+		return this._x;
+	},
+
+	setX: function(x) {
+		this._x = x;
+		this._owner[this._setter](this);
+	},
+
+	getY: function() {
+		return this._y;
+	},
+
+	setY: function(y) {
+		this._y = y;
+		this._owner[this._setter](this);
+	},
+
+	isSelected: function() {
+		return !!(this._owner._selection & this._getSelection());
+	},
+
+	setSelected: function(selected) {
+		this._owner.changeSelection(this._getSelection(), selected);
+	},
+
+	_getSelection: function() {
+		return this._setter === 'setPosition' ? 4 : 0;
+	}
+});
+
+var Size = Base.extend({
+	_class: 'Size',
+	_readIndex: true,
+
+	initialize: function Size(arg0, arg1) {
+		var type = typeof arg0;
+		if (type === 'number') {
+			var hasHeight = typeof arg1 === 'number';
+			this.width = arg0;
+			this.height = hasHeight ? arg1 : arg0;
+			if (this.__read)
+				this.__read = hasHeight ? 2 : 1;
+		} else if (type === 'undefined' || arg0 === null) {
+			this.width = this.height = 0;
+			if (this.__read)
+				this.__read = arg0 === null ? 1 : 0;
+		} else {
+			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
+			if (Array.isArray(obj)) {
+				this.width = obj[0];
+				this.height = obj.length > 1 ? obj[1] : obj[0];
+			} else if ('width' in obj) {
+				this.width = obj.width;
+				this.height = obj.height;
+			} else if ('x' in obj) {
+				this.width = obj.x;
+				this.height = obj.y;
+			} else {
+				this.width = this.height = 0;
+				if (this.__read)
+					this.__read = 0;
+			}
+			if (this.__read)
+				this.__read = 1;
+		}
+	},
+
+	set: function(width, height) {
+		this.width = width;
+		this.height = height;
+		return this;
+	},
+
+	equals: function(size) {
+		return size === this || size && (this.width === size.width
+				&& this.height === size.height
+				|| Array.isArray(size) && this.width === size[0]
+					&& this.height === size[1]) || false;
+	},
+
+	clone: function() {
+		return new Size(this.width, this.height);
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '{ width: ' + f.number(this.width)
+				+ ', height: ' + f.number(this.height) + ' }';
+	},
+
+	_serialize: function(options) {
+		var f = options.formatter;
+		return [f.number(this.width),
+				f.number(this.height)];
+	},
+
+	add: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width + size.width, this.height + size.height);
+	},
+
+	subtract: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width - size.width, this.height - size.height);
+	},
+
+	multiply: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width * size.width, this.height * size.height);
+	},
+
+	divide: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width / size.width, this.height / size.height);
+	},
+
+	modulo: function() {
+		var size = Size.read(arguments);
+		return new Size(this.width % size.width, this.height % size.height);
+	},
+
+	negate: function() {
+		return new Size(-this.width, -this.height);
+	},
+
+	isZero: function() {
+		return Numerical.isZero(this.width) && Numerical.isZero(this.height);
+	},
+
+	isNaN: function() {
+		return isNaN(this.width) || isNaN(this.height);
+	},
+
+	statics: {
+		min: function(size1, size2) {
+			return new Size(
+				Math.min(size1.width, size2.width),
+				Math.min(size1.height, size2.height));
+		},
+
+		max: function(size1, size2) {
+			return new Size(
+				Math.max(size1.width, size2.width),
+				Math.max(size1.height, size2.height));
+		},
+
+		random: function() {
+			return new Size(Math.random(), Math.random());
+		}
+	}
+}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
+	var op = Math[key];
+	this[key] = function() {
+		return new Size(op(this.width), op(this.height));
+	};
+}, {}));
+
+var LinkedSize = Size.extend({
+	initialize: function Size(width, height, owner, setter) {
+		this._width = width;
+		this._height = height;
+		this._owner = owner;
+		this._setter = setter;
+	},
+
+	set: function(width, height, _dontNotify) {
+		this._width = width;
+		this._height = height;
+		if (!_dontNotify)
+			this._owner[this._setter](this);
+		return this;
+	},
+
+	getWidth: function() {
+		return this._width;
+	},
+
+	setWidth: function(width) {
+		this._width = width;
+		this._owner[this._setter](this);
+	},
+
+	getHeight: function() {
+		return this._height;
+	},
+
+	setHeight: function(height) {
+		this._height = height;
+		this._owner[this._setter](this);
+	}
+});
+
+var Rectangle = Base.extend({
+	_class: 'Rectangle',
+	_readIndex: true,
+	beans: true,
+
+	initialize: function Rectangle(arg0, arg1, arg2, arg3) {
+		var type = typeof arg0,
+			read = 0;
+		if (type === 'number') {
+			this.x = arg0;
+			this.y = arg1;
+			this.width = arg2;
+			this.height = arg3;
+			read = 4;
+		} else if (type === 'undefined' || arg0 === null) {
+			this.x = this.y = this.width = this.height = 0;
+			read = arg0 === null ? 1 : 0;
+		} else if (arguments.length === 1) {
+			if (Array.isArray(arg0)) {
+				this.x = arg0[0];
+				this.y = arg0[1];
+				this.width = arg0[2];
+				this.height = arg0[3];
+				read = 1;
+			} else if (arg0.x !== undefined || arg0.width !== undefined) {
+				this.x = arg0.x || 0;
+				this.y = arg0.y || 0;
+				this.width = arg0.width || 0;
+				this.height = arg0.height || 0;
+				read = 1;
+			} else if (arg0.from === undefined && arg0.to === undefined) {
+				this.x = this.y = this.width = this.height = 0;
+				this._set(arg0);
+				read = 1;
+			}
+		}
+		if (!read) {
+			var point = Point.readNamed(arguments, 'from'),
+				next = Base.peek(arguments);
+			this.x = point.x;
+			this.y = point.y;
+			if (next && next.x !== undefined || Base.hasNamed(arguments, 'to')) {
+				var to = Point.readNamed(arguments, 'to');
+				this.width = to.x - point.x;
+				this.height = to.y - point.y;
+				if (this.width < 0) {
+					this.x = to.x;
+					this.width = -this.width;
+				}
+				if (this.height < 0) {
+					this.y = to.y;
+					this.height = -this.height;
+				}
+			} else {
+				var size = Size.read(arguments);
+				this.width = size.width;
+				this.height = size.height;
+			}
+			read = arguments.__index;
+		}
+		if (this.__read)
+			this.__read = read;
+	},
+
+	set: function(x, y, width, height) {
+		this.x = x;
+		this.y = y;
+		this.width = width;
+		this.height = height;
+		return this;
+	},
+
+	clone: function() {
+		return new Rectangle(this.x, this.y, this.width, this.height);
+	},
+
+	equals: function(rect) {
+		var rt = Base.isPlainValue(rect)
+				? Rectangle.read(arguments)
+				: rect;
+		return rt === this
+				|| rt && this.x === rt.x && this.y === rt.y
+					&& this.width === rt.width && this.height === rt.height
+				|| false;
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '{ x: ' + f.number(this.x)
+				+ ', y: ' + f.number(this.y)
+				+ ', width: ' + f.number(this.width)
+				+ ', height: ' + f.number(this.height)
+				+ ' }';
+	},
+
+	_serialize: function(options) {
+		var f = options.formatter;
+		return [f.number(this.x),
+				f.number(this.y),
+				f.number(this.width),
+				f.number(this.height)];
+	},
+
+	getPoint: function(_dontLink) {
+		var ctor = _dontLink ? Point : LinkedPoint;
+		return new ctor(this.x, this.y, this, 'setPoint');
+	},
+
+	setPoint: function() {
+		var point = Point.read(arguments);
+		this.x = point.x;
+		this.y = point.y;
+	},
+
+	getSize: function(_dontLink) {
+		var ctor = _dontLink ? Size : LinkedSize;
+		return new ctor(this.width, this.height, this, 'setSize');
+	},
+
+	setSize: function() {
+		var size = Size.read(arguments);
+		if (this._fixX)
+			this.x += (this.width - size.width) * this._fixX;
+		if (this._fixY)
+			this.y += (this.height - size.height) * this._fixY;
+		this.width = size.width;
+		this.height = size.height;
+		this._fixW = 1;
+		this._fixH = 1;
+	},
+
+	getLeft: function() {
+		return this.x;
+	},
+
+	setLeft: function(left) {
+		if (!this._fixW)
+			this.width -= left - this.x;
+		this.x = left;
+		this._fixX = 0;
+	},
+
+	getTop: function() {
+		return this.y;
+	},
+
+	setTop: function(top) {
+		if (!this._fixH)
+			this.height -= top - this.y;
+		this.y = top;
+		this._fixY = 0;
+	},
+
+	getRight: function() {
+		return this.x + this.width;
+	},
+
+	setRight: function(right) {
+		if (this._fixX !== undefined && this._fixX !== 1)
+			this._fixW = 0;
+		if (this._fixW)
+			this.x = right - this.width;
+		else
+			this.width = right - this.x;
+		this._fixX = 1;
+	},
+
+	getBottom: function() {
+		return this.y + this.height;
+	},
+
+	setBottom: function(bottom) {
+		if (this._fixY !== undefined && this._fixY !== 1)
+			this._fixH = 0;
+		if (this._fixH)
+			this.y = bottom - this.height;
+		else
+			this.height = bottom - this.y;
+		this._fixY = 1;
+	},
+
+	getCenterX: function() {
+		return this.x + this.width * 0.5;
+	},
+
+	setCenterX: function(x) {
+		this.x = x - this.width * 0.5;
+		this._fixX = 0.5;
+	},
+
+	getCenterY: function() {
+		return this.y + this.height * 0.5;
+	},
+
+	setCenterY: function(y) {
+		this.y = y - this.height * 0.5;
+		this._fixY = 0.5;
+	},
+
+	getCenter: function(_dontLink) {
+		var ctor = _dontLink ? Point : LinkedPoint;
+		return new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');
+	},
+
+	setCenter: function() {
+		var point = Point.read(arguments);
+		this.setCenterX(point.x);
+		this.setCenterY(point.y);
+		return this;
+	},
+
+	getArea: function() {
+		return this.width * this.height;
+	},
+
+	isEmpty: function() {
+		return this.width === 0 || this.height === 0;
+	},
+
+	contains: function(arg) {
+		return arg && arg.width !== undefined
+				|| (Array.isArray(arg) ? arg : arguments).length === 4
+				? this._containsRectangle(Rectangle.read(arguments))
+				: this._containsPoint(Point.read(arguments));
+	},
+
+	_containsPoint: function(point) {
+		var x = point.x,
+			y = point.y;
+		return x >= this.x && y >= this.y
+				&& x <= this.x + this.width
+				&& y <= this.y + this.height;
+	},
+
+	_containsRectangle: function(rect) {
+		var x = rect.x,
+			y = rect.y;
+		return x >= this.x && y >= this.y
+				&& x + rect.width <= this.x + this.width
+				&& y + rect.height <= this.y + this.height;
+	},
+
+	intersects: function() {
+		var rect = Rectangle.read(arguments);
+		return rect.x + rect.width > this.x
+				&& rect.y + rect.height > this.y
+				&& rect.x < this.x + this.width
+				&& rect.y < this.y + this.height;
+	},
+
+	touches: function() {
+		var rect = Rectangle.read(arguments);
+		return rect.x + rect.width >= this.x
+				&& rect.y + rect.height >= this.y
+				&& rect.x <= this.x + this.width
+				&& rect.y <= this.y + this.height;
+	},
+
+	intersect: function() {
+		var rect = Rectangle.read(arguments),
+			x1 = Math.max(this.x, rect.x),
+			y1 = Math.max(this.y, rect.y),
+			x2 = Math.min(this.x + this.width, rect.x + rect.width),
+			y2 = Math.min(this.y + this.height, rect.y + rect.height);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	},
+
+	unite: function() {
+		var rect = Rectangle.read(arguments),
+			x1 = Math.min(this.x, rect.x),
+			y1 = Math.min(this.y, rect.y),
+			x2 = Math.max(this.x + this.width, rect.x + rect.width),
+			y2 = Math.max(this.y + this.height, rect.y + rect.height);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	},
+
+	include: function() {
+		var point = Point.read(arguments);
+		var x1 = Math.min(this.x, point.x),
+			y1 = Math.min(this.y, point.y),
+			x2 = Math.max(this.x + this.width, point.x),
+			y2 = Math.max(this.y + this.height, point.y);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	},
+
+	expand: function() {
+		var amount = Size.read(arguments),
+			hor = amount.width,
+			ver = amount.height;
+		return new Rectangle(this.x - hor / 2, this.y - ver / 2,
+				this.width + hor, this.height + ver);
+	},
+
+	scale: function(hor, ver) {
+		return this.expand(this.width * hor - this.width,
+				this.height * (ver === undefined ? hor : ver) - this.height);
+	}
+}, Base.each([
+		['Top', 'Left'], ['Top', 'Right'],
+		['Bottom', 'Left'], ['Bottom', 'Right'],
+		['Left', 'Center'], ['Top', 'Center'],
+		['Right', 'Center'], ['Bottom', 'Center']
+	],
+	function(parts, index) {
+		var part = parts.join(''),
+			xFirst = /^[RL]/.test(part);
+		if (index >= 4)
+			parts[1] += xFirst ? 'Y' : 'X';
+		var x = parts[xFirst ? 0 : 1],
+			y = parts[xFirst ? 1 : 0],
+			getX = 'get' + x,
+			getY = 'get' + y,
+			setX = 'set' + x,
+			setY = 'set' + y,
+			get = 'get' + part,
+			set = 'set' + part;
+		this[get] = function(_dontLink) {
+			var ctor = _dontLink ? Point : LinkedPoint;
+			return new ctor(this[getX](), this[getY](), this, set);
+		};
+		this[set] = function() {
+			var point = Point.read(arguments);
+			this[setX](point.x);
+			this[setY](point.y);
+		};
+	}, {
+		beans: true
+	}
+));
+
+var LinkedRectangle = Rectangle.extend({
+	initialize: function Rectangle(x, y, width, height, owner, setter) {
+		this.set(x, y, width, height, true);
+		this._owner = owner;
+		this._setter = setter;
+	},
+
+	set: function(x, y, width, height, _dontNotify) {
+		this._x = x;
+		this._y = y;
+		this._width = width;
+		this._height = height;
+		if (!_dontNotify)
+			this._owner[this._setter](this);
+		return this;
+	}
+},
+new function() {
+	var proto = Rectangle.prototype;
+
+	return Base.each(['x', 'y', 'width', 'height'], function(key) {
+		var part = Base.capitalize(key),
+			internal = '_' + key;
+		this['get' + part] = function() {
+			return this[internal];
+		};
+
+		this['set' + part] = function(value) {
+			this[internal] = value;
+			if (!this._dontNotify)
+				this._owner[this._setter](this);
+		};
+	}, Base.each(['Point', 'Size', 'Center',
+			'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',
+			'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
+			'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],
+		function(key) {
+			var name = 'set' + key;
+			this[name] = function() {
+				this._dontNotify = true;
+				proto[name].apply(this, arguments);
+				this._dontNotify = false;
+				this._owner[this._setter](this);
+			};
+		}, {
+			isSelected: function() {
+				return !!(this._owner._selection & 2);
+			},
+
+			setSelected: function(selected) {
+				var owner = this._owner;
+				if (owner.changeSelection) {
+					owner.changeSelection(2, selected);
+				}
+			}
+		})
+	);
+});
+
+var Matrix = Base.extend({
+	_class: 'Matrix',
+
+	initialize: function Matrix(arg) {
+		var count = arguments.length,
+			ok = true;
+		if (count === 6) {
+			this.set.apply(this, arguments);
+		} else if (count === 1) {
+			if (arg instanceof Matrix) {
+				this.set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty);
+			} else if (Array.isArray(arg)) {
+				this.set.apply(this, arg);
+			} else {
+				ok = false;
+			}
+		} else if (count === 0) {
+			this.reset();
+		} else {
+			ok = false;
+		}
+		if (!ok) {
+			throw new Error('Unsupported matrix parameters');
+		}
+	},
+
+	set: function(a, b, c, d, tx, ty, _dontNotify) {
+		this._a = a;
+		this._b = b;
+		this._c = c;
+		this._d = d;
+		this._tx = tx;
+		this._ty = ty;
+		if (!_dontNotify)
+			this._changed();
+		return this;
+	},
+
+	_serialize: function(options, dictionary) {
+		return Base.serialize(this.getValues(), options, true, dictionary);
+	},
+
+	_changed: function() {
+		var owner = this._owner;
+		if (owner) {
+			if (owner._applyMatrix) {
+				owner.transform(null, true);
+			} else {
+				owner._changed(9);
+			}
+		}
+	},
+
+	clone: function() {
+		return new Matrix(this._a, this._b, this._c, this._d,
+				this._tx, this._ty);
+	},
+
+	equals: function(mx) {
+		return mx === this || mx && this._a === mx._a && this._b === mx._b
+				&& this._c === mx._c && this._d === mx._d
+				&& this._tx === mx._tx && this._ty === mx._ty;
+	},
+
+	toString: function() {
+		var f = Formatter.instance;
+		return '[[' + [f.number(this._a), f.number(this._c),
+					f.number(this._tx)].join(', ') + '], ['
+				+ [f.number(this._b), f.number(this._d),
+					f.number(this._ty)].join(', ') + ']]';
+	},
+
+	reset: function(_dontNotify) {
+		this._a = this._d = 1;
+		this._b = this._c = this._tx = this._ty = 0;
+		if (!_dontNotify)
+			this._changed();
+		return this;
+	},
+
+	apply: function(recursively, _setApplyMatrix) {
+		var owner = this._owner;
+		if (owner) {
+			owner.transform(null, true, Base.pick(recursively, true),
+					_setApplyMatrix);
+			return this.isIdentity();
+		}
+		return false;
+	},
+
+	translate: function() {
+		var point = Point.read(arguments),
+			x = point.x,
+			y = point.y;
+		this._tx += x * this._a + y * this._c;
+		this._ty += x * this._b + y * this._d;
+		this._changed();
+		return this;
+	},
+
+	scale: function() {
+		var scale = Point.read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		if (center)
+			this.translate(center);
+		this._a *= scale.x;
+		this._b *= scale.x;
+		this._c *= scale.y;
+		this._d *= scale.y;
+		if (center)
+			this.translate(center.negate());
+		this._changed();
+		return this;
+	},
+
+	rotate: function(angle ) {
+		angle *= Math.PI / 180;
+		var center = Point.read(arguments, 1),
+			x = center.x,
+			y = center.y,
+			cos = Math.cos(angle),
+			sin = Math.sin(angle),
+			tx = x - x * cos + y * sin,
+			ty = y - x * sin - y * cos,
+			a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d;
+		this._a = cos * a + sin * c;
+		this._b = cos * b + sin * d;
+		this._c = -sin * a + cos * c;
+		this._d = -sin * b + cos * d;
+		this._tx += tx * a + ty * c;
+		this._ty += tx * b + ty * d;
+		this._changed();
+		return this;
+	},
+
+	shear: function() {
+		var shear = Point.read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		if (center)
+			this.translate(center);
+		var a = this._a,
+			b = this._b;
+		this._a += shear.y * this._c;
+		this._b += shear.y * this._d;
+		this._c += shear.x * a;
+		this._d += shear.x * b;
+		if (center)
+			this.translate(center.negate());
+		this._changed();
+		return this;
+	},
+
+	skew: function() {
+		var skew = Point.read(arguments),
+			center = Point.read(arguments, 0, { readNull: true }),
+			toRadians = Math.PI / 180,
+			shear = new Point(Math.tan(skew.x * toRadians),
+				Math.tan(skew.y * toRadians));
+		return this.shear(shear, center);
+	},
+
+	append: function(mx) {
+		if (mx) {
+			var a1 = this._a,
+				b1 = this._b,
+				c1 = this._c,
+				d1 = this._d,
+				a2 = mx._a,
+				b2 = mx._c,
+				c2 = mx._b,
+				d2 = mx._d,
+				tx2 = mx._tx,
+				ty2 = mx._ty;
+			this._a = a2 * a1 + c2 * c1;
+			this._c = b2 * a1 + d2 * c1;
+			this._b = a2 * b1 + c2 * d1;
+			this._d = b2 * b1 + d2 * d1;
+			this._tx += tx2 * a1 + ty2 * c1;
+			this._ty += tx2 * b1 + ty2 * d1;
+			this._changed();
+		}
+		return this;
+	},
+
+	prepend: function(mx) {
+		if (mx) {
+			var a1 = this._a,
+				b1 = this._b,
+				c1 = this._c,
+				d1 = this._d,
+				tx1 = this._tx,
+				ty1 = this._ty,
+				a2 = mx._a,
+				b2 = mx._c,
+				c2 = mx._b,
+				d2 = mx._d,
+				tx2 = mx._tx,
+				ty2 = mx._ty;
+			this._a = a2 * a1 + b2 * b1;
+			this._c = a2 * c1 + b2 * d1;
+			this._b = c2 * a1 + d2 * b1;
+			this._d = c2 * c1 + d2 * d1;
+			this._tx = a2 * tx1 + b2 * ty1 + tx2;
+			this._ty = c2 * tx1 + d2 * ty1 + ty2;
+			this._changed();
+		}
+		return this;
+	},
+
+	appended: function(mx) {
+		return this.clone().append(mx);
+	},
+
+	prepended: function(mx) {
+		return this.clone().prepend(mx);
+	},
+
+	invert: function() {
+		var a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d,
+			tx = this._tx,
+			ty = this._ty,
+			det = a * d - b * c,
+			res = null;
+		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
+			this._a = d / det;
+			this._b = -b / det;
+			this._c = -c / det;
+			this._d = a / det;
+			this._tx = (c * ty - d * tx) / det;
+			this._ty = (b * tx - a * ty) / det;
+			res = this;
+		}
+		return res;
+	},
+
+	inverted: function() {
+		return this.clone().invert();
+	},
+
+	concatenate: '#append',
+	preConcatenate: '#prepend',
+	chain: '#appended',
+
+	_shiftless: function() {
+		return new Matrix(this._a, this._b, this._c, this._d, 0, 0);
+	},
+
+	_orNullIfIdentity: function() {
+		return this.isIdentity() ? null : this;
+	},
+
+	isIdentity: function() {
+		return this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1
+				&& this._tx === 0 && this._ty === 0;
+	},
+
+	isInvertible: function() {
+		var det = this._a * this._d - this._c * this._b;
+		return det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);
+	},
+
+	isSingular: function() {
+		return !this.isInvertible();
+	},
+
+	transform: function( src, dst, count) {
+		return arguments.length < 3
+			? this._transformPoint(Point.read(arguments))
+			: this._transformCoordinates(src, dst, count);
+	},
+
+	_transformPoint: function(point, dest, _dontNotify) {
+		var x = point.x,
+			y = point.y;
+		if (!dest)
+			dest = new Point();
+		return dest.set(
+				x * this._a + y * this._c + this._tx,
+				x * this._b + y * this._d + this._ty,
+				_dontNotify);
+	},
+
+	_transformCoordinates: function(src, dst, count) {
+		for (var i = 0, max = 2 * count; i < max; i += 2) {
+			var x = src[i],
+				y = src[i + 1];
+			dst[i] = x * this._a + y * this._c + this._tx;
+			dst[i + 1] = x * this._b + y * this._d + this._ty;
+		}
+		return dst;
+	},
+
+	_transformCorners: function(rect) {
+		var x1 = rect.x,
+			y1 = rect.y,
+			x2 = x1 + rect.width,
+			y2 = y1 + rect.height,
+			coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];
+		return this._transformCoordinates(coords, coords, 4);
+	},
+
+	_transformBounds: function(bounds, dest, _dontNotify) {
+		var coords = this._transformCorners(bounds),
+			min = coords.slice(0, 2),
+			max = min.slice();
+		for (var i = 2; i < 8; i++) {
+			var val = coords[i],
+				j = i & 1;
+			if (val < min[j]) {
+				min[j] = val;
+			} else if (val > max[j]) {
+				max[j] = val;
+			}
+		}
+		if (!dest)
+			dest = new Rectangle();
+		return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1],
+				_dontNotify);
+	},
+
+	inverseTransform: function() {
+		return this._inverseTransform(Point.read(arguments));
+	},
+
+	_inverseTransform: function(point, dest, _dontNotify) {
+		var a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d,
+			tx = this._tx,
+			ty = this._ty,
+			det = a * d - b * c,
+			res = null;
+		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
+			var x = point.x - this._tx,
+				y = point.y - this._ty;
+			if (!dest)
+				dest = new Point();
+			res = dest.set(
+					(x * d - y * c) / det,
+					(y * a - x * b) / det,
+					_dontNotify);
+		}
+		return res;
+	},
+
+	decompose: function() {
+		var a = this._a,
+			b = this._b,
+			c = this._c,
+			d = this._d,
+			det = a * d - b * c,
+			sqrt = Math.sqrt,
+			atan2 = Math.atan2,
+			degrees = 180 / Math.PI,
+			rotate,
+			scale,
+			skew;
+		if (a !== 0 || b !== 0) {
+			var r = sqrt(a * a + b * b);
+			rotate = Math.acos(a / r) * (b > 0 ? 1 : -1);
+			scale = [r, det / r];
+			skew = [atan2(a * c + b * d, r * r), 0];
+		} else if (c !== 0 || d !== 0) {
+			var s = sqrt(c * c + d * d);
+			rotate = Math.asin(c / s)  * (d > 0 ? 1 : -1);
+			scale = [det / s, s];
+			skew = [0, atan2(a * c + b * d, s * s)];
+		} else {
+			rotate = 0;
+			skew = scale = [0, 0];
+		}
+		return {
+			translation: this.getTranslation(),
+			rotation: rotate * degrees,
+			scaling: new Point(scale),
+			skewing: new Point(skew[0] * degrees, skew[1] * degrees)
+		};
+	},
+
+	getValues: function() {
+		return [ this._a, this._b, this._c, this._d, this._tx, this._ty ];
+	},
+
+	getTranslation: function() {
+		return new Point(this._tx, this._ty);
+	},
+
+	getScaling: function() {
+		return (this.decompose() || {}).scaling;
+	},
+
+	getRotation: function() {
+		return (this.decompose() || {}).rotation;
+	},
+
+	applyToContext: function(ctx) {
+		if (!this.isIdentity()) {
+			ctx.transform(this._a, this._b, this._c, this._d,
+					this._tx, this._ty);
+		}
+	}
+}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {
+	var part = Base.capitalize(key),
+		prop = '_' + key;
+	this['get' + part] = function() {
+		return this[prop];
+	};
+	this['set' + part] = function(value) {
+		this[prop] = value;
+		this._changed();
+	};
+}, {}));
+
+var Line = Base.extend({
+	_class: 'Line',
+
+	initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
+		var asVector = false;
+		if (arguments.length >= 4) {
+			this._px = arg0;
+			this._py = arg1;
+			this._vx = arg2;
+			this._vy = arg3;
+			asVector = arg4;
+		} else {
+			this._px = arg0.x;
+			this._py = arg0.y;
+			this._vx = arg1.x;
+			this._vy = arg1.y;
+			asVector = arg2;
+		}
+		if (!asVector) {
+			this._vx -= this._px;
+			this._vy -= this._py;
+		}
+	},
+
+	getPoint: function() {
+		return new Point(this._px, this._py);
+	},
+
+	getVector: function() {
+		return new Point(this._vx, this._vy);
+	},
+
+	getLength: function() {
+		return this.getVector().getLength();
+	},
+
+	intersect: function(line, isInfinite) {
+		return Line.intersect(
+				this._px, this._py, this._vx, this._vy,
+				line._px, line._py, line._vx, line._vy,
+				true, isInfinite);
+	},
+
+	getSide: function(point, isInfinite) {
+		return Line.getSide(
+				this._px, this._py, this._vx, this._vy,
+				point.x, point.y, true, isInfinite);
+	},
+
+	getDistance: function(point) {
+		return Math.abs(Line.getSignedDistance(
+				this._px, this._py, this._vx, this._vy,
+				point.x, point.y, true));
+	},
+
+	isCollinear: function(line) {
+		return Point.isCollinear(this._vx, this._vy, line._vx, line._vy);
+	},
+
+	isOrthogonal: function(line) {
+		return Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);
+	},
+
+	statics: {
+		intersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,
+				isInfinite) {
+			if (!asVector) {
+				v1x -= p1x;
+				v1y -= p1y;
+				v2x -= p2x;
+				v2y -= p2y;
+			}
+			var cross = v1x * v2y - v1y * v2x;
+			if (!Numerical.isZero(cross)) {
+				var dx = p1x - p2x,
+					dy = p1y - p2y,
+					u1 = (v2x * dy - v2y * dx) / cross,
+					u2 = (v1x * dy - v1y * dx) / cross,
+					epsilon = 1e-12,
+					uMin = -epsilon,
+					uMax = 1 + epsilon;
+				if (isInfinite
+						|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {
+					if (!isInfinite) {
+						u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;
+					}
+					return new Point(
+							p1x + u1 * v1x,
+							p1y + u1 * v1y);
+				}
+			}
+		},
+
+		getSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {
+			if (!asVector) {
+				vx -= px;
+				vy -= py;
+			}
+			var v2x = x - px,
+				v2y = y - py,
+				ccw = v2x * vy - v2y * vx;
+			if (ccw === 0 && !isInfinite) {
+				ccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);
+				if (ccw >= 0 && ccw <= 1)
+					ccw = 0;
+			}
+			return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
+		},
+
+		getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
+			if (!asVector) {
+				vx -= px;
+				vy -= py;
+			}
+			return vx === 0 ? vy > 0 ? x - px : px - x
+				 : vy === 0 ? vx < 0 ? y - py : py - y
+				 : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);
+		}
+	}
+});
+
+var Project = PaperScopeItem.extend({
+	_class: 'Project',
+	_list: 'projects',
+	_reference: 'project',
+	_compactSerialize: true,
+
+	initialize: function Project(element) {
+		PaperScopeItem.call(this, true);
+		this._children = [];
+		this._namedChildren = {};
+		this._activeLayer = null;
+		this._currentStyle = new Style(null, null, this);
+		this._view = View.create(this,
+				element || CanvasProvider.getCanvas(1, 1));
+		this._selectionItems = {};
+		this._selectionCount = 0;
+		this._updateVersion = 0;
+	},
+
+	_serialize: function(options, dictionary) {
+		return Base.serialize(this._children, options, true, dictionary);
+	},
+
+	_changed: function(flags, item) {
+		if (flags & 1) {
+			var view = this._view;
+			if (view) {
+				view._needsUpdate = true;
+				if (!view._requested && view._autoUpdate)
+					view.requestUpdate();
+			}
+		}
+		var changes = this._changes;
+		if (changes && item) {
+			var changesById = this._changesById,
+				id = item._id,
+				entry = changesById[id];
+			if (entry) {
+				entry.flags |= flags;
+			} else {
+				changes.push(changesById[id] = { item: item, flags: flags });
+			}
+		}
+	},
+
+	clear: function() {
+		var children = this._children;
+		for (var i = children.length - 1; i >= 0; i--)
+			children[i].remove();
+	},
+
+	isEmpty: function() {
+		return this._children.length === 0;
+	},
+
+	remove: function remove() {
+		if (!remove.base.call(this))
+			return false;
+		if (this._view)
+			this._view.remove();
+		return true;
+	},
+
+	getView: function() {
+		return this._view;
+	},
+
+	getCurrentStyle: function() {
+		return this._currentStyle;
+	},
+
+	setCurrentStyle: function(style) {
+		this._currentStyle.initialize(style);
+	},
+
+	getIndex: function() {
+		return this._index;
+	},
+
+	getOptions: function() {
+		return this._scope.settings;
+	},
+
+	getLayers: function() {
+		return this._children;
+	},
+
+	getActiveLayer: function() {
+		return this._activeLayer || new Layer({ project: this, insert: true });
+	},
+
+	getSymbolDefinitions: function() {
+		var definitions = [],
+			ids = {};
+		this.getItems({
+			class: SymbolItem,
+			match: function(item) {
+				var definition = item._definition,
+					id = definition._id;
+				if (!ids[id]) {
+					ids[id] = true;
+					definitions.push(definition);
+				}
+				return false;
+			}
+		});
+		return definitions;
+	},
+
+	getSymbols: 'getSymbolDefinitions',
+
+	getSelectedItems: function() {
+		var selectionItems = this._selectionItems,
+			items = [];
+		for (var id in selectionItems) {
+			var item = selectionItems[id],
+				selection = item._selection;
+			if (selection & 1 && item.isInserted()) {
+				items.push(item);
+			} else if (!selection) {
+				this._updateSelection(item);
+			}
+		}
+		return items;
+	},
+
+	_updateSelection: function(item) {
+		var id = item._id,
+			selectionItems = this._selectionItems;
+		if (item._selection) {
+			if (selectionItems[id] !== item) {
+				this._selectionCount++;
+				selectionItems[id] = item;
+			}
+		} else if (selectionItems[id] === item) {
+			this._selectionCount--;
+			delete selectionItems[id];
+		}
+	},
+
+	selectAll: function() {
+		var children = this._children;
+		for (var i = 0, l = children.length; i < l; i++)
+			children[i].setFullySelected(true);
+	},
+
+	deselectAll: function() {
+		var selectionItems = this._selectionItems;
+		for (var i in selectionItems)
+			selectionItems[i].setFullySelected(false);
+	},
+
+	addLayer: function(layer) {
+		return this.insertLayer(undefined, layer);
+	},
+
+	insertLayer: function(index, layer) {
+		if (layer instanceof Layer) {
+			layer._remove(false, true);
+			Base.splice(this._children, [layer], index, 0);
+			layer._setProject(this, true);
+			var name = layer._name;
+			if (name)
+				layer.setName(name);
+			if (this._changes)
+				layer._changed(5);
+			if (!this._activeLayer)
+				this._activeLayer = layer;
+		} else {
+			layer = null;
+		}
+		return layer;
+	},
+
+	_insertItem: function(index, item, _preserve, _created) {
+		item = this.insertLayer(index, item)
+				|| (this._activeLayer || this._insertItem(undefined,
+						new Layer(Item.NO_INSERT), true, true))
+						.insertChild(index, item, _preserve);
+		if (_created && item.activate)
+			item.activate();
+		return item;
+	},
+
+	getItems: function(options) {
+		return Item._getItems(this, options);
+	},
+
+	getItem: function(options) {
+		return Item._getItems(this, options, null, null, true)[0] || null;
+	},
+
+	importJSON: function(json) {
+		this.activate();
+		var layer = this._activeLayer;
+		return Base.importJSON(json, layer && layer.isEmpty() && layer);
+	},
+
+	removeOn: function(type) {
+		var sets = this._removeSets;
+		if (sets) {
+			if (type === 'mouseup')
+				sets.mousedrag = null;
+			var set = sets[type];
+			if (set) {
+				for (var id in set) {
+					var item = set[id];
+					for (var key in sets) {
+						var other = sets[key];
+						if (other && other != set)
+							delete other[item._id];
+					}
+					item.remove();
+				}
+				sets[type] = null;
+			}
+		}
+	},
+
+	draw: function(ctx, matrix, pixelRatio) {
+		this._updateVersion++;
+		ctx.save();
+		matrix.applyToContext(ctx);
+		var children = this._children,
+			param = new Base({
+				offset: new Point(0, 0),
+				pixelRatio: pixelRatio,
+				viewMatrix: matrix.isIdentity() ? null : matrix,
+				matrices: [new Matrix()],
+				updateMatrix: true
+			});
+		for (var i = 0, l = children.length; i < l; i++) {
+			children[i].draw(ctx, param);
+		}
+		ctx.restore();
+
+		if (this._selectionCount > 0) {
+			ctx.save();
+			ctx.strokeWidth = 1;
+			var items = this._selectionItems,
+				size = this._scope.settings.handleSize,
+				version = this._updateVersion;
+			for (var id in items) {
+				items[id]._drawSelection(ctx, matrix, size, items, version);
+			}
+			ctx.restore();
+		}
+	}
+});
+
+var Item = Base.extend(Emitter, {
+	statics: {
+		extend: function extend(src) {
+			if (src._serializeFields)
+				src._serializeFields = Base.set({},
+					this.prototype._serializeFields, src._serializeFields);
+			return extend.base.apply(this, arguments);
+		},
+
+		NO_INSERT: { insert: false }
+	},
+
+	_class: 'Item',
+	_name: null,
+	_applyMatrix: true,
+	_canApplyMatrix: true,
+	_canScaleStroke: false,
+	_pivot: null,
+	_visible: true,
+	_blendMode: 'normal',
+	_opacity: 1,
+	_locked: false,
+	_guide: false,
+	_clipMask: false,
+	_selection: 0,
+	_selectBounds: true,
+	_selectChildren: false,
+	_serializeFields: {
+		name: null,
+		applyMatrix: null,
+		matrix: new Matrix(),
+		pivot: null,
+		visible: true,
+		blendMode: 'normal',
+		opacity: 1,
+		locked: false,
+		guide: false,
+		clipMask: false,
+		selected: false,
+		data: {}
+	}
+},
+new function() {
+	var handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
+			'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];
+	return Base.each(handlers,
+		function(name) {
+			this._events[name] = {
+				install: function(type) {
+					this.getView()._countItemEvent(type, 1);
+				},
+
+				uninstall: function(type) {
+					this.getView()._countItemEvent(type, -1);
+				}
+			};
+		}, {
+			_events: {
+				onFrame: {
+					install: function() {
+						this.getView()._animateItem(this, true);
+					},
+
+					uninstall: function() {
+						this.getView()._animateItem(this, false);
+					}
+				},
+
+				onLoad: {},
+				onError: {}
+			},
+			statics: {
+				_itemHandlers: handlers
+			}
+		}
+	);
+}, {
+	initialize: function Item() {
+	},
+
+	_initialize: function(props, point) {
+		var hasProps = props && Base.isPlainObject(props),
+			internal = hasProps && props.internal === true,
+			matrix = this._matrix = new Matrix(),
+			project = hasProps && props.project || paper.project,
+			settings = paper.settings;
+		this._id = internal ? null : UID.get();
+		this._parent = this._index = null;
+		this._applyMatrix = this._canApplyMatrix && settings.applyMatrix;
+		if (point)
+			matrix.translate(point);
+		matrix._owner = this;
+		this._style = new Style(project._currentStyle, this, project);
+		if (internal || hasProps && props.insert === false
+			|| !settings.insertItems && !(hasProps && props.insert === true)) {
+			this._setProject(project);
+		} else {
+			(hasProps && props.parent || project)
+					._insertItem(undefined, this, true, true);
+		}
+		if (hasProps && props !== Item.NO_INSERT) {
+			Base.filter(this, props, {
+				internal: true, insert: true, project: true, parent: true
+			});
+		}
+		return hasProps;
+	},
+
+	_serialize: function(options, dictionary) {
+		var props = {},
+			that = this;
+
+		function serialize(fields) {
+			for (var key in fields) {
+				var value = that[key];
+				if (!Base.equals(value, key === 'leading'
+						? fields.fontSize * 1.2 : fields[key])) {
+					props[key] = Base.serialize(value, options,
+							key !== 'data', dictionary);
+				}
+			}
+		}
+
+		serialize(this._serializeFields);
+		if (!(this instanceof Group))
+			serialize(this._style._defaults);
+		return [ this._class, props ];
+	},
+
+	_changed: function(flags) {
+		var symbol = this._symbol,
+			cacheParent = this._parent || symbol,
+			project = this._project;
+		if (flags & 8) {
+			this._bounds = this._position = this._decomposed =
+					this._globalMatrix = undefined;
+		}
+		if (cacheParent
+				&& (flags & 40)) {
+			Item._clearBoundsCache(cacheParent);
+		}
+		if (flags & 2) {
+			Item._clearBoundsCache(this);
+		}
+		if (project)
+			project._changed(flags, this);
+		if (symbol)
+			symbol._changed(flags);
+	},
+
+	set: function(props) {
+		if (props)
+			this._set(props);
+		return this;
+	},
+
+	getId: function() {
+		return this._id;
+	},
+
+	getName: function() {
+		return this._name;
+	},
+
+	setName: function(name) {
+
+		if (this._name)
+			this._removeNamed();
+		if (name === (+name) + '')
+			throw new Error(
+					'Names consisting only of numbers are not supported.');
+		var owner = this._getOwner();
+		if (name && owner) {
+			var children = owner._children,
+				namedChildren = owner._namedChildren;
+			(namedChildren[name] = namedChildren[name] || []).push(this);
+			if (!(name in children))
+				children[name] = this;
+		}
+		this._name = name || undefined;
+		this._changed(128);
+	},
+
+	getStyle: function() {
+		return this._style;
+	},
+
+	setStyle: function(style) {
+		this.getStyle().set(style);
+	}
+}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],
+	function(name) {
+		var part = Base.capitalize(name),
+			name = '_' + name;
+		this['get' + part] = function() {
+			return this[name];
+		};
+		this['set' + part] = function(value) {
+			if (value != this[name]) {
+				this[name] = value;
+				this._changed(name === '_locked'
+						? 128 : 129);
+			}
+		};
+	},
+{}), {
+	beans: true,
+
+	getSelection: function() {
+		return this._selection;
+	},
+
+	setSelection: function(selection) {
+		if (selection !== this._selection) {
+			this._selection = selection;
+			var project = this._project;
+			if (project) {
+				project._updateSelection(this);
+				this._changed(129);
+			}
+		}
+	},
+
+	changeSelection: function(flag, selected) {
+		var selection = this._selection;
+		this.setSelection(selected ? selection | flag : selection & ~flag);
+	},
+
+	isSelected: function() {
+		if (this._selectChildren) {
+			var children = this._children;
+			for (var i = 0, l = children.length; i < l; i++)
+				if (children[i].isSelected())
+					return true;
+		}
+		return !!(this._selection & 1);
+	},
+
+	setSelected: function(selected) {
+		if (this._selectChildren) {
+			var children = this._children;
+			for (var i = 0, l = children.length; i < l; i++)
+				children[i].setSelected(selected);
+		}
+		this.changeSelection(1, selected);
+	},
+
+	isFullySelected: function() {
+		var children = this._children,
+			selected = !!(this._selection & 1);
+		if (children && selected) {
+			for (var i = 0, l = children.length; i < l; i++)
+				if (!children[i].isFullySelected())
+					return false;
+			return true;
+		}
+		return selected;
+	},
+
+	setFullySelected: function(selected) {
+		var children = this._children;
+		if (children) {
+			for (var i = 0, l = children.length; i < l; i++)
+				children[i].setFullySelected(selected);
+		}
+		this.changeSelection(1, selected);
+	},
+
+	isClipMask: function() {
+		return this._clipMask;
+	},
+
+	setClipMask: function(clipMask) {
+		if (this._clipMask != (clipMask = !!clipMask)) {
+			this._clipMask = clipMask;
+			if (clipMask) {
+				this.setFillColor(null);
+				this.setStrokeColor(null);
+			}
+			this._changed(129);
+			if (this._parent)
+				this._parent._changed(1024);
+		}
+	},
+
+	getData: function() {
+		if (!this._data)
+			this._data = {};
+		return this._data;
+	},
+
+	setData: function(data) {
+		this._data = data;
+	},
+
+	getPosition: function(_dontLink) {
+		var position = this._position,
+			ctor = _dontLink ? Point : LinkedPoint;
+		if (!position) {
+			var pivot = this._pivot;
+			position = this._position = pivot
+					? this._matrix._transformPoint(pivot)
+					: this.getBounds().getCenter(true);
+		}
+		return new ctor(position.x, position.y, this, 'setPosition');
+	},
+
+	setPosition: function() {
+		this.translate(Point.read(arguments).subtract(this.getPosition(true)));
+	},
+
+	getPivot: function(_dontLink) {
+		var pivot = this._pivot;
+		if (pivot) {
+			var ctor = _dontLink ? Point : LinkedPoint;
+			pivot = new ctor(pivot.x, pivot.y, this, 'setPivot');
+		}
+		return pivot;
+	},
+
+	setPivot: function() {
+		this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
+		this._position = undefined;
+	}
+}, Base.each({
+		getStrokeBounds: { stroke: true },
+		getHandleBounds: { handle: true },
+		getInternalBounds: { internal: true }
+	},
+	function(options, key) {
+		this[key] = function(matrix) {
+			return this.getBounds(matrix, options);
+		};
+	},
+{
+	beans: true,
+
+	getBounds: function(matrix, options) {
+		var hasMatrix = options || matrix instanceof Matrix,
+			opts = Base.set({}, hasMatrix ? options : matrix,
+					this._boundsOptions);
+		if (!opts.stroke || this.getStrokeScaling())
+			opts.cacheItem = this;
+		var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
+		return arguments.length === 0
+				? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
+						bounds.height, this, 'setBounds')
+				: bounds;
+	},
+
+	setBounds: function() {
+		var rect = Rectangle.read(arguments),
+			bounds = this.getBounds(),
+			_matrix = this._matrix,
+			matrix = new Matrix(),
+			center = rect.getCenter();
+		matrix.translate(center);
+		if (rect.width != bounds.width || rect.height != bounds.height) {
+			if (!_matrix.isInvertible()) {
+				_matrix.initialize(_matrix._backup
+						|| new Matrix().translate(_matrix.getTranslation()));
+				bounds = this.getBounds();
+			}
+			matrix.scale(
+					bounds.width !== 0 ? rect.width / bounds.width : 0,
+					bounds.height !== 0 ? rect.height / bounds.height : 0);
+		}
+		center = bounds.getCenter();
+		matrix.translate(-center.x, -center.y);
+		this.transform(matrix);
+	},
+
+	_getBounds: function(matrix, options) {
+		var children = this._children;
+		if (!children || children.length === 0)
+			return new Rectangle();
+		Item._updateBoundsCache(this, options.cacheItem);
+		return Item._getBounds(children, matrix, options);
+	},
+
+	_getCachedBounds: function(matrix, options) {
+		matrix = matrix && matrix._orNullIfIdentity();
+		var internal = options.internal,
+			cacheItem = options.cacheItem,
+			_matrix = internal ? null : this._matrix._orNullIfIdentity(),
+			cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
+				options.stroke ? 1 : 0,
+				options.handle ? 1 : 0,
+				internal ? 1 : 0
+			].join('');
+		Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
+		if (cacheKey && this._bounds && cacheKey in this._bounds)
+			return this._bounds[cacheKey].rect.clone();
+		var bounds = this._getBounds(matrix || _matrix, options);
+		if (cacheKey) {
+			if (!this._bounds)
+				this._bounds = {};
+			var cached = this._bounds[cacheKey] = {
+				rect: bounds.clone(),
+				internal: options.internal
+			};
+		}
+		return bounds;
+	},
+
+	_getStrokeMatrix: function(matrix, options) {
+		var parent = this.getStrokeScaling() ? null
+				: options && options.internal ? this
+					: this._parent || this._symbol && this._symbol._item,
+			mx = parent ? parent.getViewMatrix().invert() : matrix;
+		return mx && mx._shiftless();
+	},
+
+	statics: {
+		_updateBoundsCache: function(parent, item) {
+			if (parent && item) {
+				var id = item._id,
+					ref = parent._boundsCache = parent._boundsCache || {
+						ids: {},
+						list: []
+					};
+				if (!ref.ids[id]) {
+					ref.list.push(item);
+					ref.ids[id] = item;
+				}
+			}
+		},
+
+		_clearBoundsCache: function(item) {
+			var cache = item._boundsCache;
+			if (cache) {
+				item._bounds = item._position = item._boundsCache = undefined;
+				for (var i = 0, list = cache.list, l = list.length; i < l; i++){
+					var other = list[i];
+					if (other !== item) {
+						other._bounds = other._position = undefined;
+						if (other._boundsCache)
+							Item._clearBoundsCache(other);
+					}
+				}
+			}
+		},
+
+		_getBounds: function(items, matrix, options) {
+			var x1 = Infinity,
+				x2 = -x1,
+				y1 = x1,
+				y2 = x2;
+			options = options || {};
+			for (var i = 0, l = items.length; i < l; i++) {
+				var item = items[i];
+				if (item._visible && !item.isEmpty()) {
+					var rect = item._getCachedBounds(
+						matrix && matrix.appended(item._matrix), options);
+					x1 = Math.min(rect.x, x1);
+					y1 = Math.min(rect.y, y1);
+					x2 = Math.max(rect.x + rect.width, x2);
+					y2 = Math.max(rect.y + rect.height, y2);
+				}
+			}
+			return isFinite(x1)
+					? new Rectangle(x1, y1, x2 - x1, y2 - y1)
+					: new Rectangle();
+		}
+	}
+
+}), {
+	beans: true,
+
+	_decompose: function() {
+		return this._decomposed || (this._decomposed = this._matrix.decompose());
+	},
+
+	getRotation: function() {
+		var decomposed = this._decompose();
+		return decomposed && decomposed.rotation;
+	},
+
+	setRotation: function(rotation) {
+		var current = this.getRotation();
+		if (current != null && rotation != null) {
+			this.rotate(rotation - current);
+		}
+	},
+
+	getScaling: function(_dontLink) {
+		var decomposed = this._decompose(),
+			scaling = decomposed && decomposed.scaling,
+			ctor = _dontLink ? Point : LinkedPoint;
+		return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling');
+	},
+
+	setScaling: function() {
+		var current = this.getScaling(),
+			scaling = Point.read(arguments, 0, { clone: true, readNull: true });
+		if (current && scaling) {
+			this.scale(scaling.x / current.x, scaling.y / current.y);
+		}
+	},
+
+	getMatrix: function() {
+		return this._matrix;
+	},
+
+	setMatrix: function() {
+		var matrix = this._matrix;
+		matrix.initialize.apply(matrix, arguments);
+	},
+
+	getGlobalMatrix: function(_dontClone) {
+		var matrix = this._globalMatrix,
+			updateVersion = this._project._updateVersion;
+		if (matrix && matrix._updateVersion !== updateVersion)
+			matrix = null;
+		if (!matrix) {
+			matrix = this._globalMatrix = this._matrix.clone();
+			var parent = this._parent;
+			if (parent)
+				matrix.prepend(parent.getGlobalMatrix(true));
+			matrix._updateVersion = updateVersion;
+		}
+		return _dontClone ? matrix : matrix.clone();
+	},
+
+	getViewMatrix: function() {
+		return this.getGlobalMatrix().prepend(this.getView()._matrix);
+	},
+
+	getApplyMatrix: function() {
+		return this._applyMatrix;
+	},
+
+	setApplyMatrix: function(apply) {
+		if (this._applyMatrix = this._canApplyMatrix && !!apply)
+			this.transform(null, true);
+	},
+
+	getTransformContent: '#getApplyMatrix',
+	setTransformContent: '#setApplyMatrix',
+}, {
+	getProject: function() {
+		return this._project;
+	},
+
+	_setProject: function(project, installEvents) {
+		if (this._project !== project) {
+			if (this._project)
+				this._installEvents(false);
+			this._project = project;
+			var children = this._children;
+			for (var i = 0, l = children && children.length; i < l; i++)
+				children[i]._setProject(project);
+			installEvents = true;
+		}
+		if (installEvents)
+			this._installEvents(true);
+	},
+
+	getView: function() {
+		return this._project._view;
+	},
+
+	_installEvents: function _installEvents(install) {
+		_installEvents.base.call(this, install);
+		var children = this._children;
+		for (var i = 0, l = children && children.length; i < l; i++)
+			children[i]._installEvents(install);
+	},
+
+	getLayer: function() {
+		var parent = this;
+		while (parent = parent._parent) {
+			if (parent instanceof Layer)
+				return parent;
+		}
+		return null;
+	},
+
+	getParent: function() {
+		return this._parent;
+	},
+
+	setParent: function(item) {
+		return item.addChild(this);
+	},
+
+	_getOwner: '#getParent',
+
+	getChildren: function() {
+		return this._children;
+	},
+
+	setChildren: function(items, _preserve) {
+		this.removeChildren();
+		this.addChildren(items, _preserve);
+	},
+
+	getFirstChild: function() {
+		return this._children && this._children[0] || null;
+	},
+
+	getLastChild: function() {
+		return this._children && this._children[this._children.length - 1]
+				|| null;
+	},
+
+	getNextSibling: function() {
+		var owner = this._getOwner();
+		return owner && owner._children[this._index + 1] || null;
+	},
+
+	getPreviousSibling: function() {
+		var owner = this._getOwner();
+		return owner && owner._children[this._index - 1] || null;
+	},
+
+	getIndex: function() {
+		return this._index;
+	},
+
+	equals: function(item) {
+		return item === this || item && this._class === item._class
+				&& this._style.equals(item._style)
+				&& this._matrix.equals(item._matrix)
+				&& this._locked === item._locked
+				&& this._visible === item._visible
+				&& this._blendMode === item._blendMode
+				&& this._opacity === item._opacity
+				&& this._clipMask === item._clipMask
+				&& this._guide === item._guide
+				&& this._equals(item)
+				|| false;
+	},
+
+	_equals: function(item) {
+		return Base.equals(this._children, item._children);
+	},
+
+	clone: function(options) {
+		var copy = new this.constructor(Item.NO_INSERT),
+			children = this._children,
+			insert = Base.pick(options ? options.insert : undefined,
+					options === undefined || options === true),
+			deep = Base.pick(options ? options.deep : undefined, true);
+		if (children)
+			copy.copyAttributes(this);
+		if (!children || deep)
+			copy.copyContent(this);
+		if (!children)
+			copy.copyAttributes(this);
+		if (insert)
+			copy.insertAbove(this);
+		var name = this._name,
+			parent = this._parent;
+		if (name && parent) {
+			var children = parent._children,
+				orig = name,
+				i = 1;
+			while (children[name])
+				name = orig + ' ' + (i++);
+			if (name !== orig)
+				copy.setName(name);
+		}
+		return copy;
+	},
+
+	copyContent: function(source) {
+		var children = source._children;
+		for (var i = 0, l = children && children.length; i < l; i++) {
+			this.addChild(children[i].clone(false), true);
+		}
+	},
+
+	copyAttributes: function(source, excludeMatrix) {
+		this.setStyle(source._style);
+		var keys = ['_locked', '_visible', '_blendMode', '_opacity',
+				'_clipMask', '_guide'];
+		for (var i = 0, l = keys.length; i < l; i++) {
+			var key = keys[i];
+			if (source.hasOwnProperty(key))
+				this[key] = source[key];
+		}
+		if (!excludeMatrix)
+			this._matrix.initialize(source._matrix);
+		this.setApplyMatrix(source._applyMatrix);
+		this.setPivot(source._pivot);
+		this.setSelection(source._selection);
+		var data = source._data,
+			name = source._name;
+		this._data = data ? Base.clone(data) : null;
+		if (name)
+			this.setName(name);
+	},
+
+	rasterize: function(resolution, insert) {
+		var bounds = this.getStrokeBounds(),
+			scale = (resolution || this.getView().getResolution()) / 72,
+			topLeft = bounds.getTopLeft().floor(),
+			bottomRight = bounds.getBottomRight().ceil(),
+			size = new Size(bottomRight.subtract(topLeft)),
+			raster = new Raster(Item.NO_INSERT);
+		if (!size.isZero()) {
+			var canvas = CanvasProvider.getCanvas(size.multiply(scale)),
+				ctx = canvas.getContext('2d'),
+				matrix = new Matrix().scale(scale).translate(topLeft.negate());
+			ctx.save();
+			matrix.applyToContext(ctx);
+			this.draw(ctx, new Base({ matrices: [matrix] }));
+			ctx.restore();
+			raster.setCanvas(canvas);
+		}
+		raster.transform(new Matrix().translate(topLeft.add(size.divide(2)))
+				.scale(1 / scale));
+		if (insert === undefined || insert)
+			raster.insertAbove(this);
+		return raster;
+	},
+
+	contains: function() {
+		return !!this._contains(
+				this._matrix._inverseTransform(Point.read(arguments)));
+	},
+
+	_contains: function(point) {
+		var children = this._children;
+		if (children) {
+			for (var i = children.length - 1; i >= 0; i--) {
+				if (children[i].contains(point))
+					return true;
+			}
+			return false;
+		}
+		return point.isInside(this.getInternalBounds());
+	},
+
+	isInside: function() {
+		return Rectangle.read(arguments).contains(this.getBounds());
+	},
+
+	_asPathItem: function() {
+		return new Path.Rectangle({
+			rectangle: this.getInternalBounds(),
+			matrix: this._matrix,
+			insert: false,
+		});
+	},
+
+	intersects: function(item, _matrix) {
+		if (!(item instanceof Item))
+			return false;
+		return this._asPathItem().getIntersections(item._asPathItem(), null,
+				_matrix, true).length > 0;
+	}
+},
+new function() {
+	function hitTest() {
+		return this._hitTest(
+				Point.read(arguments),
+				HitResult.getOptions(arguments));
+	}
+
+	function hitTestAll() {
+		var point = Point.read(arguments),
+			options = HitResult.getOptions(arguments),
+			callback = options.match,
+			results = [];
+		options = Base.set({}, options, {
+			match: function(hit) {
+				if (!callback || callback(hit))
+					results.push(hit);
+			}
+		});
+		this._hitTest(point, options);
+		return results;
+	}
+
+	function hitTestChildren(point, options, viewMatrix, _exclude) {
+		var children = this._children;
+		if (children) {
+			for (var i = children.length - 1; i >= 0; i--) {
+				var child = children[i];
+				var res = child !== _exclude && child._hitTest(point, options,
+						viewMatrix);
+				if (res)
+					return res;
+			}
+		}
+		return null;
+	}
+
+	Project.inject({
+		hitTest: hitTest,
+		hitTestAll: hitTestAll,
+		_hitTest: hitTestChildren
+	});
+
+	return {
+		hitTest: hitTest,
+		hitTestAll: hitTestAll,
+		_hitTestChildren: hitTestChildren,
+	};
+}, {
+
+	_hitTest: function(point, options, parentViewMatrix) {
+		if (this._locked || !this._visible || this._guide && !options.guides
+				|| this.isEmpty()) {
+			return null;
+		}
+
+		var matrix = this._matrix,
+			viewMatrix = parentViewMatrix
+					? parentViewMatrix.appended(matrix)
+					: this.getGlobalMatrix().prepend(this.getView()._matrix),
+			strokeMatrix = this.getStrokeScaling()
+					? null
+					: viewMatrix.inverted()._shiftless(),
+			tolerance = Math.max(options.tolerance, 1e-6),
+			tolerancePadding = options._tolerancePadding = new Size(
+					Path._getStrokePadding(tolerance, strokeMatrix));
+		point = matrix._inverseTransform(point);
+		if (!point || !this._children &&
+			!this.getBounds({ internal: true, stroke: true, handle: true })
+				.expand(tolerancePadding.multiply(2))._containsPoint(point)) {
+			return null;
+		}
+
+		var checkSelf = !(options.guides && !this._guide
+				|| options.selected && !this.isSelected()
+				|| options.type && options.type !== Base.hyphenate(this._class)
+				|| options.class && !(this instanceof options.class)),
+			callback = options.match,
+			that = this,
+			bounds,
+			res;
+
+		function match(hit) {
+			return !callback || hit && callback(hit) ? hit : null;
+		}
+
+		function checkBounds(type, part) {
+			var pt = bounds['get' + part]();
+			if (point.subtract(pt).divide(tolerancePadding).length <= 1) {
+				return new HitResult(type, that,
+						{ name: Base.hyphenate(part), point: pt });
+			}
+		}
+
+		if (checkSelf && (options.center || options.bounds) && this._parent) {
+			bounds = this.getInternalBounds();
+			if (options.center) {
+				res = checkBounds('center', 'Center');
+			}
+			if (!res && options.bounds) {
+				var points = [
+					'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
+					'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'
+				];
+				for (var i = 0; i < 8 && !res; i++) {
+					res = checkBounds('bounds', points[i]);
+				}
+			}
+			res = match(res);
+		}
+
+		if (!res) {
+			res = this._hitTestChildren(point, options, viewMatrix)
+				|| checkSelf
+					&& match(this._hitTestSelf(point, options, viewMatrix,
+						strokeMatrix))
+				|| null;
+		}
+		if (res && res.point) {
+			res.point = matrix.transform(res.point);
+		}
+		return res;
+	},
+
+	_hitTestSelf: function(point, options) {
+		if (options.fill && this.hasFill() && this._contains(point))
+			return new HitResult('fill', this);
+	},
+
+	matches: function(name, compare) {
+		function matchObject(obj1, obj2) {
+			for (var i in obj1) {
+				if (obj1.hasOwnProperty(i)) {
+					var val1 = obj1[i],
+						val2 = obj2[i];
+					if (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {
+						if (!matchObject(val1, val2))
+							return false;
+					} else if (!Base.equals(val1, val2)) {
+						return false;
+					}
+				}
+			}
+			return true;
+		}
+		var type = typeof name;
+		if (type === 'object') {
+			for (var key in name) {
+				if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
+					return false;
+			}
+			return true;
+		} else if (type === 'function') {
+			return name(this);
+		} else if (name === 'match') {
+			return compare(this);
+		} else {
+			var value = /^(empty|editable)$/.test(name)
+					? this['is' + Base.capitalize(name)]()
+					: name === 'type'
+						? Base.hyphenate(this._class)
+						: this[name];
+			if (name === 'class') {
+				if (typeof compare === 'function')
+					return this instanceof compare;
+				value = this._class;
+			}
+			if (typeof compare === 'function') {
+				return !!compare(value);
+			} else if (compare) {
+				if (compare.test) {
+					return compare.test(value);
+				} else if (Base.isPlainObject(compare)) {
+					return matchObject(compare, value);
+				}
+			}
+			return Base.equals(value, compare);
+		}
+	},
+
+	getItems: function(options) {
+		return Item._getItems(this, options, this._matrix);
+	},
+
+	getItem: function(options) {
+		return Item._getItems(this, options, this._matrix, null, true)[0]
+				|| null;
+	},
+
+	statics: {
+		_getItems: function _getItems(item, options, matrix, param, firstOnly) {
+			if (!param) {
+				var obj = typeof options === 'object' && options,
+					overlapping = obj && obj.overlapping,
+					inside = obj && obj.inside,
+					bounds = overlapping || inside,
+					rect = bounds && Rectangle.read([bounds]);
+				param = {
+					items: [],
+					recursive: obj && obj.recursive !== false,
+					inside: !!inside,
+					overlapping: !!overlapping,
+					rect: rect,
+					path: overlapping && new Path.Rectangle({
+						rectangle: rect,
+						insert: false
+					})
+				};
+				if (obj) {
+					options = Base.filter({}, options, {
+						recursive: true, inside: true, overlapping: true
+					});
+				}
+			}
+			var children = item._children,
+				items = param.items,
+				rect = param.rect;
+			matrix = rect && (matrix || new Matrix());
+			for (var i = 0, l = children && children.length; i < l; i++) {
+				var child = children[i],
+					childMatrix = matrix && matrix.appended(child._matrix),
+					add = true;
+				if (rect) {
+					var bounds = child.getBounds(childMatrix);
+					if (!rect.intersects(bounds))
+						continue;
+					if (!(rect.contains(bounds)
+							|| param.overlapping && (bounds.contains(rect)
+								|| param.path.intersects(child, childMatrix))))
+						add = false;
+				}
+				if (add && child.matches(options)) {
+					items.push(child);
+					if (firstOnly)
+						break;
+				}
+				if (param.recursive !== false) {
+					_getItems(child, options, childMatrix, param, firstOnly);
+				}
+				if (firstOnly && items.length > 0)
+					break;
+			}
+			return items;
+		}
+	}
+}, {
+
+	importJSON: function(json) {
+		var res = Base.importJSON(json, this);
+		return res !== this ? this.addChild(res) : res;
+	},
+
+	addChild: function(item, _preserve) {
+		return this.insertChild(undefined, item, _preserve);
+	},
+
+	insertChild: function(index, item, _preserve) {
+		var res = item ? this.insertChildren(index, [item], _preserve) : null;
+		return res && res[0];
+	},
+
+	addChildren: function(items, _preserve) {
+		return this.insertChildren(this._children.length, items, _preserve);
+	},
+
+	insertChildren: function(index, items, _preserve, _proto) {
+		var children = this._children;
+		if (children && items && items.length > 0) {
+			items = Array.prototype.slice.apply(items);
+			for (var i = items.length - 1; i >= 0; i--) {
+				var item = items[i];
+				if (!item || _proto && !(item instanceof _proto)) {
+					items.splice(i, 1);
+				} else {
+					item._remove(false, true);
+				}
+			}
+			Base.splice(children, items, index, 0);
+			var project = this._project,
+				notifySelf = project._changes;
+			for (var i = 0, l = items.length; i < l; i++) {
+				var item = items[i],
+					name = item._name;
+				item._parent = this;
+				item._setProject(project, true);
+				if (name)
+					item.setName(name);
+				if (notifySelf)
+					this._changed(5);
+			}
+			this._changed(11);
+		} else {
+			items = null;
+		}
+		return items;
+	},
+
+	_insertItem: '#insertChild',
+
+	_insertAt: function(item, offset, _preserve) {
+		var res = this;
+		if (res !== item) {
+			var owner = item && item._getOwner();
+			if (owner) {
+				res._remove(false, true);
+				owner._insertItem(item._index + offset, res, _preserve);
+			} else {
+				res = null;
+			}
+		}
+		return res;
+	},
+
+	insertAbove: function(item, _preserve) {
+		return this._insertAt(item, 1, _preserve);
+	},
+
+	insertBelow: function(item, _preserve) {
+		return this._insertAt(item, 0, _preserve);
+	},
+
+	sendToBack: function() {
+		var owner = this._getOwner();
+		return owner ? owner._insertItem(0, this) : null;
+	},
+
+	bringToFront: function() {
+		var owner = this._getOwner();
+		return owner ? owner._insertItem(undefined, this) : null;
+	},
+
+	appendTop: '#addChild',
+
+	appendBottom: function(item) {
+		return this.insertChild(0, item);
+	},
+
+	moveAbove: '#insertAbove',
+
+	moveBelow: '#insertBelow',
+
+	copyTo: function(owner) {
+		return owner._insertItem(undefined, this.clone(false));
+	},
+
+	reduce: function(options) {
+		var children = this._children;
+		if (children && children.length === 1) {
+			var child = children[0].reduce(options);
+			if (this._parent) {
+				child.insertAbove(this);
+				this.remove();
+			} else {
+				child.remove();
+			}
+			return child;
+		}
+		return this;
+	},
+
+	_removeNamed: function() {
+		var owner = this._getOwner();
+		if (owner) {
+			var children = owner._children,
+				namedChildren = owner._namedChildren,
+				name = this._name,
+				namedArray = namedChildren[name],
+				index = namedArray ? namedArray.indexOf(this) : -1;
+			if (index !== -1) {
+				if (children[name] == this)
+					delete children[name];
+				namedArray.splice(index, 1);
+				if (namedArray.length) {
+					children[name] = namedArray[0];
+				} else {
+					delete namedChildren[name];
+				}
+			}
+		}
+	},
+
+	_remove: function(notifySelf, notifyParent) {
+		var owner = this._getOwner(),
+			project = this._project,
+			index = this._index;
+		if (owner) {
+			if (index != null) {
+				if (project._activeLayer === this)
+					project._activeLayer = this.getNextSibling()
+							|| this.getPreviousSibling();
+				Base.splice(owner._children, null, index, 1);
+			}
+			if (this._name)
+				this._removeNamed();
+			this._installEvents(false);
+			if (notifySelf && project._changes)
+				this._changed(5);
+			if (notifyParent)
+				owner._changed(11, this);
+			this._parent = null;
+			return true;
+		}
+		return false;
+	},
+
+	remove: function() {
+		return this._remove(true, true);
+	},
+
+	replaceWith: function(item) {
+		var ok = item && item.insertBelow(this);
+		if (ok)
+			this.remove();
+		return ok;
+	},
+
+	removeChildren: function(start, end) {
+		if (!this._children)
+			return null;
+		start = start || 0;
+		end = Base.pick(end, this._children.length);
+		var removed = Base.splice(this._children, null, start, end - start);
+		for (var i = removed.length - 1; i >= 0; i--) {
+			removed[i]._remove(true, false);
+		}
+		if (removed.length > 0)
+			this._changed(11);
+		return removed;
+	},
+
+	clear: '#removeChildren',
+
+	reverseChildren: function() {
+		if (this._children) {
+			this._children.reverse();
+			for (var i = 0, l = this._children.length; i < l; i++)
+				this._children[i]._index = i;
+			this._changed(11);
+		}
+	},
+
+	isEmpty: function() {
+		return !this._children || this._children.length === 0;
+	},
+
+	isEditable: function() {
+		var item = this;
+		while (item) {
+			if (!item._visible || item._locked)
+				return false;
+			item = item._parent;
+		}
+		return true;
+	},
+
+	hasFill: function() {
+		return this.getStyle().hasFill();
+	},
+
+	hasStroke: function() {
+		return this.getStyle().hasStroke();
+	},
+
+	hasShadow: function() {
+		return this.getStyle().hasShadow();
+	},
+
+	_getOrder: function(item) {
+		function getList(item) {
+			var list = [];
+			do {
+				list.unshift(item);
+			} while (item = item._parent);
+			return list;
+		}
+		var list1 = getList(this),
+			list2 = getList(item);
+		for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {
+			if (list1[i] != list2[i]) {
+				return list1[i]._index < list2[i]._index ? 1 : -1;
+			}
+		}
+		return 0;
+	},
+
+	hasChildren: function() {
+		return this._children && this._children.length > 0;
+	},
+
+	isInserted: function() {
+		return this._parent ? this._parent.isInserted() : false;
+	},
+
+	isAbove: function(item) {
+		return this._getOrder(item) === -1;
+	},
+
+	isBelow: function(item) {
+		return this._getOrder(item) === 1;
+	},
+
+	isParent: function(item) {
+		return this._parent === item;
+	},
+
+	isChild: function(item) {
+		return item && item._parent === this;
+	},
+
+	isDescendant: function(item) {
+		var parent = this;
+		while (parent = parent._parent) {
+			if (parent === item)
+				return true;
+		}
+		return false;
+	},
+
+	isAncestor: function(item) {
+		return item ? item.isDescendant(this) : false;
+	},
+
+	isSibling: function(item) {
+		return this._parent === item._parent;
+	},
+
+	isGroupedWith: function(item) {
+		var parent = this._parent;
+		while (parent) {
+			if (parent._parent
+				&& /^(Group|Layer|CompoundPath)$/.test(parent._class)
+				&& item.isDescendant(parent))
+					return true;
+			parent = parent._parent;
+		}
+		return false;
+	},
+
+}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
+	var rotate = key === 'rotate';
+	this[key] = function() {
+		var value = (rotate ? Base : Point).read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		return this.transform(new Matrix()[key](value,
+				center || this.getPosition(true)));
+	};
+}, {
+	translate: function() {
+		var mx = new Matrix();
+		return this.transform(mx.translate.apply(mx, arguments));
+	},
+
+	transform: function(matrix, _applyMatrix, _applyRecursively,
+			_setApplyMatrix) {
+		if (matrix && matrix.isIdentity())
+			matrix = null;
+		var _matrix = this._matrix,
+			applyMatrix = (_applyMatrix || this._applyMatrix)
+					&& ((!_matrix.isIdentity() || matrix)
+						|| _applyMatrix && _applyRecursively && this._children);
+		if (!matrix && !applyMatrix)
+			return this;
+		if (matrix) {
+			if (!matrix.isInvertible() && _matrix.isInvertible())
+				_matrix._backup = _matrix.getValues();
+			_matrix.prepend(matrix);
+		}
+		if (applyMatrix = applyMatrix && this._transformContent(_matrix,
+					_applyRecursively, _setApplyMatrix)) {
+			var pivot = this._pivot,
+				style = this._style,
+				fillColor = style.getFillColor(true),
+				strokeColor = style.getStrokeColor(true);
+			if (pivot)
+				_matrix._transformPoint(pivot, pivot, true);
+			if (fillColor)
+				fillColor.transform(_matrix);
+			if (strokeColor)
+				strokeColor.transform(_matrix);
+			_matrix.reset(true);
+			if (_setApplyMatrix && this._canApplyMatrix)
+				this._applyMatrix = true;
+		}
+		var bounds = this._bounds,
+			position = this._position;
+		this._changed(9);
+		var decomp = bounds && matrix && matrix.decompose();
+		if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
+			for (var key in bounds) {
+				var cache = bounds[key];
+				if (applyMatrix || !cache.internal) {
+					var rect = cache.rect;
+					matrix._transformBounds(rect, rect);
+				}
+			}
+			var getter = this._boundsGetter,
+				rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
+			if (rect)
+				this._position = rect.getCenter(true);
+			this._bounds = bounds;
+		} else if (matrix && position) {
+			this._position = matrix._transformPoint(position, position);
+		}
+		return this;
+	},
+
+	_transformContent: function(matrix, applyRecursively, setApplyMatrix) {
+		var children = this._children;
+		if (children) {
+			for (var i = 0, l = children.length; i < l; i++)
+				children[i].transform(matrix, true, applyRecursively,
+						setApplyMatrix);
+			return true;
+		}
+	},
+
+	globalToLocal: function() {
+		return this.getGlobalMatrix(true)._inverseTransform(
+				Point.read(arguments));
+	},
+
+	localToGlobal: function() {
+		return this.getGlobalMatrix(true)._transformPoint(
+				Point.read(arguments));
+	},
+
+	parentToLocal: function() {
+		return this._matrix._inverseTransform(Point.read(arguments));
+	},
+
+	localToParent: function() {
+		return this._matrix._transformPoint(Point.read(arguments));
+	},
+
+	fitBounds: function(rectangle, fill) {
+		rectangle = Rectangle.read(arguments);
+		var bounds = this.getBounds(),
+			itemRatio = bounds.height / bounds.width,
+			rectRatio = rectangle.height / rectangle.width,
+			scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
+					? rectangle.width / bounds.width
+					: rectangle.height / bounds.height,
+			newBounds = new Rectangle(new Point(),
+					new Size(bounds.width * scale, bounds.height * scale));
+		newBounds.setCenter(rectangle.getCenter());
+		this.setBounds(newBounds);
+	}
+}), {
+
+	_setStyles: function(ctx, param, viewMatrix) {
+		var style = this._style;
+		if (style.hasFill()) {
+			ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx);
+		}
+		if (style.hasStroke()) {
+			ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx);
+			ctx.lineWidth = style.getStrokeWidth();
+			var strokeJoin = style.getStrokeJoin(),
+				strokeCap = style.getStrokeCap(),
+				miterLimit = style.getMiterLimit();
+			if (strokeJoin)
+				ctx.lineJoin = strokeJoin;
+			if (strokeCap)
+				ctx.lineCap = strokeCap;
+			if (miterLimit)
+				ctx.miterLimit = miterLimit;
+			if (paper.support.nativeDash) {
+				var dashArray = style.getDashArray(),
+					dashOffset = style.getDashOffset();
+				if (dashArray && dashArray.length) {
+					if ('setLineDash' in ctx) {
+						ctx.setLineDash(dashArray);
+						ctx.lineDashOffset = dashOffset;
+					} else {
+						ctx.mozDash = dashArray;
+						ctx.mozDashOffset = dashOffset;
+					}
+				}
+			}
+		}
+		if (style.hasShadow()) {
+			var pixelRatio = param.pixelRatio || 1,
+				mx = viewMatrix._shiftless().prepend(
+					new Matrix().scale(pixelRatio, pixelRatio)),
+				blur = mx.transform(new Point(style.getShadowBlur(), 0)),
+				offset = mx.transform(this.getShadowOffset());
+			ctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);
+			ctx.shadowBlur = blur.getLength();
+			ctx.shadowOffsetX = offset.x;
+			ctx.shadowOffsetY = offset.y;
+		}
+	},
+
+	draw: function(ctx, param, parentStrokeMatrix) {
+		var updateVersion = this._updateVersion = this._project._updateVersion;
+		if (!this._visible || this._opacity === 0)
+			return;
+		var matrices = param.matrices,
+			viewMatrix = param.viewMatrix,
+			matrix = this._matrix,
+			globalMatrix = matrices[matrices.length - 1].appended(matrix);
+		if (!globalMatrix.isInvertible())
+			return;
+
+		viewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)
+				: globalMatrix;
+
+		matrices.push(globalMatrix);
+		if (param.updateMatrix) {
+			globalMatrix._updateVersion = updateVersion;
+			this._globalMatrix = globalMatrix;
+		}
+
+		var blendMode = this._blendMode,
+			opacity = this._opacity,
+			normalBlend = blendMode === 'normal',
+			nativeBlend = BlendMode.nativeModes[blendMode],
+			direct = normalBlend && opacity === 1
+					|| param.dontStart
+					|| param.clip
+					|| (nativeBlend || normalBlend && opacity < 1)
+						&& this._canComposite(),
+			pixelRatio = param.pixelRatio || 1,
+			mainCtx, itemOffset, prevOffset;
+		if (!direct) {
+			var bounds = this.getStrokeBounds(viewMatrix);
+			if (!bounds.width || !bounds.height)
+				return;
+			prevOffset = param.offset;
+			itemOffset = param.offset = bounds.getTopLeft().floor();
+			mainCtx = ctx;
+			ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)
+					.multiply(pixelRatio));
+			if (pixelRatio !== 1)
+				ctx.scale(pixelRatio, pixelRatio);
+		}
+		ctx.save();
+		var strokeMatrix = parentStrokeMatrix
+				? parentStrokeMatrix.appended(matrix)
+				: this._canScaleStroke && !this.getStrokeScaling(true)
+					&& viewMatrix,
+			clip = !direct && param.clipItem,
+			transform = !strokeMatrix || clip;
+		if (direct) {
+			ctx.globalAlpha = opacity;
+			if (nativeBlend)
+				ctx.globalCompositeOperation = blendMode;
+		} else if (transform) {
+			ctx.translate(-itemOffset.x, -itemOffset.y);
+		}
+		if (transform) {
+			(direct ? matrix : viewMatrix).applyToContext(ctx);
+		}
+		if (clip) {
+			param.clipItem.draw(ctx, param.extend({ clip: true }));
+		}
+		if (strokeMatrix) {
+			ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
+			var offset = param.offset;
+			if (offset)
+				ctx.translate(-offset.x, -offset.y);
+		}
+		this._draw(ctx, param, viewMatrix, strokeMatrix);
+		ctx.restore();
+		matrices.pop();
+		if (param.clip && !param.dontFinish)
+			ctx.clip();
+		if (!direct) {
+			BlendMode.process(blendMode, ctx, mainCtx, opacity,
+					itemOffset.subtract(prevOffset).multiply(pixelRatio));
+			CanvasProvider.release(ctx);
+			param.offset = prevOffset;
+		}
+	},
+
+	_isUpdated: function(updateVersion) {
+		var parent = this._parent;
+		if (parent instanceof CompoundPath)
+			return parent._isUpdated(updateVersion);
+		var updated = this._updateVersion === updateVersion;
+		if (!updated && parent && parent._visible
+				&& parent._isUpdated(updateVersion)) {
+			this._updateVersion = updateVersion;
+			updated = true;
+		}
+		return updated;
+	},
+
+	_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {
+		var selection = this._selection,
+			itemSelected = selection & 1,
+			boundsSelected = selection & 2
+					|| itemSelected && this._selectBounds,
+			positionSelected = selection & 4;
+		if (!this._drawSelected)
+			itemSelected = false;
+		if ((itemSelected || boundsSelected || positionSelected)
+				&& this._isUpdated(updateVersion)) {
+			var layer,
+				color = this.getSelectedColor(true) || (layer = this.getLayer())
+					&& layer.getSelectedColor(true),
+				mx = matrix.appended(this.getGlobalMatrix(true)),
+				half = size / 2;
+			ctx.strokeStyle = ctx.fillStyle = color
+					? color.toCanvasStyle(ctx) : '#009dec';
+			if (itemSelected)
+				this._drawSelected(ctx, mx, selectionItems);
+			if (positionSelected) {
+				var point = this.getPosition(true),
+					x = point.x,
+					y = point.y;
+				ctx.beginPath();
+				ctx.arc(x, y, half, 0, Math.PI * 2, true);
+				ctx.stroke();
+				var deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],
+					start = half,
+					end = size + 1;
+				for (var i = 0; i < 4; i++) {
+					var delta = deltas[i],
+						dx = delta[0],
+						dy = delta[1];
+					ctx.moveTo(x + dx * start, y + dy * start);
+					ctx.lineTo(x + dx * end, y + dy * end);
+					ctx.stroke();
+				}
+			}
+			if (boundsSelected) {
+				var coords = mx._transformCorners(this.getInternalBounds());
+				ctx.beginPath();
+				for (var i = 0; i < 8; i++) {
+					ctx[i === 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);
+				}
+				ctx.closePath();
+				ctx.stroke();
+				for (var i = 0; i < 8; i++) {
+					ctx.fillRect(coords[i] - half, coords[++i] - half,
+							size, size);
+				}
+			}
+		}
+	},
+
+	_canComposite: function() {
+		return false;
+	}
+}, Base.each(['down', 'drag', 'up', 'move'], function(key) {
+	this['removeOn' + Base.capitalize(key)] = function() {
+		var hash = {};
+		hash[key] = true;
+		return this.removeOn(hash);
+	};
+}, {
+
+	removeOn: function(obj) {
+		for (var name in obj) {
+			if (obj[name]) {
+				var key = 'mouse' + name,
+					project = this._project,
+					sets = project._removeSets = project._removeSets || {};
+				sets[key] = sets[key] || {};
+				sets[key][this._id] = this;
+			}
+		}
+		return this;
+	}
+}));
+
+var Group = Item.extend({
+	_class: 'Group',
+	_selectBounds: false,
+	_selectChildren: true,
+	_serializeFields: {
+		children: []
+	},
+
+	initialize: function Group(arg) {
+		this._children = [];
+		this._namedChildren = {};
+		if (!this._initialize(arg))
+			this.addChildren(Array.isArray(arg) ? arg : arguments);
+	},
+
+	_changed: function _changed(flags) {
+		_changed.base.call(this, flags);
+		if (flags & 1026) {
+			this._clipItem = undefined;
+		}
+	},
+
+	_getClipItem: function() {
+		var clipItem = this._clipItem;
+		if (clipItem === undefined) {
+			clipItem = null;
+			var children = this._children;
+			for (var i = 0, l = children.length; i < l; i++) {
+				if (children[i]._clipMask) {
+					clipItem = children[i];
+					break;
+				}
+			}
+			this._clipItem = clipItem;
+		}
+		return clipItem;
+	},
+
+	isClipped: function() {
+		return !!this._getClipItem();
+	},
+
+	setClipped: function(clipped) {
+		var child = this.getFirstChild();
+		if (child)
+			child.setClipMask(clipped);
+	},
+
+	_getBounds: function _getBounds(matrix, options) {
+		var clipItem = this._getClipItem();
+		return clipItem
+			? clipItem._getCachedBounds(
+				matrix && matrix.appended(clipItem._matrix),
+				Base.set({}, options, { stroke: false }))
+			: _getBounds.base.call(this, matrix, options);
+	},
+
+	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
+		var clipItem = this._getClipItem();
+		return (!clipItem || clipItem.contains(point))
+				&& _hitTestChildren.base.call(this, point, options, viewMatrix,
+					clipItem);
+	},
+
+	_draw: function(ctx, param) {
+		var clip = param.clip,
+			clipItem = !clip && this._getClipItem();
+		param = param.extend({ clipItem: clipItem, clip: false });
+		if (clip) {
+			ctx.beginPath();
+			param.dontStart = param.dontFinish = true;
+		} else if (clipItem) {
+			clipItem.draw(ctx, param.extend({ clip: true }));
+		}
+		var children = this._children;
+		for (var i = 0, l = children.length; i < l; i++) {
+			var item = children[i];
+			if (item !== clipItem)
+				item.draw(ctx, param);
+		}
+	}
+});
+
+var Layer = Group.extend({
+	_class: 'Layer',
+
+	initialize: function Layer() {
+		Group.apply(this, arguments);
+	},
+
+	_getOwner: function() {
+		return this._parent || this._index != null && this._project;
+	},
+
+	isInserted: function isInserted() {
+		return this._parent ? isInserted.base.call(this) : this._index != null;
+	},
+
+	activate: function() {
+		this._project._activeLayer = this;
+	},
+
+	_hitTestSelf: function() {
+	}
+});
+
+var Shape = Item.extend({
+	_class: 'Shape',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_canScaleStroke: true,
+	_serializeFields: {
+		type: null,
+		size: null,
+		radius: null
+	},
+
+	initialize: function Shape(props) {
+		this._initialize(props);
+	},
+
+	_equals: function(item) {
+		return this._type === item._type
+			&& this._size.equals(item._size)
+			&& Base.equals(this._radius, item._radius);
+	},
+
+	copyContent: function(source) {
+		this.setType(source._type);
+		this.setSize(source._size);
+		this.setRadius(source._radius);
+	},
+
+	getType: function() {
+		return this._type;
+	},
+
+	setType: function(type) {
+		this._type = type;
+	},
+
+	getShape: '#getType',
+	setShape: '#setType',
+
+	getSize: function() {
+		var size = this._size;
+		return new LinkedSize(size.width, size.height, this, 'setSize');
+	},
+
+	setSize: function() {
+		var size = Size.read(arguments);
+		if (!this._size) {
+			this._size = size.clone();
+		} else if (!this._size.equals(size)) {
+			var type = this._type,
+				width = size.width,
+				height = size.height;
+			if (type === 'rectangle') {
+				var radius = Size.min(this._radius, size.divide(2));
+				this._radius.set(radius.width, radius.height);
+			} else if (type === 'circle') {
+				width = height = (width + height) / 2;
+				this._radius = width / 2;
+			} else if (type === 'ellipse') {
+				this._radius.set(width / 2, height / 2);
+			}
+			this._size.set(width, height);
+			this._changed(9);
+		}
+	},
+
+	getRadius: function() {
+		var rad = this._radius;
+		return this._type === 'circle'
+				? rad
+				: new LinkedSize(rad.width, rad.height, this, 'setRadius');
+	},
+
+	setRadius: function(radius) {
+		var type = this._type;
+		if (type === 'circle') {
+			if (radius === this._radius)
+				return;
+			var size = radius * 2;
+			this._radius = radius;
+			this._size.set(size, size);
+		} else {
+			radius = Size.read(arguments);
+			if (!this._radius) {
+				this._radius = radius.clone();
+			} else {
+				if (this._radius.equals(radius))
+					return;
+				this._radius.set(radius.width, radius.height);
+				if (type === 'rectangle') {
+					var size = Size.max(this._size, radius.multiply(2));
+					this._size.set(size.width, size.height);
+				} else if (type === 'ellipse') {
+					this._size.set(radius.width * 2, radius.height * 2);
+				}
+			}
+		}
+		this._changed(9);
+	},
+
+	isEmpty: function() {
+		return false;
+	},
+
+	toPath: function(insert) {
+		var path = new Path[Base.capitalize(this._type)]({
+			center: new Point(),
+			size: this._size,
+			radius: this._radius,
+			insert: false
+		});
+		path.copyAttributes(this);
+		if (paper.settings.applyMatrix)
+			path.setApplyMatrix(true);
+		if (insert === undefined || insert)
+			path.insertAbove(this);
+		return path;
+	},
+
+	toShape: '#clone',
+
+	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
+		var style = this._style,
+			hasFill = style.hasFill(),
+			hasStroke = style.hasStroke(),
+			dontPaint = param.dontFinish || param.clip,
+			untransformed = !strokeMatrix;
+		if (hasFill || hasStroke || dontPaint) {
+			var type = this._type,
+				radius = this._radius,
+				isCircle = type === 'circle';
+			if (!param.dontStart)
+				ctx.beginPath();
+			if (untransformed && isCircle) {
+				ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
+			} else {
+				var rx = isCircle ? radius : radius.width,
+					ry = isCircle ? radius : radius.height,
+					size = this._size,
+					width = size.width,
+					height = size.height;
+				if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
+					ctx.rect(-width / 2, -height / 2, width, height);
+				} else {
+					var x = width / 2,
+						y = height / 2,
+						kappa = 1 - 0.5522847498307936,
+						cx = rx * kappa,
+						cy = ry * kappa,
+						c = [
+							-x, -y + ry,
+							-x, -y + cy,
+							-x + cx, -y,
+							-x + rx, -y,
+							x - rx, -y,
+							x - cx, -y,
+							x, -y + cy,
+							x, -y + ry,
+							x, y - ry,
+							x, y - cy,
+							x - cx, y,
+							x - rx, y,
+							-x + rx, y,
+							-x + cx, y,
+							-x, y - cy,
+							-x, y - ry
+						];
+					if (strokeMatrix)
+						strokeMatrix.transform(c, c, 32);
+					ctx.moveTo(c[0], c[1]);
+					ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);
+					if (x !== rx)
+						ctx.lineTo(c[8], c[9]);
+					ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);
+					if (y !== ry)
+						ctx.lineTo(c[16], c[17]);
+					ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);
+					if (x !== rx)
+						ctx.lineTo(c[24], c[25]);
+					ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);
+				}
+			}
+			ctx.closePath();
+		}
+		if (!dontPaint && (hasFill || hasStroke)) {
+			this._setStyles(ctx, param, viewMatrix);
+			if (hasFill) {
+				ctx.fill(style.getFillRule());
+				ctx.shadowColor = 'rgba(0,0,0,0)';
+			}
+			if (hasStroke)
+				ctx.stroke();
+		}
+	},
+
+	_canComposite: function() {
+		return !(this.hasFill() && this.hasStroke());
+	},
+
+	_getBounds: function(matrix, options) {
+		var rect = new Rectangle(this._size).setCenter(0, 0),
+			style = this._style,
+			strokeWidth = options.stroke && style.hasStroke()
+					&& style.getStrokeWidth();
+		if (matrix)
+			rect = matrix._transformBounds(rect);
+		return strokeWidth
+				? rect.expand(Path._getStrokePadding(strokeWidth,
+					this._getStrokeMatrix(matrix, options)))
+				: rect;
+	}
+},
+new function() {
+	function getCornerCenter(that, point, expand) {
+		var radius = that._radius;
+		if (!radius.isZero()) {
+			var halfSize = that._size.divide(2);
+			for (var i = 0; i < 4; i++) {
+				var dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),
+					corner = dir.multiply(halfSize),
+					center = corner.subtract(dir.multiply(radius)),
+					rect = new Rectangle(corner, center);
+				if ((expand ? rect.expand(expand) : rect).contains(point))
+					return center;
+			}
+		}
+	}
+
+	function isOnEllipseStroke(point, radius, padding, quadrant) {
+		var vector = point.divide(radius);
+		return (!quadrant || vector.quadrant === quadrant) &&
+				vector.subtract(vector.normalize()).multiply(radius)
+					.divide(padding).length <= 1;
+	}
+
+	return {
+		_contains: function _contains(point) {
+			if (this._type === 'rectangle') {
+				var center = getCornerCenter(this, point);
+				return center
+						? point.subtract(center).divide(this._radius)
+							.getLength() <= 1
+						: _contains.base.call(this, point);
+			} else {
+				return point.divide(this.size).getLength() <= 0.5;
+			}
+		},
+
+		_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,
+				strokeMatrix) {
+			var hit = false,
+				style = this._style,
+				hitStroke = options.stroke && style.hasStroke(),
+				hitFill = options.fill && style.hasFill();
+			if (hitStroke || hitFill) {
+				var type = this._type,
+					radius = this._radius,
+					strokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,
+					strokePadding = options._tolerancePadding.add(
+						Path._getStrokePadding(strokeRadius,
+							!style.getStrokeScaling() && strokeMatrix));
+				if (type === 'rectangle') {
+					var padding = strokePadding.multiply(2),
+						center = getCornerCenter(this, point, padding);
+					if (center) {
+						hit = isOnEllipseStroke(point.subtract(center), radius,
+								strokePadding, center.getQuadrant());
+					} else {
+						var rect = new Rectangle(this._size).setCenter(0, 0),
+							outer = rect.expand(padding),
+							inner = rect.expand(padding.negate());
+						hit = outer._containsPoint(point)
+								&& !inner._containsPoint(point);
+					}
+				} else {
+					hit = isOnEllipseStroke(point, radius, strokePadding);
+				}
+			}
+			return hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)
+					: _hitTestSelf.base.apply(this, arguments);
+		}
+	};
+}, {
+
+statics: new function() {
+	function createShape(type, point, size, radius, args) {
+		var item = new Shape(Base.getNamed(args));
+		item._type = type;
+		item._size = size;
+		item._radius = radius;
+		return item.translate(point);
+	}
+
+	return {
+		Circle: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				radius = Base.readNamed(arguments, 'radius');
+			return createShape('circle', center, new Size(radius * 2), radius,
+					arguments);
+		},
+
+		Rectangle: function() {
+			var rect = Rectangle.readNamed(arguments, 'rectangle'),
+				radius = Size.min(Size.readNamed(arguments, 'radius'),
+						rect.getSize(true).divide(2));
+			return createShape('rectangle', rect.getCenter(true),
+					rect.getSize(true), radius, arguments);
+		},
+
+		Ellipse: function() {
+			var ellipse = Shape._readEllipse(arguments),
+				radius = ellipse.radius;
+			return createShape('ellipse', ellipse.center, radius.multiply(2),
+					radius, arguments);
+		},
+
+		_readEllipse: function(args) {
+			var center,
+				radius;
+			if (Base.hasNamed(args, 'radius')) {
+				center = Point.readNamed(args, 'center');
+				radius = Size.readNamed(args, 'radius');
+			} else {
+				var rect = Rectangle.readNamed(args, 'rectangle');
+				center = rect.getCenter(true);
+				radius = rect.getSize(true).divide(2);
+			}
+			return { center: center, radius: radius };
+		}
+	};
+}});
+
+var Raster = Item.extend({
+	_class: 'Raster',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_boundsOptions: { stroke: false, handle: false },
+	_serializeFields: {
+		crossOrigin: null,
+		source: null
+	},
+
+	initialize: function Raster(object, position) {
+		if (!this._initialize(object,
+				position !== undefined && Point.read(arguments, 1))) {
+			var image = typeof object === 'string'
+					? document.getElementById(object) : object;
+			if (image) {
+				this.setImage(image);
+			} else {
+				this.setSource(object);
+			}
+		}
+		if (!this._size) {
+			this._size = new Size();
+			this._loaded = false;
+		}
+	},
+
+	_equals: function(item) {
+		return this.getSource() === item.getSource();
+	},
+
+	copyContent: function(source) {
+		var image = source._image,
+			canvas = source._canvas;
+		if (image) {
+			this._setImage(image);
+		} else if (canvas) {
+			var copyCanvas = CanvasProvider.getCanvas(source._size);
+			copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
+			this._setImage(copyCanvas);
+		}
+		this._crossOrigin = source._crossOrigin;
+	},
+
+	getSize: function() {
+		var size = this._size;
+		return new LinkedSize(size ? size.width : 0, size ? size.height : 0,
+				this, 'setSize');
+	},
+
+	setSize: function() {
+		var size = Size.read(arguments);
+		if (!size.equals(this._size)) {
+			if (size.width > 0 && size.height > 0) {
+				var element = this.getElement();
+				this._setImage(CanvasProvider.getCanvas(size));
+				if (element)
+					this.getContext(true).drawImage(element, 0, 0,
+							size.width, size.height);
+			} else {
+				if (this._canvas)
+					CanvasProvider.release(this._canvas);
+				this._size = size.clone();
+			}
+		}
+	},
+
+	getWidth: function() {
+		return this._size ? this._size.width : 0;
+	},
+
+	setWidth: function(width) {
+		this.setSize(width, this.getHeight());
+	},
+
+	getHeight: function() {
+		return this._size ? this._size.height : 0;
+	},
+
+	setHeight: function(height) {
+		this.setSize(this.getWidth(), height);
+	},
+
+	getLoaded: function() {
+		return this._loaded;
+	},
+
+	isEmpty: function() {
+		var size = this._size;
+		return !size || size.width === 0 && size.height === 0;
+	},
+
+	getResolution: function() {
+		var matrix = this._matrix,
+			orig = new Point(0, 0).transform(matrix),
+			u = new Point(1, 0).transform(matrix).subtract(orig),
+			v = new Point(0, 1).transform(matrix).subtract(orig);
+		return new Size(
+			72 / u.getLength(),
+			72 / v.getLength()
+		);
+	},
+
+	getPpi: '#getResolution',
+
+	getImage: function() {
+		return this._image;
+	},
+
+	setImage: function(image) {
+		var that = this;
+
+		function emit(event) {
+			var view = that.getView(),
+				type = event && event.type || 'load';
+			if (view && that.responds(type)) {
+				paper = view._scope;
+				that.emit(type, new Event(event));
+			}
+		}
+
+		this._setImage(image);
+		if (this._loaded) {
+			setTimeout(emit, 0);
+		} else if (image) {
+			DomEvent.add(image, {
+				load: function(event) {
+					that._setImage(image);
+					emit(event);
+				},
+				error: emit
+			});
+		}
+	},
+
+	_setImage: function(image) {
+		if (this._canvas)
+			CanvasProvider.release(this._canvas);
+		if (image && image.getContext) {
+			this._image = null;
+			this._canvas = image;
+			this._loaded = true;
+		} else {
+			this._image = image;
+			this._canvas = null;
+			this._loaded = !!(image && image.src && image.complete);
+		}
+		this._size = new Size(
+				image ? image.naturalWidth || image.width : 0,
+				image ? image.naturalHeight || image.height : 0);
+		this._context = null;
+		this._changed(521);
+	},
+
+	getCanvas: function() {
+		if (!this._canvas) {
+			var ctx = CanvasProvider.getContext(this._size);
+			try {
+				if (this._image)
+					ctx.drawImage(this._image, 0, 0);
+				this._canvas = ctx.canvas;
+			} catch (e) {
+				CanvasProvider.release(ctx);
+			}
+		}
+		return this._canvas;
+	},
+
+	setCanvas: '#setImage',
+
+	getContext: function(modify) {
+		if (!this._context)
+			this._context = this.getCanvas().getContext('2d');
+		if (modify) {
+			this._image = null;
+			this._changed(513);
+		}
+		return this._context;
+	},
+
+	setContext: function(context) {
+		this._context = context;
+	},
+
+	getSource: function() {
+		var image = this._image;
+		return image && image.src || this.toDataURL();
+	},
+
+	setSource: function(src) {
+		var image = new window.Image(),
+			crossOrigin = this._crossOrigin;
+		if (crossOrigin)
+			image.crossOrigin = crossOrigin;
+		image.src = src;
+		this.setImage(image);
+	},
+
+	getCrossOrigin: function() {
+		var image = this._image;
+		return image && image.crossOrigin || this._crossOrigin || '';
+	},
+
+	setCrossOrigin: function(crossOrigin) {
+		this._crossOrigin = crossOrigin;
+		var image = this._image;
+		if (image)
+			image.crossOrigin = crossOrigin;
+	},
+
+	getElement: function() {
+		return this._canvas || this._loaded && this._image;
+	}
+}, {
+	beans: false,
+
+	getSubCanvas: function() {
+		var rect = Rectangle.read(arguments),
+			ctx = CanvasProvider.getContext(rect.getSize());
+		ctx.drawImage(this.getCanvas(), rect.x, rect.y,
+				rect.width, rect.height, 0, 0, rect.width, rect.height);
+		return ctx.canvas;
+	},
+
+	getSubRaster: function() {
+		var rect = Rectangle.read(arguments),
+			raster = new Raster(Item.NO_INSERT);
+		raster._setImage(this.getSubCanvas(rect));
+		raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
+		raster._matrix.prepend(this._matrix);
+		raster.insertAbove(this);
+		return raster;
+	},
+
+	toDataURL: function() {
+		var image = this._image,
+			src = image && image.src;
+		if (/^data:/.test(src))
+			return src;
+		var canvas = this.getCanvas();
+		return canvas ? canvas.toDataURL.apply(canvas, arguments) : null;
+	},
+
+	drawImage: function(image ) {
+		var point = Point.read(arguments, 1);
+		this.getContext(true).drawImage(image, point.x, point.y);
+	},
+
+	getAverageColor: function(object) {
+		var bounds, path;
+		if (!object) {
+			bounds = this.getBounds();
+		} else if (object instanceof PathItem) {
+			path = object;
+			bounds = object.getBounds();
+		} else if (typeof object === 'object') {
+			if ('width' in object) {
+				bounds = new Rectangle(object);
+			} else if ('x' in object) {
+				bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
+			}
+		}
+		if (!bounds)
+			return null;
+		var sampleSize = 32,
+			width = Math.min(bounds.width, sampleSize),
+			height = Math.min(bounds.height, sampleSize);
+		var ctx = Raster._sampleContext;
+		if (!ctx) {
+			ctx = Raster._sampleContext = CanvasProvider.getContext(
+					new Size(sampleSize));
+		} else {
+			ctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);
+		}
+		ctx.save();
+		var matrix = new Matrix()
+				.scale(width / bounds.width, height / bounds.height)
+				.translate(-bounds.x, -bounds.y);
+		matrix.applyToContext(ctx);
+		if (path)
+			path.draw(ctx, new Base({ clip: true, matrices: [matrix] }));
+		this._matrix.applyToContext(ctx);
+		var element = this.getElement(),
+			size = this._size;
+		if (element)
+			ctx.drawImage(element, -size.width / 2, -size.height / 2);
+		ctx.restore();
+		var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),
+				Math.ceil(height)).data,
+			channels = [0, 0, 0],
+			total = 0;
+		for (var i = 0, l = pixels.length; i < l; i += 4) {
+			var alpha = pixels[i + 3];
+			total += alpha;
+			alpha /= 255;
+			channels[0] += pixels[i] * alpha;
+			channels[1] += pixels[i + 1] * alpha;
+			channels[2] += pixels[i + 2] * alpha;
+		}
+		for (var i = 0; i < 3; i++)
+			channels[i] /= total;
+		return total ? Color.read(channels) : null;
+	},
+
+	getPixel: function() {
+		var point = Point.read(arguments);
+		var data = this.getContext().getImageData(point.x, point.y, 1, 1).data;
+		return new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],
+				data[3] / 255);
+	},
+
+	setPixel: function() {
+		var point = Point.read(arguments),
+			color = Color.read(arguments),
+			components = color._convert('rgb'),
+			alpha = color._alpha,
+			ctx = this.getContext(true),
+			imageData = ctx.createImageData(1, 1),
+			data = imageData.data;
+		data[0] = components[0] * 255;
+		data[1] = components[1] * 255;
+		data[2] = components[2] * 255;
+		data[3] = alpha != null ? alpha * 255 : 255;
+		ctx.putImageData(imageData, point.x, point.y);
+	},
+
+	createImageData: function() {
+		var size = Size.read(arguments);
+		return this.getContext().createImageData(size.width, size.height);
+	},
+
+	getImageData: function() {
+		var rect = Rectangle.read(arguments);
+		if (rect.isEmpty())
+			rect = new Rectangle(this._size);
+		return this.getContext().getImageData(rect.x, rect.y,
+				rect.width, rect.height);
+	},
+
+	setImageData: function(data ) {
+		var point = Point.read(arguments, 1);
+		this.getContext(true).putImageData(data, point.x, point.y);
+	},
+
+	_getBounds: function(matrix, options) {
+		var rect = new Rectangle(this._size).setCenter(0, 0);
+		return matrix ? matrix._transformBounds(rect) : rect;
+	},
+
+	_hitTestSelf: function(point) {
+		if (this._contains(point)) {
+			var that = this;
+			return new HitResult('pixel', that, {
+				offset: point.add(that._size.divide(2)).round(),
+				color: {
+					get: function() {
+						return that.getPixel(this.offset);
+					}
+				}
+			});
+		}
+	},
+
+	_draw: function(ctx) {
+		var element = this.getElement();
+		if (element) {
+			ctx.globalAlpha = this._opacity;
+			ctx.drawImage(element,
+					-this._size.width / 2, -this._size.height / 2);
+		}
+	},
+
+	_canComposite: function() {
+		return true;
+	}
+});
+
+var SymbolItem = Item.extend({
+	_class: 'SymbolItem',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_boundsOptions: { stroke: true },
+	_serializeFields: {
+		symbol: null
+	},
+
+	initialize: function SymbolItem(arg0, arg1) {
+		if (!this._initialize(arg0,
+				arg1 !== undefined && Point.read(arguments, 1)))
+			this.setDefinition(arg0 instanceof SymbolDefinition ?
+					arg0 : new SymbolDefinition(arg0));
+	},
+
+	_equals: function(item) {
+		return this._definition === item._definition;
+	},
+
+	copyContent: function(source) {
+		this.setDefinition(source._definition);
+	},
+
+	getDefinition: function() {
+		return this._definition;
+	},
+
+	setDefinition: function(definition) {
+		this._definition = definition;
+		this._changed(9);
+	},
+
+	getSymbol: '#getDefinition',
+	setSymbol: '#setDefinition',
+
+	isEmpty: function() {
+		return this._definition._item.isEmpty();
+	},
+
+	_getBounds: function(matrix, options) {
+		var item = this._definition._item;
+		return item._getCachedBounds(item._matrix.prepended(matrix), options);
+	},
+
+	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
+		var res = this._definition._item._hitTest(point, options, viewMatrix);
+		if (res)
+			res.item = this;
+		return res;
+	},
+
+	_draw: function(ctx, param) {
+		this._definition._item.draw(ctx, param);
+	}
+
+});
+
+var SymbolDefinition = Base.extend({
+	_class: 'SymbolDefinition',
+
+	initialize: function SymbolDefinition(item, dontCenter) {
+		this._id = UID.get();
+		this.project = paper.project;
+		if (item)
+			this.setItem(item, dontCenter);
+	},
+
+	_serialize: function(options, dictionary) {
+		return dictionary.add(this, function() {
+			return Base.serialize([this._class, this._item],
+					options, false, dictionary);
+		});
+	},
+
+	_changed: function(flags) {
+		if (flags & 8)
+			Item._clearBoundsCache(this);
+		if (flags & 1)
+			this.project._changed(flags);
+	},
+
+	getItem: function() {
+		return this._item;
+	},
+
+	setItem: function(item, _dontCenter) {
+		if (item._symbol)
+			item = item.clone();
+		if (this._item)
+			this._item._symbol = null;
+		this._item = item;
+		item.remove();
+		item.setSelected(false);
+		if (!_dontCenter)
+			item.setPosition(new Point());
+		item._symbol = this;
+		this._changed(9);
+	},
+
+	getDefinition: '#getItem',
+	setDefinition: '#setItem',
+
+	place: function(position) {
+		return new SymbolItem(this, position);
+	},
+
+	clone: function() {
+		return new SymbolDefinition(this._item.clone(false));
+	},
+
+	equals: function(symbol) {
+		return symbol === this
+				|| symbol && this._item.equals(symbol._item)
+				|| false;
+	}
+});
+
+var HitResult = Base.extend({
+	_class: 'HitResult',
+
+	initialize: function HitResult(type, item, values) {
+		this.type = type;
+		this.item = item;
+		if (values) {
+			values.enumerable = true;
+			this.inject(values);
+		}
+	},
+
+	statics: {
+		getOptions: function(args) {
+			var options = args && Base.read(args);
+			return Base.set({
+				type: null,
+				tolerance: paper.settings.hitTolerance,
+				fill: !options,
+				stroke: !options,
+				segments: !options,
+				handles: false,
+				ends: false,
+				center: false,
+				bounds: false,
+				guides: false,
+				selected: false
+			}, options);
+		}
+	}
+});
+
+var Segment = Base.extend({
+	_class: 'Segment',
+	beans: true,
+	_selection: 0,
+
+	initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
+		var count = arguments.length,
+			point, handleIn, handleOut,
+			selection;
+		if (count === 0) {
+		} else if (count === 1) {
+			if (arg0 && 'point' in arg0) {
+				point = arg0.point;
+				handleIn = arg0.handleIn;
+				handleOut = arg0.handleOut;
+				selection = arg0.selection;
+			} else {
+				point = arg0;
+			}
+		} else if (arg0 == null || typeof arg0 === 'object') {
+			point = arg0;
+			handleIn = arg1;
+			handleOut = arg2;
+			selection = arg3;
+		} else {
+			point = arg0 !== undefined ? [ arg0, arg1 ] : null;
+			handleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;
+			handleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;
+		}
+		new SegmentPoint(point, this, '_point');
+		new SegmentPoint(handleIn, this, '_handleIn');
+		new SegmentPoint(handleOut, this, '_handleOut');
+		if (selection)
+			this.setSelection(selection);
+	},
+
+	_serialize: function(options, dictionary) {
+		var point = this._point,
+			selection = this._selection,
+			obj = selection || this.hasHandles()
+					? [point, this._handleIn, this._handleOut]
+					: point;
+		if (selection)
+			obj.push(selection);
+		return Base.serialize(obj, options, true, dictionary);
+	},
+
+	_changed: function(point) {
+		var path = this._path;
+		if (!path)
+			return;
+		var curves = path._curves,
+			index = this._index,
+			curve;
+		if (curves) {
+			if ((!point || point === this._point || point === this._handleIn)
+					&& (curve = index > 0 ? curves[index - 1] : path._closed
+						? curves[curves.length - 1] : null))
+				curve._changed();
+			if ((!point || point === this._point || point === this._handleOut)
+					&& (curve = curves[index]))
+				curve._changed();
+		}
+		path._changed(25);
+	},
+
+	getPoint: function() {
+		return this._point;
+	},
+
+	setPoint: function() {
+		var point = Point.read(arguments);
+		this._point.set(point.x, point.y);
+	},
+
+	getHandleIn: function() {
+		return this._handleIn;
+	},
+
+	setHandleIn: function() {
+		var point = Point.read(arguments);
+		this._handleIn.set(point.x, point.y);
+	},
+
+	getHandleOut: function() {
+		return this._handleOut;
+	},
+
+	setHandleOut: function() {
+		var point = Point.read(arguments);
+		this._handleOut.set(point.x, point.y);
+	},
+
+	hasHandles: function() {
+		return !this._handleIn.isZero() || !this._handleOut.isZero();
+	},
+
+	clearHandles: function() {
+		this._handleIn.set(0, 0);
+		this._handleOut.set(0, 0);
+	},
+
+	getSelection: function() {
+		return this._selection;
+	},
+
+	setSelection: function(selection) {
+		var oldSelection = this._selection,
+			path = this._path;
+		this._selection = selection = selection || 0;
+		if (path && selection !== oldSelection) {
+			path._updateSelection(this, oldSelection, selection);
+			path._changed(129);
+		}
+	},
+
+	changeSelection: function(flag, selected) {
+		var selection = this._selection;
+		this.setSelection(selected ? selection | flag : selection & ~flag);
+	},
+
+	isSelected: function() {
+		return !!(this._selection & 7);
+	},
+
+	setSelected: function(selected) {
+		this.changeSelection(7, selected);
+	},
+
+	getIndex: function() {
+		return this._index !== undefined ? this._index : null;
+	},
+
+	getPath: function() {
+		return this._path || null;
+	},
+
+	getCurve: function() {
+		var path = this._path,
+			index = this._index;
+		if (path) {
+			if (index > 0 && !path._closed
+					&& index === path._segments.length - 1)
+				index--;
+			return path.getCurves()[index] || null;
+		}
+		return null;
+	},
+
+	getLocation: function() {
+		var curve = this.getCurve();
+		return curve
+				? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)
+				: null;
+	},
+
+	getNext: function() {
+		var segments = this._path && this._path._segments;
+		return segments && (segments[this._index + 1]
+				|| this._path._closed && segments[0]) || null;
+	},
+
+	smooth: function(options, _first, _last) {
+		var opts = options || {},
+			type = opts.type,
+			factor = opts.factor,
+			prev = this.getPrevious(),
+			next = this.getNext(),
+			p0 = (prev || this)._point,
+			p1 = this._point,
+			p2 = (next || this)._point,
+			d1 = p0.getDistance(p1),
+			d2 = p1.getDistance(p2);
+		if (!type || type === 'catmull-rom') {
+			var a = factor === undefined ? 0.5 : factor,
+				d1_a = Math.pow(d1, a),
+				d1_2a = d1_a * d1_a,
+				d2_a = Math.pow(d2, a),
+				d2_2a = d2_a * d2_a;
+			if (!_first && prev) {
+				var A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,
+					N = 3 * d2_a * (d2_a + d1_a);
+				this.setHandleIn(N !== 0
+					? new Point(
+						(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,
+						(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)
+					: new Point());
+			}
+			if (!_last && next) {
+				var A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,
+					N = 3 * d1_a * (d1_a + d2_a);
+				this.setHandleOut(N !== 0
+					? new Point(
+						(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,
+						(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)
+					: new Point());
+			}
+		} else if (type === 'geometric') {
+			if (prev && next) {
+				var vector = p0.subtract(p2),
+					t = factor === undefined ? 0.4 : factor,
+					k = t * d1 / (d1 + d2);
+				if (!_first)
+					this.setHandleIn(vector.multiply(k));
+				if (!_last)
+					this.setHandleOut(vector.multiply(k - t));
+			}
+		} else {
+			throw new Error('Smoothing method \'' + type + '\' not supported.');
+		}
+	},
+
+	getPrevious: function() {
+		var segments = this._path && this._path._segments;
+		return segments && (segments[this._index - 1]
+				|| this._path._closed && segments[segments.length - 1]) || null;
+	},
+
+	isFirst: function() {
+		return this._index === 0;
+	},
+
+	isLast: function() {
+		var path = this._path;
+		return path && this._index === path._segments.length - 1 || false;
+	},
+
+	reverse: function() {
+		var handleIn = this._handleIn,
+			handleOut = this._handleOut,
+			inX = handleIn._x,
+			inY = handleIn._y;
+		handleIn.set(handleOut._x, handleOut._y);
+		handleOut.set(inX, inY);
+	},
+
+	reversed: function() {
+		return new Segment(this._point, this._handleOut, this._handleIn);
+	},
+
+	remove: function() {
+		return this._path ? !!this._path.removeSegment(this._index) : false;
+	},
+
+	clone: function() {
+		return new Segment(this._point, this._handleIn, this._handleOut);
+	},
+
+	equals: function(segment) {
+		return segment === this || segment && this._class === segment._class
+				&& this._point.equals(segment._point)
+				&& this._handleIn.equals(segment._handleIn)
+				&& this._handleOut.equals(segment._handleOut)
+				|| false;
+	},
+
+	toString: function() {
+		var parts = [ 'point: ' + this._point ];
+		if (!this._handleIn.isZero())
+			parts.push('handleIn: ' + this._handleIn);
+		if (!this._handleOut.isZero())
+			parts.push('handleOut: ' + this._handleOut);
+		return '{ ' + parts.join(', ') + ' }';
+	},
+
+	transform: function(matrix) {
+		this._transformCoordinates(matrix, new Array(6), true);
+		this._changed();
+	},
+
+	interpolate: function(from, to, factor) {
+		var u = 1 - factor,
+			v = factor,
+			point1 = from._point,
+			point2 = to._point,
+			handleIn1 = from._handleIn,
+			handleIn2 = to._handleIn,
+			handleOut2 = to._handleOut,
+			handleOut1 = from._handleOut;
+		this._point.set(
+				u * point1._x + v * point2._x,
+				u * point1._y + v * point2._y, true);
+		this._handleIn.set(
+				u * handleIn1._x + v * handleIn2._x,
+				u * handleIn1._y + v * handleIn2._y, true);
+		this._handleOut.set(
+				u * handleOut1._x + v * handleOut2._x,
+				u * handleOut1._y + v * handleOut2._y, true);
+		this._changed();
+	},
+
+	_transformCoordinates: function(matrix, coords, change) {
+		var point = this._point,
+			handleIn = !change || !this._handleIn.isZero()
+					? this._handleIn : null,
+			handleOut = !change || !this._handleOut.isZero()
+					? this._handleOut : null,
+			x = point._x,
+			y = point._y,
+			i = 2;
+		coords[0] = x;
+		coords[1] = y;
+		if (handleIn) {
+			coords[i++] = handleIn._x + x;
+			coords[i++] = handleIn._y + y;
+		}
+		if (handleOut) {
+			coords[i++] = handleOut._x + x;
+			coords[i++] = handleOut._y + y;
+		}
+		if (matrix) {
+			matrix._transformCoordinates(coords, coords, i / 2);
+			x = coords[0];
+			y = coords[1];
+			if (change) {
+				point._x = x;
+				point._y = y;
+				i = 2;
+				if (handleIn) {
+					handleIn._x = coords[i++] - x;
+					handleIn._y = coords[i++] - y;
+				}
+				if (handleOut) {
+					handleOut._x = coords[i++] - x;
+					handleOut._y = coords[i++] - y;
+				}
+			} else {
+				if (!handleIn) {
+					coords[i++] = x;
+					coords[i++] = y;
+				}
+				if (!handleOut) {
+					coords[i++] = x;
+					coords[i++] = y;
+				}
+			}
+		}
+		return coords;
+	}
+});
+
+var SegmentPoint = Point.extend({
+	initialize: function SegmentPoint(point, owner, key) {
+		var x, y,
+			selected;
+		if (!point) {
+			x = y = 0;
+		} else if ((x = point[0]) !== undefined) {
+			y = point[1];
+		} else {
+			var pt = point;
+			if ((x = pt.x) === undefined) {
+				pt = Point.read(arguments);
+				x = pt.x;
+			}
+			y = pt.y;
+			selected = pt.selected;
+		}
+		this._x = x;
+		this._y = y;
+		this._owner = owner;
+		owner[key] = this;
+		if (selected)
+			this.setSelected(true);
+	},
+
+	set: function(x, y) {
+		this._x = x;
+		this._y = y;
+		this._owner._changed(this);
+		return this;
+	},
+
+	getX: function() {
+		return this._x;
+	},
+
+	setX: function(x) {
+		this._x = x;
+		this._owner._changed(this);
+	},
+
+	getY: function() {
+		return this._y;
+	},
+
+	setY: function(y) {
+		this._y = y;
+		this._owner._changed(this);
+	},
+
+	isZero: function() {
+		return Numerical.isZero(this._x) && Numerical.isZero(this._y);
+	},
+
+	isSelected: function() {
+		return !!(this._owner._selection & this._getSelection());
+	},
+
+	setSelected: function(selected) {
+		this._owner.changeSelection(this._getSelection(), selected);
+	},
+
+	_getSelection: function() {
+		var owner = this._owner;
+		return this === owner._point ? 1
+			: this === owner._handleIn ? 2
+			: this === owner._handleOut ? 4
+			: 0;
+	}
+});
+
+var Curve = Base.extend({
+	_class: 'Curve',
+
+	initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
+		var count = arguments.length,
+			seg1, seg2,
+			point1, point2,
+			handle1, handle2;
+		if (count === 3) {
+			this._path = arg0;
+			seg1 = arg1;
+			seg2 = arg2;
+		} else if (count === 0) {
+			seg1 = new Segment();
+			seg2 = new Segment();
+		} else if (count === 1) {
+			if ('segment1' in arg0) {
+				seg1 = new Segment(arg0.segment1);
+				seg2 = new Segment(arg0.segment2);
+			} else if ('point1' in arg0) {
+				point1 = arg0.point1;
+				handle1 = arg0.handle1;
+				handle2 = arg0.handle2;
+				point2 = arg0.point2;
+			} else if (Array.isArray(arg0)) {
+				point1 = [arg0[0], arg0[1]];
+				point2 = [arg0[6], arg0[7]];
+				handle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];
+				handle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];
+			}
+		} else if (count === 2) {
+			seg1 = new Segment(arg0);
+			seg2 = new Segment(arg1);
+		} else if (count === 4) {
+			point1 = arg0;
+			handle1 = arg1;
+			handle2 = arg2;
+			point2 = arg3;
+		} else if (count === 8) {
+			point1 = [arg0, arg1];
+			point2 = [arg6, arg7];
+			handle1 = [arg2 - arg0, arg3 - arg1];
+			handle2 = [arg4 - arg6, arg5 - arg7];
+		}
+		this._segment1 = seg1 || new Segment(point1, null, handle1);
+		this._segment2 = seg2 || new Segment(point2, handle2, null);
+	},
+
+	_serialize: function(options, dictionary) {
+		return Base.serialize(this.hasHandles()
+				? [this.getPoint1(), this.getHandle1(), this.getHandle2(),
+					this.getPoint2()]
+				: [this.getPoint1(), this.getPoint2()],
+				options, true, dictionary);
+	},
+
+	_changed: function() {
+		this._length = this._bounds = undefined;
+	},
+
+	clone: function() {
+		return new Curve(this._segment1, this._segment2);
+	},
+
+	toString: function() {
+		var parts = [ 'point1: ' + this._segment1._point ];
+		if (!this._segment1._handleOut.isZero())
+			parts.push('handle1: ' + this._segment1._handleOut);
+		if (!this._segment2._handleIn.isZero())
+			parts.push('handle2: ' + this._segment2._handleIn);
+		parts.push('point2: ' + this._segment2._point);
+		return '{ ' + parts.join(', ') + ' }';
+	},
+
+	remove: function() {
+		var removed = false;
+		if (this._path) {
+			var segment2 = this._segment2,
+				handleOut = segment2._handleOut;
+			removed = segment2.remove();
+			if (removed)
+				this._segment1._handleOut.set(handleOut.x, handleOut.y);
+		}
+		return removed;
+	},
+
+	getPoint1: function() {
+		return this._segment1._point;
+	},
+
+	setPoint1: function() {
+		var point = Point.read(arguments);
+		this._segment1._point.set(point.x, point.y);
+	},
+
+	getPoint2: function() {
+		return this._segment2._point;
+	},
+
+	setPoint2: function() {
+		var point = Point.read(arguments);
+		this._segment2._point.set(point.x, point.y);
+	},
+
+	getHandle1: function() {
+		return this._segment1._handleOut;
+	},
+
+	setHandle1: function() {
+		var point = Point.read(arguments);
+		this._segment1._handleOut.set(point.x, point.y);
+	},
+
+	getHandle2: function() {
+		return this._segment2._handleIn;
+	},
+
+	setHandle2: function() {
+		var point = Point.read(arguments);
+		this._segment2._handleIn.set(point.x, point.y);
+	},
+
+	getSegment1: function() {
+		return this._segment1;
+	},
+
+	getSegment2: function() {
+		return this._segment2;
+	},
+
+	getPath: function() {
+		return this._path;
+	},
+
+	getIndex: function() {
+		return this._segment1._index;
+	},
+
+	getNext: function() {
+		var curves = this._path && this._path._curves;
+		return curves && (curves[this._segment1._index + 1]
+				|| this._path._closed && curves[0]) || null;
+	},
+
+	getPrevious: function() {
+		var curves = this._path && this._path._curves;
+		return curves && (curves[this._segment1._index - 1]
+				|| this._path._closed && curves[curves.length - 1]) || null;
+	},
+
+	isFirst: function() {
+		return this._segment1._index === 0;
+	},
+
+	isLast: function() {
+		var path = this._path;
+		return path && this._segment1._index === path._curves.length - 1
+				|| false;
+	},
+
+	isSelected: function() {
+		return this.getPoint1().isSelected()
+				&& this.getHandle2().isSelected()
+				&& this.getHandle2().isSelected()
+				&& this.getPoint2().isSelected();
+	},
+
+	setSelected: function(selected) {
+		this.getPoint1().setSelected(selected);
+		this.getHandle1().setSelected(selected);
+		this.getHandle2().setSelected(selected);
+		this.getPoint2().setSelected(selected);
+	},
+
+	getValues: function(matrix) {
+		return Curve.getValues(this._segment1, this._segment2, matrix);
+	},
+
+	getPoints: function() {
+		var coords = this.getValues(),
+			points = [];
+		for (var i = 0; i < 8; i += 2)
+			points.push(new Point(coords[i], coords[i + 1]));
+		return points;
+	},
+
+	getLength: function() {
+		if (this._length == null)
+			this._length = Curve.getLength(this.getValues(), 0, 1);
+		return this._length;
+	},
+
+	getArea: function() {
+		return Curve.getArea(this.getValues());
+	},
+
+	getLine: function() {
+		return new Line(this._segment1._point, this._segment2._point);
+	},
+
+	getPart: function(from, to) {
+		return new Curve(Curve.getPart(this.getValues(), from, to));
+	},
+
+	getPartLength: function(from, to) {
+		return Curve.getLength(this.getValues(), from, to);
+	},
+
+	getIntersections: function(curve) {
+		return Curve._getIntersections(this.getValues(),
+				curve && curve !== this ? curve.getValues() : null,
+				this, curve, [], {});
+	},
+
+	divideAt: function(location) {
+		return this.divideAtTime(location && location.curve === this
+				? location.time : location);
+	},
+
+	divideAtTime: function(time, _setHandles) {
+		var tMin = 4e-7,
+			tMax = 1 - tMin,
+			res = null;
+		if (time >= tMin && time <= tMax) {
+			var parts = Curve.subdivide(this.getValues(), time),
+				left = parts[0],
+				right = parts[1],
+				setHandles = _setHandles || this.hasHandles(),
+				segment1 = this._segment1,
+				segment2 = this._segment2,
+				path = this._path;
+			if (setHandles) {
+				segment1._handleOut.set(left[2] - left[0], left[3] - left[1]);
+				segment2._handleIn.set(right[4] - right[6],right[5] - right[7]);
+			}
+			var x = left[6], y = left[7],
+				segment = new Segment(new Point(x, y),
+						setHandles && new Point(left[4] - x, left[5] - y),
+						setHandles && new Point(right[2] - x, right[3] - y));
+			if (path) {
+				path.insert(segment1._index + 1, segment);
+				res = this.getNext();
+			} else {
+				this._segment2 = segment;
+				this._changed();
+				res = new Curve(segment, segment2);
+			}
+		}
+		return res;
+	},
+
+	splitAt: function(location) {
+		return this._path ? this._path.splitAt(location) : null;
+	},
+
+	splitAtTime: function(t) {
+		return this.splitAt(this.getLocationAtTime(t));
+	},
+
+	divide: function(offset, isTime) {
+		return this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset
+				: this.getTimeAt(offset));
+	},
+
+	split: function(offset, isTime) {
+		return this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset
+				: this.getTimeAt(offset));
+	},
+
+	reversed: function() {
+		return new Curve(this._segment2.reversed(), this._segment1.reversed());
+	},
+
+	clearHandles: function() {
+		this._segment1._handleOut.set(0, 0);
+		this._segment2._handleIn.set(0, 0);
+	},
+
+statics: {
+	getValues: function(segment1, segment2, matrix) {
+		var p1 = segment1._point,
+			h1 = segment1._handleOut,
+			h2 = segment2._handleIn,
+			p2 = segment2._point,
+			values = [
+				p1._x, p1._y,
+				p1._x + h1._x, p1._y + h1._y,
+				p2._x + h2._x, p2._y + h2._y,
+				p2._x, p2._y
+			];
+		if (matrix)
+			matrix._transformCoordinates(values, values, 4);
+		return values;
+	},
+
+	subdivide: function(v, t) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7];
+		if (t === undefined)
+			t = 0.5;
+		var u = 1 - t,
+			p3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,
+			p4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,
+			p5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,
+			p6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,
+			p7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,
+			p8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;
+		return [
+			[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],
+			[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]
+		];
+	},
+
+	solveCubic: function (v, coord, val, roots, min, max) {
+		var p1 = v[coord],
+			c1 = v[coord + 2],
+			c2 = v[coord + 4],
+			p2 = v[coord + 6],
+			res = 0;
+		if (  !(p1 < val && p2 < val && c1 < val && c2 < val ||
+				p1 > val && p2 > val && c1 > val && c2 > val)) {
+			var c = 3 * (c1 - p1),
+				b = 3 * (c2 - c1) - c,
+				a = p2 - p1 - c - b;
+			res = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
+		}
+		return res;
+	},
+
+	getTimeOf: function(v, point) {
+		var p1 = new Point(v[0], v[1]),
+			p2 = new Point(v[6], v[7]),
+			epsilon = 1e-12,
+			t = point.isClose(p1, epsilon) ? 0
+			  : point.isClose(p2, epsilon) ? 1
+			  : null;
+		if (t !== null)
+			return t;
+		var coords = [point.x, point.y],
+			roots = [],
+			geomEpsilon = 2e-7;
+		for (var c = 0; c < 2; c++) {
+			var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);
+			for (var i = 0; i < count; i++) {
+				t = roots[i];
+				if (point.isClose(Curve.getPoint(v, t), geomEpsilon))
+					return t;
+			}
+		}
+		return point.isClose(p1, geomEpsilon) ? 0
+			 : point.isClose(p2, geomEpsilon) ? 1
+			 : null;
+	},
+
+	getNearestTime: function(v, point) {
+		if (Curve.isStraight(v)) {
+			var p1x = v[0], p1y = v[1],
+				p2x = v[6], p2y = v[7],
+				vx = p2x - p1x, vy = p2y - p1y,
+				det = vx * vx + vy * vy;
+			if (det === 0)
+				return 0;
+			var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
+			return u < 1e-12 ? 0
+				 : u > 0.999999999999 ? 1
+				 : Curve.getTimeOf(v,
+					new Point(p1x + u * vx, p1y + u * vy));
+		}
+
+		var count = 100,
+			minDist = Infinity,
+			minT = 0;
+
+		function refine(t) {
+			if (t >= 0 && t <= 1) {
+				var dist = point.getDistance(Curve.getPoint(v, t), true);
+				if (dist < minDist) {
+					minDist = dist;
+					minT = t;
+					return true;
+				}
+			}
+		}
+
+		for (var i = 0; i <= count; i++)
+			refine(i / count);
+
+		var step = 1 / (count * 2);
+		while (step > 4e-7) {
+			if (!refine(minT - step) && !refine(minT + step))
+				step /= 2;
+		}
+		return minT;
+	},
+
+	getPart: function(v, from, to) {
+		var flip = from > to;
+		if (flip) {
+			var tmp = from;
+			from = to;
+			to = tmp;
+		}
+		if (from > 0)
+			v = Curve.subdivide(v, from)[1];
+		if (to < 1)
+			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
+		return flip
+				? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]
+				: v;
+	},
+
+	isFlatEnough: function(v, flatness) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7],
+			ux = 3 * c1x - 2 * p1x - p2x,
+			uy = 3 * c1y - 2 * p1y - p2y,
+			vx = 3 * c2x - 2 * p2x - p1x,
+			vy = 3 * c2y - 2 * p2y - p1y;
+		return Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)
+				<= 16 * flatness * flatness;
+	},
+
+	getArea: function(v) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7];
+		return 3 * ((p2y - p1y) * (c1x + c2x) - (p2x - p1x) * (c1y + c2y)
+				+ c1y * (p1x - c2x) - c1x * (p1y - c2y)
+				+ p2y * (c2x + p1x / 3) - p2x * (c2y + p1y / 3)) / 20;
+	},
+
+	getBounds: function(v) {
+		var min = v.slice(0, 2),
+			max = min.slice(),
+			roots = [0, 0];
+		for (var i = 0; i < 2; i++)
+			Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
+					i, 0, min, max, roots);
+		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
+	},
+
+	_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
+		function add(value, padding) {
+			var left = value - padding,
+				right = value + padding;
+			if (left < min[coord])
+				min[coord] = left;
+			if (right > max[coord])
+				max[coord] = right;
+		}
+
+		padding /= 2;
+		var minPad = min[coord] - padding,
+			maxPad = max[coord] + padding;
+		if (    v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||
+				v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
+			if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {
+				add(v0, padding);
+				add(v3, padding);
+			} else {
+				var a = 3 * (v1 - v2) - v0 + v3,
+					b = 2 * (v0 + v2) - 4 * v1,
+					c = v1 - v0,
+					count = Numerical.solveQuadratic(a, b, c, roots),
+					tMin = 4e-7,
+					tMax = 1 - tMin;
+				add(v3, 0);
+				for (var i = 0; i < count; i++) {
+					var t = roots[i],
+						u = 1 - t;
+					if (tMin < t && t < tMax)
+						add(u * u * u * v0
+							+ 3 * u * u * t * v1
+							+ 3 * u * t * t * v2
+							+ t * t * t * v3,
+							padding);
+				}
+			}
+		}
+	}
+}}, Base.each(
+	['getBounds', 'getStrokeBounds', 'getHandleBounds'],
+	function(name) {
+		this[name] = function() {
+			if (!this._bounds)
+				this._bounds = {};
+			var bounds = this._bounds[name];
+			if (!bounds) {
+				bounds = this._bounds[name] = Path[name](
+						[this._segment1, this._segment2], false, this._path);
+			}
+			return bounds.clone();
+		};
+	},
+{
+
+}), Base.each({
+	isStraight: function(l, h1, h2) {
+		if (h1.isZero() && h2.isZero()) {
+			return true;
+		} else {
+			var v = l.getVector(),
+				epsilon = 2e-7;
+			if (v.isZero()) {
+				return false;
+			} else if (l.getDistance(h1) < epsilon
+					&& l.getDistance(h2) < epsilon) {
+				var div = v.dot(v),
+					p1 = v.dot(h1) / div,
+					p2 = v.dot(h2) / div;
+				return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
+			}
+		}
+		return false;
+	},
+
+	isLinear: function(l, h1, h2) {
+		var third = l.getVector().divide(3);
+		return h1.equals(third) && h2.negate().equals(third);
+	}
+}, function(test, name) {
+	this[name] = function() {
+		var seg1 = this._segment1,
+			seg2 = this._segment2;
+		return test(new Line(seg1._point, seg2._point),
+				seg1._handleOut, seg2._handleIn);
+	};
+
+	this.statics[name] = function(v) {
+		var p1x = v[0], p1y = v[1],
+			p2x = v[6], p2y = v[7];
+		return test(new Line(p1x, p1y, p2x, p2y),
+				new Point(v[2] - p1x, v[3] - p1y),
+				new Point(v[4] - p2x, v[5] - p2y));
+	};
+}, {
+	statics: {},
+
+	hasHandles: function() {
+		return !this._segment1._handleOut.isZero()
+				|| !this._segment2._handleIn.isZero();
+	},
+
+	isCollinear: function(curve) {
+		return curve && this.isStraight() && curve.isStraight()
+				&& this.getLine().isCollinear(curve.getLine());
+	},
+
+	isHorizontal: function() {
+		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)
+				< 1e-7;
+	},
+
+	isVertical: function() {
+		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)
+				< 1e-7;
+	}
+}), {
+	beans: false,
+
+	getLocationAt: function(offset, _isTime) {
+		return this.getLocationAtTime(
+				_isTime ? offset : this.getTimeAt(offset));
+	},
+
+	getLocationAtTime: function(t) {
+		return t != null && t >= 0 && t <= 1
+				? new CurveLocation(this, t)
+				: null;
+	},
+
+	getTimeAt: function(offset, start) {
+		return Curve.getTimeAt(this.getValues(), offset, start);
+	},
+
+	getParameterAt: '#getTimeAt',
+
+	getOffsetAtTime: function(t) {
+		return this.getPartLength(0, t);
+	},
+
+	getLocationOf: function() {
+		return this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));
+	},
+
+	getOffsetOf: function() {
+		var loc = this.getLocationOf.apply(this, arguments);
+		return loc ? loc.getOffset() : null;
+	},
+
+	getTimeOf: function() {
+		return Curve.getTimeOf(this.getValues(), Point.read(arguments));
+	},
+
+	getParameterOf: '#getTimeOf',
+
+	getNearestLocation: function() {
+		var point = Point.read(arguments),
+			values = this.getValues(),
+			t = Curve.getNearestTime(values, point),
+			pt = Curve.getPoint(values, t);
+		return new CurveLocation(this, t, pt, null, point.getDistance(pt));
+	},
+
+	getNearestPoint: function() {
+		var loc = this.getNearestLocation.apply(this, arguments);
+		return loc ? loc.getPoint() : loc;
+	}
+
+},
+new function() {
+	var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
+		'getWeightedNormal', 'getCurvature'];
+	return Base.each(methods,
+		function(name) {
+			this[name + 'At'] = function(location, _isTime) {
+				var values = this.getValues();
+				return Curve[name](values, _isTime ? location
+						: Curve.getTimeAt(values, location));
+			};
+
+			this[name + 'AtTime'] = function(time) {
+				return Curve[name](this.getValues(), time);
+			};
+		}, {
+			statics: {
+				_evaluateMethods: methods
+			}
+		}
+	);
+},
+new function() {
+
+	function getLengthIntegrand(v) {
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7],
+
+			ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
+			bx = 6 * (p1x + c2x) - 12 * c1x,
+			cx = 3 * (c1x - p1x),
+
+			ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
+			by = 6 * (p1y + c2y) - 12 * c1y,
+			cy = 3 * (c1y - p1y);
+
+		return function(t) {
+			var dx = (ax * t + bx) * t + cx,
+				dy = (ay * t + by) * t + cy;
+			return Math.sqrt(dx * dx + dy * dy);
+		};
+	}
+
+	function getIterations(a, b) {
+		return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
+	}
+
+	function evaluate(v, t, type, normalized) {
+		if (t == null || t < 0 || t > 1)
+			return null;
+		var p1x = v[0], p1y = v[1],
+			c1x = v[2], c1y = v[3],
+			c2x = v[4], c2y = v[5],
+			p2x = v[6], p2y = v[7],
+			isZero = Numerical.isZero;
+		if (isZero(c1x - p1x) && isZero(c1y - p1y)) {
+			c1x = p1x;
+			c1y = p1y;
+		}
+		if (isZero(c2x - p2x) && isZero(c2y - p2y)) {
+			c2x = p2x;
+			c2y = p2y;
+		}
+		var cx = 3 * (c1x - p1x),
+			bx = 3 * (c2x - c1x) - cx,
+			ax = p2x - p1x - cx - bx,
+			cy = 3 * (c1y - p1y),
+			by = 3 * (c2y - c1y) - cy,
+			ay = p2y - p1y - cy - by,
+			x, y;
+		if (type === 0) {
+			x = t === 0 ? p1x : t === 1 ? p2x
+					: ((ax * t + bx) * t + cx) * t + p1x;
+			y = t === 0 ? p1y : t === 1 ? p2y
+					: ((ay * t + by) * t + cy) * t + p1y;
+		} else {
+			var tMin = 4e-7,
+				tMax = 1 - tMin;
+			if (t < tMin) {
+				x = cx;
+				y = cy;
+			} else if (t > tMax) {
+				x = 3 * (p2x - c2x);
+				y = 3 * (p2y - c2y);
+			} else {
+				x = (3 * ax * t + 2 * bx) * t + cx;
+				y = (3 * ay * t + 2 * by) * t + cy;
+			}
+			if (normalized) {
+				if (x === 0 && y === 0 && (t < tMin || t > tMax)) {
+					x = c2x - c1x;
+					y = c2y - c1y;
+				}
+				var len = Math.sqrt(x * x + y * y);
+				if (len) {
+					x /= len;
+					y /= len;
+				}
+			}
+			if (type === 3) {
+				var x2 = 6 * ax * t + 2 * bx,
+					y2 = 6 * ay * t + 2 * by,
+					d = Math.pow(x * x + y * y, 3 / 2);
+				x = d !== 0 ? (x * y2 - y * x2) / d : 0;
+				y = 0;
+			}
+		}
+		return type === 2 ? new Point(y, -x) : new Point(x, y);
+	}
+
+	return { statics: {
+
+		getLength: function(v, a, b, ds) {
+			if (a === undefined)
+				a = 0;
+			if (b === undefined)
+				b = 1;
+			if (Curve.isStraight(v)) {
+				var c = v;
+				if (b < 1) {
+					c = Curve.subdivide(c, b)[0];
+					a /= b;
+				}
+				if (a > 0) {
+					c = Curve.subdivide(c, a)[1];
+				}
+				var dx = c[6] - c[0],
+					dy = c[7] - c[1];
+				return Math.sqrt(dx * dx + dy * dy);
+			}
+			return Numerical.integrate(ds || getLengthIntegrand(v), a, b,
+					getIterations(a, b));
+		},
+
+		getTimeAt: function(v, offset, start) {
+			if (start === undefined)
+				start = offset < 0 ? 1 : 0;
+			if (offset === 0)
+				return start;
+			var abs = Math.abs,
+				epsilon = 1e-12,
+				forward = offset > 0,
+				a = forward ? start : 0,
+				b = forward ? 1 : start,
+				ds = getLengthIntegrand(v),
+				rangeLength = Curve.getLength(v, a, b, ds),
+				diff = abs(offset) - rangeLength;
+			if (abs(diff) < epsilon) {
+				return forward ? b : a;
+			} else if (diff > epsilon) {
+				return null;
+			}
+			var guess = offset / rangeLength,
+				length = 0;
+			function f(t) {
+				length += Numerical.integrate(ds, start, t,
+						getIterations(start, t));
+				start = t;
+				return length - offset;
+			}
+			return Numerical.findRoot(f, ds, start + guess, a, b, 32,
+					1e-12);
+		},
+
+		getPoint: function(v, t) {
+			return evaluate(v, t, 0, false);
+		},
+
+		getTangent: function(v, t) {
+			return evaluate(v, t, 1, true);
+		},
+
+		getWeightedTangent: function(v, t) {
+			return evaluate(v, t, 1, false);
+		},
+
+		getNormal: function(v, t) {
+			return evaluate(v, t, 2, true);
+		},
+
+		getWeightedNormal: function(v, t) {
+			return evaluate(v, t, 2, false);
+		},
+
+		getCurvature: function(v, t) {
+			return evaluate(v, t, 3, false).x;
+		}
+	}};
+},
+new function() {
+
+	function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
+			overlap) {
+		var excludeStart = !overlap && param.excludeStart,
+			excludeEnd = !overlap && param.excludeEnd,
+			tMin = 4e-7,
+			tMax = 1 - tMin;
+		if (t1 == null)
+			t1 = Curve.getTimeOf(v1, p1);
+		if (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&
+			t1 <= (excludeEnd ? tMax : 1)) {
+			if (t2 == null)
+				t2 = Curve.getTimeOf(v2, p2);
+			if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
+				t2 <= (excludeStart ? tMax : 1)) {
+				var renormalize = param.renormalize;
+				if (renormalize) {
+					var res = renormalize(t1, t2);
+					t1 = res[0];
+					t2 = res[1];
+				}
+				var loc1 = new CurveLocation(c1, t1,
+						p1 || Curve.getPoint(v1, t1), overlap),
+					loc2 = new CurveLocation(c2, t2,
+						p2 || Curve.getPoint(v2, t2), overlap),
+					flip = loc1.getPath() === loc2.getPath()
+						&& loc1.getIndex() > loc2.getIndex(),
+					loc = flip ? loc2 : loc1,
+					include = param.include;
+				loc1._intersection = loc2;
+				loc2._intersection = loc1;
+				if (!include || include(loc)) {
+					CurveLocation.insert(locations, loc, true);
+				}
+			}
+		}
+	}
+
+	function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,
+			uMin, uMax, flip, recursion, calls) {
+		if (++recursion >= 48 || ++calls > 4096)
+			return calls;
+		var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
+			getSignedDistance = Line.getSignedDistance,
+			d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),
+			d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),
+			factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
+			dMin = factor * Math.min(0, d1, d2),
+			dMax = factor * Math.max(0, d1, d2),
+			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
+			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
+			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
+			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
+			hull = getConvexHull(dp0, dp1, dp2, dp3),
+			top = hull[0],
+			bottom = hull[1],
+			tMinClip,
+			tMaxClip;
+		if (d1 === 0 && d2 === 0
+				&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0
+			|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null
+			|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),
+				dMin, dMax)) == null)
+			return calls;
+		var tMinNew = tMin + (tMax - tMin) * tMinClip,
+			tMaxNew = tMin + (tMax - tMin) * tMaxClip;
+		if (Math.max(uMax - uMin, tMaxNew - tMinNew)
+				< 1e-9) {
+			var t = (tMinNew + tMaxNew) / 2,
+				u = (uMin + uMax) / 2;
+			v1 = c1.getValues();
+			v2 = c2.getValues();
+			addLocation(locations, param,
+					flip ? v2 : v1, flip ? c2 : c1, flip ? u : t, null,
+					flip ? v1 : v2, flip ? c1 : c2, flip ? t : u, null);
+		} else {
+			v1 = Curve.getPart(v1, tMinClip, tMaxClip);
+			if (tMaxClip - tMinClip > 0.8) {
+				if (tMaxNew - tMinNew > uMax - uMin) {
+					var parts = Curve.subdivide(v1, 0.5),
+						t = (tMinNew + tMaxNew) / 2;
+					calls = addCurveIntersections(
+							v2, parts[0], c2, c1, locations, param,
+							uMin, uMax, tMinNew, t, !flip, recursion, calls);
+					calls = addCurveIntersections(
+							v2, parts[1], c2, c1, locations, param,
+							uMin, uMax, t, tMaxNew, !flip, recursion, calls);
+				} else {
+					var parts = Curve.subdivide(v2, 0.5),
+						u = (uMin + uMax) / 2;
+					calls = addCurveIntersections(
+							parts[0], v1, c2, c1, locations, param,
+							uMin, u, tMinNew, tMaxNew, !flip, recursion, calls);
+					calls = addCurveIntersections(
+							parts[1], v1, c2, c1, locations, param,
+							u, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
+				}
+			} else {
+				calls = addCurveIntersections(
+						v2, v1, c2, c1, locations, param,
+						uMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
+			}
+		}
+		return calls;
+	}
+
+	function getConvexHull(dq0, dq1, dq2, dq3) {
+		var p0 = [ 0, dq0 ],
+			p1 = [ 1 / 3, dq1 ],
+			p2 = [ 2 / 3, dq2 ],
+			p3 = [ 1, dq3 ],
+			dist1 = dq1 - (2 * dq0 + dq3) / 3,
+			dist2 = dq2 - (dq0 + 2 * dq3) / 3,
+			hull;
+		if (dist1 * dist2 < 0) {
+			hull = [[p0, p1, p3], [p0, p2, p3]];
+		} else {
+			var distRatio = dist1 / dist2;
+			hull = [
+				distRatio >= 2 ? [p0, p1, p3]
+				: distRatio <= 0.5 ? [p0, p2, p3]
+				: [p0, p1, p2, p3],
+				[p0, p3]
+			];
+		}
+		return (dist1 || dist2) < 0 ? hull.reverse() : hull;
+	}
+
+	function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
+		if (hullTop[0][1] < dMin) {
+			return clipConvexHullPart(hullTop, true, dMin);
+		} else if (hullBottom[0][1] > dMax) {
+			return clipConvexHullPart(hullBottom, false, dMax);
+		} else {
+			return hullTop[0][0];
+		}
+	}
+
+	function clipConvexHullPart(part, top, threshold) {
+		var px = part[0][0],
+			py = part[0][1];
+		for (var i = 1, l = part.length; i < l; i++) {
+			var qx = part[i][0],
+				qy = part[i][1];
+			if (top ? qy >= threshold : qy <= threshold) {
+				return qy === threshold ? qx
+						: px + (threshold - py) * (qx - px) / (qy - py);
+			}
+			px = qx;
+			py = qy;
+		}
+		return null;
+	}
+
+	function addCurveLineIntersections(v1, v2, c1, c2, locations, param) {
+		var flip = Curve.isStraight(v1),
+			vc = flip ? v2 : v1,
+			vl = flip ? v1 : v2,
+			lx1 = vl[0], ly1 = vl[1],
+			lx2 = vl[6], ly2 = vl[7],
+			ldx = lx2 - lx1,
+			ldy = ly2 - ly1,
+			angle = Math.atan2(-ldy, ldx),
+			sin = Math.sin(angle),
+			cos = Math.cos(angle),
+			rvc = [];
+		for(var i = 0; i < 8; i += 2) {
+			var x = vc[i] - lx1,
+				y = vc[i + 1] - ly1;
+			rvc.push(
+				x * cos - y * sin,
+				x * sin + y * cos);
+		}
+		var roots = [],
+			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
+		for (var i = 0; i < count; i++) {
+			var tc = roots[i],
+				pc = Curve.getPoint(vc, tc),
+				tl = Curve.getTimeOf(vl, pc);
+			if (tl !== null) {
+				var pl = Curve.getPoint(vl, tl),
+					t1 = flip ? tl : tc,
+					t2 = flip ? tc : tl;
+				if (!param.excludeEnd || t2 > Numerical.CURVETIME_EPSILON) {
+					addLocation(locations, param,
+							v1, c1, t1, flip ? pl : pc,
+							v2, c2, t2, flip ? pc : pl);
+				}
+			}
+		}
+	}
+
+	function addLineIntersection(v1, v2, c1, c2, locations, param) {
+		var pt = Line.intersect(
+				v1[0], v1[1], v1[6], v1[7],
+				v2[0], v2[1], v2[6], v2[7]);
+		if (pt) {
+			addLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);
+		}
+	}
+
+	return { statics: {
+		_getIntersections: function(v1, v2, c1, c2, locations, param) {
+			if (!v2) {
+				return Curve._getSelfIntersection(v1, c1, locations, param);
+			}
+			var epsilon = 2e-7,
+				c1p1x = v1[0], c1p1y = v1[1],
+				c1p2x = v1[6], c1p2y = v1[7],
+				c2p1x = v2[0], c2p1y = v2[1],
+				c2p2x = v2[6], c2p2y = v2[7],
+				c1s1x = (3 * v1[2] + c1p1x) / 4,
+				c1s1y = (3 * v1[3] + c1p1y) / 4,
+				c1s2x = (3 * v1[4] + c1p2x) / 4,
+				c1s2y = (3 * v1[5] + c1p2y) / 4,
+				c2s1x = (3 * v2[2] + c2p1x) / 4,
+				c2s1y = (3 * v2[3] + c2p1y) / 4,
+				c2s2x = (3 * v2[4] + c2p2x) / 4,
+				c2s2y = (3 * v2[5] + c2p2y) / 4,
+				min = Math.min,
+				max = Math.max;
+			if (!(  max(c1p1x, c1s1x, c1s2x, c1p2x) + epsilon >
+					min(c2p1x, c2s1x, c2s2x, c2p2x) &&
+					min(c1p1x, c1s1x, c1s2x, c1p2x) - epsilon <
+					max(c2p1x, c2s1x, c2s2x, c2p2x) &&
+					max(c1p1y, c1s1y, c1s2y, c1p2y) + epsilon >
+					min(c2p1y, c2s1y, c2s2y, c2p2y) &&
+					min(c1p1y, c1s1y, c1s2y, c1p2y) - epsilon <
+					max(c2p1y, c2s1y, c2s2y, c2p2y)))
+				return locations;
+			var overlaps = Curve.getOverlaps(v1, v2);
+			if (overlaps) {
+				for (var i = 0; i < 2; i++) {
+					var overlap = overlaps[i];
+					addLocation(locations, param,
+						v1, c1, overlap[0], null,
+						v2, c2, overlap[1], null, true);
+				}
+				return locations;
+			}
+
+			var straight1 = Curve.isStraight(v1),
+				straight2 = Curve.isStraight(v2),
+				straight = straight1 && straight2,
+				before = locations.length;
+			(straight
+				? addLineIntersection
+				: straight1 || straight2
+					? addCurveLineIntersections
+					: addCurveIntersections)(
+						v1, v2, c1, c2, locations, param,
+						0, 1, 0, 1, 0, 0, 0);
+			if (straight && locations.length > before)
+				return locations;
+			var c1p1 = new Point(c1p1x, c1p1y),
+				c1p2 = new Point(c1p2x, c1p2y),
+				c2p1 = new Point(c2p1x, c2p1y),
+				c2p2 = new Point(c2p2x, c2p2y);
+			if (c1p1.isClose(c2p1, epsilon))
+				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);
+			if (!param.excludeStart && c1p1.isClose(c2p2, epsilon))
+				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);
+			if (!param.excludeEnd && c1p2.isClose(c2p1, epsilon))
+				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);
+			if (c1p2.isClose(c2p2, epsilon))
+				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);
+			return locations;
+		},
+
+		_getSelfIntersection: function(v1, c1, locations, param) {
+			var p1x = v1[0], p1y = v1[1],
+				h1x = v1[2], h1y = v1[3],
+				h2x = v1[4], h2y = v1[5],
+				p2x = v1[6], p2y = v1[7];
+			var line = new Line(p1x, p1y, p2x, p2y, false),
+				side1 = line.getSide(new Point(h1x, h1y), true),
+				side2 = line.getSide(new Point(h2x, h2y), true);
+			if (side1 === side2) {
+				var edgeSum = (p1x - h2x) * (h1y - p2y)
+							+ (h1x - p2x) * (h2y - p1y);
+				if (edgeSum * side1 > 0)
+					return locations;
+			}
+			var ax = p2x - 3 * h2x + 3 * h1x - p1x,
+				bx = h2x - 2 * h1x + p1x,
+				cx = h1x - p1x,
+				ay = p2y - 3 * h2y + 3 * h1y - p1y,
+				by = h2y - 2 * h1y + p1y,
+				cy = h1y - p1y,
+				ac = ay * cx - ax * cy,
+				ab = ay * bx - ax * by,
+				bc = by * cx - bx * cy;
+			if (ac * ac - 4 * ab * bc < 0) {
+				var roots = [],
+					tSplit,
+					count = Numerical.solveCubic(
+							ax * ax  + ay * ay,
+							3 * (ax * bx + ay * by),
+							2 * (bx * bx + by * by) + ax * cx + ay * cy,
+							bx * cx + by * cy,
+							roots, 0, 1);
+				if (count > 0) {
+					for (var i = 0, maxCurvature = 0; i < count; i++) {
+						var curvature = Math.abs(
+								c1.getCurvatureAtTime(roots[i]));
+						if (curvature > maxCurvature) {
+							maxCurvature = curvature;
+							tSplit = roots[i];
+						}
+					}
+					var parts = Curve.subdivide(v1, tSplit);
+					param.excludeEnd = true;
+					param.renormalize = function(t1, t2) {
+						return [t1 * tSplit, t2 * (1 - tSplit) + tSplit];
+					};
+					Curve._getIntersections(parts[0], parts[1], c1, c1,
+							locations, param);
+				}
+			}
+			return locations;
+		},
+
+		getOverlaps: function(v1, v2) {
+			var abs = Math.abs,
+				timeEpsilon = 4e-7,
+				geomEpsilon = 2e-7,
+				straight1 = Curve.isStraight(v1),
+				straight2 = Curve.isStraight(v2),
+				straightBoth = straight1 && straight2;
+
+			function getSquaredLineLength(v) {
+				var x = v[6] - v[0],
+					y = v[7] - v[1];
+				return x * x + y * y;
+			}
+
+			var flip = getSquaredLineLength(v1) < getSquaredLineLength(v2),
+				l1 = flip ? v2 : v1,
+				l2 = flip ? v1 : v2,
+				line = new Line(l1[0], l1[1], l1[6], l1[7]);
+			if (line.getDistance(new Point(l2[0], l2[1])) < geomEpsilon &&
+				line.getDistance(new Point(l2[6], l2[7])) < geomEpsilon) {
+				if (!straightBoth &&
+					line.getDistance(new Point(l1[2], l1[3])) < geomEpsilon &&
+					line.getDistance(new Point(l1[4], l1[5])) < geomEpsilon &&
+					line.getDistance(new Point(l2[2], l2[3])) < geomEpsilon &&
+					line.getDistance(new Point(l2[4], l2[5])) < geomEpsilon) {
+					straight1 = straight2 = straightBoth = true;
+				}
+			} else if (straightBoth) {
+				return null;
+			}
+			if (straight1 ^ straight2) {
+				return null;
+			}
+
+			var v = [v1, v2],
+				pairs = [];
+			for (var i = 0, t1 = 0;
+					i < 2 && pairs.length < 2;
+					i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
+				var t2 = Curve.getTimeOf(v[i ^ 1], new Point(
+						v[i][t1 === 0 ? 0 : 6],
+						v[i][t1 === 0 ? 1 : 7]));
+				if (t2 != null) {
+					var pair = i === 0 ? [t1, t2] : [t2, t1];
+					if (pairs.length === 0 ||
+						abs(pair[0] - pairs[0][0]) > timeEpsilon &&
+						abs(pair[1] - pairs[0][1]) > timeEpsilon)
+						pairs.push(pair);
+				}
+				if (i === 1 && pairs.length === 0)
+					break;
+			}
+			if (pairs.length !== 2) {
+				pairs = null;
+			} else if (!straightBoth) {
+				var o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),
+					o2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);
+				if (abs(o2[2] - o1[2]) > geomEpsilon ||
+					abs(o2[3] - o1[3]) > geomEpsilon ||
+					abs(o2[4] - o1[4]) > geomEpsilon ||
+					abs(o2[5] - o1[5]) > geomEpsilon)
+					pairs = null;
+			}
+			return pairs;
+		}
+	}};
+});
+
+var CurveLocation = Base.extend({
+	_class: 'CurveLocation',
+	beans: true,
+
+	initialize: function CurveLocation(curve, time, point, _overlap, _distance) {
+		if (time > 0.9999996) {
+			var next = curve.getNext();
+			if (next) {
+				time = 0;
+				curve = next;
+			}
+		}
+		this._setCurve(curve);
+		this._time = time;
+		this._point = point || curve.getPointAtTime(time);
+		this._overlap = _overlap;
+		this._distance = _distance;
+		this._intersection = this._next = this._previous = null;
+	},
+
+	_setCurve: function(curve) {
+		var path = curve._path;
+		this._path = path;
+		this._version = path ? path._version : 0;
+		this._curve = curve;
+		this._segment = null;
+		this._segment1 = curve._segment1;
+		this._segment2 = curve._segment2;
+	},
+
+	_setSegment: function(segment) {
+		this._setCurve(segment.getCurve());
+		this._segment = segment;
+		this._time = segment === this._segment1 ? 0 : 1;
+		this._point = segment._point.clone();
+	},
+
+	getSegment: function() {
+		var curve = this.getCurve(),
+			segment = this._segment;
+		if (!segment) {
+			var time = this.getTime();
+			if (time === 0) {
+				segment = curve._segment1;
+			} else if (time === 1) {
+				segment = curve._segment2;
+			} else if (time != null) {
+				segment = curve.getPartLength(0, time)
+					< curve.getPartLength(time, 1)
+						? curve._segment1
+						: curve._segment2;
+			}
+			this._segment = segment;
+		}
+		return segment;
+	},
+
+	getCurve: function() {
+		var path = this._path,
+			that = this;
+		if (path && path._version !== this._version) {
+			this._time = this._curve = this._offset = null;
+		}
+
+		function trySegment(segment) {
+			var curve = segment && segment.getCurve();
+			if (curve && (that._time = curve.getTimeOf(that._point))
+					!= null) {
+				that._setCurve(curve);
+				that._segment = segment;
+				return curve;
+			}
+		}
+
+		return this._curve
+			|| trySegment(this._segment)
+			|| trySegment(this._segment1)
+			|| trySegment(this._segment2.getPrevious());
+	},
+
+	getPath: function() {
+		var curve = this.getCurve();
+		return curve && curve._path;
+	},
+
+	getIndex: function() {
+		var curve = this.getCurve();
+		return curve && curve.getIndex();
+	},
+
+	getTime: function() {
+		var curve = this.getCurve(),
+			time = this._time;
+		return curve && time == null
+			? this._time = curve.getTimeOf(this._point)
+			: time;
+	},
+
+	getParameter: '#getTime',
+
+	getPoint: function() {
+		return this._point;
+	},
+
+	getOffset: function() {
+		var offset = this._offset;
+		if (offset == null) {
+			offset = 0;
+			var path = this.getPath(),
+				index = this.getIndex();
+			if (path && index != null) {
+				var curves = path.getCurves();
+				for (var i = 0; i < index; i++)
+					offset += curves[i].getLength();
+			}
+			this._offset = offset += this.getCurveOffset();
+		}
+		return offset;
+	},
+
+	getCurveOffset: function() {
+		var curve = this.getCurve(),
+			time = this.getTime();
+		return time != null && curve && curve.getPartLength(0, time);
+	},
+
+	getIntersection: function() {
+		return this._intersection;
+	},
+
+	getDistance: function() {
+		return this._distance;
+	},
+
+	divide: function() {
+		var curve = this.getCurve(),
+			res = null;
+		if (curve) {
+			res = curve.divideAtTime(this.getTime());
+			if (res)
+				this._setSegment(res._segment1);
+		}
+		return res;
+	},
+
+	split: function() {
+		var curve = this.getCurve();
+		return curve ? curve.splitAtTime(this.getTime()) : null;
+	},
+
+	equals: function(loc, _ignoreOther) {
+		var res = this === loc,
+			epsilon = 2e-7;
+		if (!res && loc instanceof CurveLocation
+				&& this.getPath() === loc.getPath()
+				&& this.getPoint().isClose(loc.getPoint(), epsilon)) {
+			var c1 = this.getCurve(),
+				c2 = loc.getCurve(),
+				abs = Math.abs,
+				diff = abs(
+					((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
+							+ this.getTime()) -
+					((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
+							+ loc.getTime()));
+			res = (diff < 4e-7
+				|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon
+					|| abs(this.getPath().getLength() - diff) < epsilon))
+				&& (_ignoreOther
+					|| (!this._intersection && !loc._intersection
+						|| this._intersection && this._intersection.equals(
+								loc._intersection, true)));
+		}
+		return res;
+	},
+
+	toString: function() {
+		var parts = [],
+			point = this.getPoint(),
+			f = Formatter.instance;
+		if (point)
+			parts.push('point: ' + point);
+		var index = this.getIndex();
+		if (index != null)
+			parts.push('index: ' + index);
+		var time = this.getTime();
+		if (time != null)
+			parts.push('time: ' + f.number(time));
+		if (this._distance != null)
+			parts.push('distance: ' + f.number(this._distance));
+		return '{ ' + parts.join(', ') + ' }';
+	},
+
+	isTouching: function() {
+		var inter = this._intersection;
+		if (inter && this.getTangent().isCollinear(inter.getTangent())) {
+			var curve1 = this.getCurve(),
+				curve2 = inter.getCurve();
+			return !(curve1.isStraight() && curve2.isStraight()
+					&& curve1.getLine().intersect(curve2.getLine()));
+		}
+		return false;
+	},
+
+	isCrossing: function() {
+		var inter = this._intersection;
+		if (!inter)
+			return false;
+		var t1 = this.getTime(),
+			t2 = inter.getTime(),
+			tMin = 4e-7,
+			tMax = 1 - tMin,
+			t1Inside = t1 > tMin && t1 < tMax,
+			t2Inside = t2 > tMin && t2 < tMax;
+		if (t1Inside && t2Inside)
+			return !this.isTouching();
+		var c2 = this.getCurve(),
+			c1 = t1 <= tMin ? c2.getPrevious() : c2,
+			c4 = inter.getCurve(),
+			c3 = t2 <= tMin ? c4.getPrevious() : c4;
+		if (t1 >= tMax)
+			c2 = c2.getNext();
+		if (t2 >= tMax)
+			c4 = c4.getNext();
+		if (!c1 || !c2 || !c3 || !c4)
+			return false;
+
+		function isInRange(angle, min, max) {
+			return min < max
+					? angle > min && angle < max
+					: angle > min || angle < max;
+		}
+
+		var lenghts = [];
+		if (!t1Inside)
+			lenghts.push(c1.getLength(), c2.getLength());
+		if (!t2Inside)
+			lenghts.push(c3.getLength(), c4.getLength());
+		var pt = this.getPoint(),
+			offset = Math.min.apply(Math, lenghts) / 64,
+			v2 = t1Inside ? c2.getTangentAtTime(t1)
+					: c2.getPointAt(offset).subtract(pt),
+			v1 = t1Inside ? v2.negate()
+					: c1.getPointAt(-offset).subtract(pt),
+			v4 = t2Inside ? c4.getTangentAtTime(t2)
+					: c4.getPointAt(offset).subtract(pt),
+			v3 = t2Inside ? v4.negate()
+					: c3.getPointAt(-offset).subtract(pt),
+			a1 = v1.getAngle(),
+			a2 = v2.getAngle(),
+			a3 = v3.getAngle(),
+			a4 = v4.getAngle();
+		return !!(t1Inside
+				? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&
+				  (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))
+				: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&
+				  (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));
+	},
+
+	hasOverlap: function() {
+		return !!this._overlap;
+	}
+}, Base.each(Curve._evaluateMethods, function(name) {
+	var get = name + 'At';
+	this[name] = function() {
+		var curve = this.getCurve(),
+			time = this.getTime();
+		return time != null && curve && curve[get](time, true);
+	};
+}, {
+	preserve: true
+}),
+new function() {
+
+	function insert(locations, loc, merge) {
+		var length = locations.length,
+			l = 0,
+			r = length - 1;
+
+		function search(index, dir) {
+			for (var i = index + dir; i >= -1 && i <= length; i += dir) {
+				var loc2 = locations[((i % length) + length) % length];
+				if (!loc.getPoint().isClose(loc2.getPoint(),
+						2e-7))
+					break;
+				if (loc.equals(loc2))
+					return loc2;
+			}
+			return null;
+		}
+
+		while (l <= r) {
+			var m = (l + r) >>> 1,
+				loc2 = locations[m],
+				found;
+			if (merge && (found = loc.equals(loc2) ? loc2
+					: (search(m, -1) || search(m, 1)))) {
+				if (loc._overlap) {
+					found._overlap = found._intersection._overlap = true;
+				}
+				return found;
+			}
+		var path1 = loc.getPath(),
+			path2 = loc2.getPath(),
+			diff = path1 === path2
+				? (loc.getIndex() + loc.getTime())
+				- (loc2.getIndex() + loc2.getTime())
+				: path1._id - path2._id;
+			if (diff < 0) {
+				r = m - 1;
+			} else {
+				l = m + 1;
+			}
+		}
+		locations.splice(l, 0, loc);
+		return loc;
+	}
+
+	return { statics: {
+		insert: insert,
+
+		expand: function(locations) {
+			var expanded = locations.slice();
+			for (var i = locations.length - 1; i >= 0; i--) {
+				insert(expanded, locations[i]._intersection, false);
+			}
+			return expanded;
+		}
+	}};
+});
+
+var PathItem = Item.extend({
+	_class: 'PathItem',
+	_selectBounds: false,
+	_canScaleStroke: true,
+
+	initialize: function PathItem() {
+	},
+
+	statics: {
+		create: function(pathData) {
+			var ctor = (pathData && pathData.match(/m/gi) || []).length > 1
+					|| /z\s*\S+/i.test(pathData) ? CompoundPath : Path;
+			return new ctor(pathData);
+		}
+	},
+
+	_asPathItem: function() {
+		return this;
+	},
+
+	setPathData: function(data) {
+
+		var parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),
+			coords,
+			relative = false,
+			previous,
+			control,
+			current = new Point(),
+			start = new Point();
+
+		function getCoord(index, coord) {
+			var val = +coords[index];
+			if (relative)
+				val += current[coord];
+			return val;
+		}
+
+		function getPoint(index) {
+			return new Point(
+				getCoord(index, 'x'),
+				getCoord(index + 1, 'y')
+			);
+		}
+
+		this.clear();
+
+		for (var i = 0, l = parts && parts.length; i < l; i++) {
+			var part = parts[i],
+				command = part[0],
+				lower = command.toLowerCase();
+			coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
+			var length = coords && coords.length;
+			relative = command === lower;
+			if (previous === 'z' && !/[mz]/.test(lower))
+				this.moveTo(current = start);
+			switch (lower) {
+			case 'm':
+			case 'l':
+				var move = lower === 'm';
+				for (var j = 0; j < length; j += 2)
+					this[j === 0 && move ? 'moveTo' : 'lineTo'](
+							current = getPoint(j));
+				control = current;
+				if (move)
+					start = current;
+				break;
+			case 'h':
+			case 'v':
+				var coord = lower === 'h' ? 'x' : 'y';
+				for (var j = 0; j < length; j++) {
+					current[coord] = getCoord(j, coord);
+					this.lineTo(current);
+				}
+				control = current;
+				break;
+			case 'c':
+				for (var j = 0; j < length; j += 6) {
+					this.cubicCurveTo(
+							getPoint(j),
+							control = getPoint(j + 2),
+							current = getPoint(j + 4));
+				}
+				break;
+			case 's':
+				for (var j = 0; j < length; j += 4) {
+					this.cubicCurveTo(
+							/[cs]/.test(previous)
+									? current.multiply(2).subtract(control)
+									: current,
+							control = getPoint(j),
+							current = getPoint(j + 2));
+					previous = lower;
+				}
+				break;
+			case 'q':
+				for (var j = 0; j < length; j += 4) {
+					this.quadraticCurveTo(
+							control = getPoint(j),
+							current = getPoint(j + 2));
+				}
+				break;
+			case 't':
+				for (var j = 0; j < length; j += 2) {
+					this.quadraticCurveTo(
+							control = (/[qt]/.test(previous)
+									? current.multiply(2).subtract(control)
+									: current),
+							current = getPoint(j));
+					previous = lower;
+				}
+				break;
+			case 'a':
+				for (var j = 0; j < length; j += 7) {
+					this.arcTo(current = getPoint(j + 5),
+							new Size(+coords[j], +coords[j + 1]),
+							+coords[j + 2], +coords[j + 4], +coords[j + 3]);
+				}
+				break;
+			case 'z':
+				this.closePath(1e-12);
+				break;
+			}
+			previous = lower;
+		}
+	},
+
+	_canComposite: function() {
+		return !(this.hasFill() && this.hasStroke());
+	},
+
+	_contains: function(point) {
+		var winding = point.isInside(
+				this.getBounds({ internal: true, handle: true }))
+					&& this._getWinding(point);
+		return !!(this.getFillRule() === 'evenodd' ? winding & 1 : winding);
+	},
+
+	getIntersections: function(path, include, _matrix, _returnFirst) {
+		var self = this === path || !path,
+			matrix1 = this._matrix._orNullIfIdentity(),
+			matrix2 = self ? matrix1
+				: (_matrix || path._matrix)._orNullIfIdentity();
+		if (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
+			return [];
+		var curves1 = this.getCurves(),
+			curves2 = self ? curves1 : path.getCurves(),
+			length1 = curves1.length,
+			length2 = self ? length1 : curves2.length,
+			values2 = [],
+			arrays = [],
+			locations,
+			path;
+		for (var i = 0; i < length2; i++)
+			values2[i] = curves2[i].getValues(matrix2);
+		for (var i = 0; i < length1; i++) {
+			var curve1 = curves1[i],
+				values1 = self ? values2[i] : curve1.getValues(matrix1),
+				path1 = curve1.getPath();
+			if (path1 !== path) {
+				path = path1;
+				locations = [];
+				arrays.push(locations);
+			}
+			if (self) {
+				Curve._getSelfIntersection(values1, curve1, locations, {
+					include: include,
+					excludeStart: length1 === 1 &&
+							curve1.getPoint1().equals(curve1.getPoint2())
+				});
+			}
+			for (var j = self ? i + 1 : 0; j < length2; j++) {
+				if (_returnFirst && locations.length)
+					return locations;
+				var curve2 = curves2[j];
+				Curve._getIntersections(
+					values1, values2[j], curve1, curve2, locations,
+					{
+						include: include,
+						excludeStart: self && curve1.getPrevious() === curve2,
+						excludeEnd: self && curve1.getNext() === curve2
+					}
+				);
+			}
+		}
+		locations = [];
+		for (var i = 0, l = arrays.length; i < l; i++) {
+			locations.push.apply(locations, arrays[i]);
+		}
+		return locations;
+	},
+
+	getCrossings: function(path) {
+		return this.getIntersections(path, function(inter) {
+			return inter._overlap || inter.isCrossing();
+		});
+	},
+
+	getNearestLocation: function() {
+		var point = Point.read(arguments),
+			curves = this.getCurves(),
+			minDist = Infinity,
+			minLoc = null;
+		for (var i = 0, l = curves.length; i < l; i++) {
+			var loc = curves[i].getNearestLocation(point);
+			if (loc._distance < minDist) {
+				minDist = loc._distance;
+				minLoc = loc;
+			}
+		}
+		return minLoc;
+	},
+
+	getNearestPoint: function() {
+		var loc = this.getNearestLocation.apply(this, arguments);
+		return loc ? loc.getPoint() : loc;
+	},
+
+	interpolate: function(from, to, factor) {
+		var isPath = !this._children,
+			name = isPath ? '_segments' : '_children',
+			itemsFrom = from[name],
+			itemsTo = to[name],
+			items = this[name];
+		if (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {
+			throw new Error('Invalid operands in interpolate() call: ' +
+					from + ', ' + to);
+		}
+		var current = items.length,
+			length = itemsTo.length;
+		if (current < length) {
+			var ctor = isPath ? Segment : Path;
+			for (var i = current; i < length; i++) {
+				this.add(new ctor());
+			}
+		} else if (current > length) {
+			this[isPath ? 'removeSegments' : 'removeChildren'](length, current);
+		}
+		for (var i = 0; i < length; i++) {
+			items[i].interpolate(itemsFrom[i], itemsTo[i], factor);
+		}
+		if (isPath) {
+			this.setClosed(from._closed);
+			this._changed(9);
+		}
+	},
+
+});
+
+var Path = PathItem.extend({
+	_class: 'Path',
+	_serializeFields: {
+		segments: [],
+		closed: false
+	},
+
+	initialize: function Path(arg) {
+		this._closed = false;
+		this._segments = [];
+		this._version = 0;
+		var segments = Array.isArray(arg)
+			? typeof arg[0] === 'object'
+				? arg
+				: arguments
+			: arg && (arg.size === undefined && (arg.x !== undefined
+					|| arg.point !== undefined))
+				? arguments
+				: null;
+		if (segments && segments.length > 0) {
+			this.setSegments(segments);
+		} else {
+			this._curves = undefined;
+			this._segmentSelection = 0;
+			if (!segments && typeof arg === 'string') {
+				this.setPathData(arg);
+				arg = null;
+			}
+		}
+		this._initialize(!segments && arg);
+	},
+
+	_equals: function(item) {
+		return this._closed === item._closed
+				&& Base.equals(this._segments, item._segments);
+	},
+
+	copyContent: function(source) {
+		this.setSegments(source._segments);
+		this._closed = source._closed;
+		var clockwise = source._clockwise;
+		if (clockwise !== undefined)
+			this._clockwise = clockwise;
+	},
+
+	_changed: function _changed(flags) {
+		_changed.base.call(this, flags);
+		if (flags & 8) {
+			this._length = this._area = this._clockwise = this._monoCurves =
+					undefined;
+			if (flags & 16) {
+				this._version++;
+			} else if (this._curves) {
+			   for (var i = 0, l = this._curves.length; i < l; i++)
+					this._curves[i]._changed();
+			}
+		} else if (flags & 32) {
+			this._bounds = undefined;
+		}
+	},
+
+	getStyle: function() {
+		var parent = this._parent;
+		return (parent instanceof CompoundPath ? parent : this)._style;
+	},
+
+	getSegments: function() {
+		return this._segments;
+	},
+
+	setSegments: function(segments) {
+		var fullySelected = this.isFullySelected();
+		this._segments.length = 0;
+		this._segmentSelection = 0;
+		this._curves = undefined;
+		if (segments && segments.length > 0)
+			this._add(Segment.readAll(segments));
+		if (fullySelected)
+			this.setFullySelected(true);
+	},
+
+	getFirstSegment: function() {
+		return this._segments[0];
+	},
+
+	getLastSegment: function() {
+		return this._segments[this._segments.length - 1];
+	},
+
+	getCurves: function() {
+		var curves = this._curves,
+			segments = this._segments;
+		if (!curves) {
+			var length = this._countCurves();
+			curves = this._curves = new Array(length);
+			for (var i = 0; i < length; i++)
+				curves[i] = new Curve(this, segments[i],
+					segments[i + 1] || segments[0]);
+		}
+		return curves;
+	},
+
+	getFirstCurve: function() {
+		return this.getCurves()[0];
+	},
+
+	getLastCurve: function() {
+		var curves = this.getCurves();
+		return curves[curves.length - 1];
+	},
+
+	isClosed: function() {
+		return this._closed;
+	},
+
+	setClosed: function(closed) {
+		if (this._closed != (closed = !!closed)) {
+			this._closed = closed;
+			if (this._curves) {
+				var length = this._curves.length = this._countCurves();
+				if (closed)
+					this._curves[length - 1] = new Curve(this,
+						this._segments[length - 1], this._segments[0]);
+			}
+			this._changed(25);
+		}
+	}
+}, {
+	beans: true,
+
+	getPathData: function(_matrix, _precision) {
+		var segments = this._segments,
+			length = segments.length,
+			f = new Formatter(_precision),
+			coords = new Array(6),
+			first = true,
+			curX, curY,
+			prevX, prevY,
+			inX, inY,
+			outX, outY,
+			parts = [];
+
+		function addSegment(segment, skipLine) {
+			segment._transformCoordinates(_matrix, coords);
+			curX = coords[0];
+			curY = coords[1];
+			if (first) {
+				parts.push('M' + f.pair(curX, curY));
+				first = false;
+			} else {
+				inX = coords[2];
+				inY = coords[3];
+				if (inX === curX && inY === curY
+						&& outX === prevX && outY === prevY) {
+					if (!skipLine)
+						parts.push('l' + f.pair(curX - prevX, curY - prevY));
+				} else {
+					parts.push('c' + f.pair(outX - prevX, outY - prevY)
+							+ ' ' + f.pair(inX - prevX, inY - prevY)
+							+ ' ' + f.pair(curX - prevX, curY - prevY));
+				}
+			}
+			prevX = curX;
+			prevY = curY;
+			outX = coords[4];
+			outY = coords[5];
+		}
+
+		if (length === 0)
+			return '';
+
+		for (var i = 0; i < length; i++)
+			addSegment(segments[i]);
+		if (this._closed && length > 0) {
+			addSegment(segments[0], true);
+			parts.push('z');
+		}
+		return parts.join('');
+	},
+
+	isEmpty: function() {
+		return this._segments.length === 0;
+	},
+
+	_transformContent: function(matrix) {
+		var segments = this._segments,
+			coords = new Array(6);
+		for (var i = 0, l = segments.length; i < l; i++)
+			segments[i]._transformCoordinates(matrix, coords, true);
+		return true;
+	},
+
+	_add: function(segs, index) {
+		var segments = this._segments,
+			curves = this._curves,
+			amount = segs.length,
+			append = index == null,
+			index = append ? segments.length : index;
+		for (var i = 0; i < amount; i++) {
+			var segment = segs[i];
+			if (segment._path)
+				segment = segs[i] = segment.clone();
+			segment._path = this;
+			segment._index = index + i;
+			if (segment._selection)
+				this._updateSelection(segment, 0, segment._selection);
+		}
+		if (append) {
+			segments.push.apply(segments, segs);
+		} else {
+			segments.splice.apply(segments, [index, 0].concat(segs));
+			for (var i = index + amount, l = segments.length; i < l; i++)
+				segments[i]._index = i;
+		}
+		if (curves) {
+			var total = this._countCurves(),
+				start = index > 0 && index + amount - 1 === total ? index - 1
+					: index,
+				insert = start,
+				end = Math.min(start + amount, total);
+			if (segs._curves) {
+				curves.splice.apply(curves, [start, 0].concat(segs._curves));
+				insert += segs._curves.length;
+			}
+			for (var i = insert; i < end; i++)
+				curves.splice(i, 0, new Curve(this, null, null));
+			this._adjustCurves(start, end);
+		}
+		this._changed(25);
+		return segs;
+	},
+
+	_adjustCurves: function(start, end) {
+		var segments = this._segments,
+			curves = this._curves,
+			curve;
+		for (var i = start; i < end; i++) {
+			curve = curves[i];
+			curve._path = this;
+			curve._segment1 = segments[i];
+			curve._segment2 = segments[i + 1] || segments[0];
+			curve._changed();
+		}
+		if (curve = curves[this._closed && start === 0 ? segments.length - 1
+				: start - 1]) {
+			curve._segment2 = segments[start] || segments[0];
+			curve._changed();
+		}
+		if (curve = curves[end]) {
+			curve._segment1 = segments[end];
+			curve._changed();
+		}
+	},
+
+	_countCurves: function() {
+		var length = this._segments.length;
+		return !this._closed && length > 0 ? length - 1 : length;
+	},
+
+	add: function(segment1 ) {
+		return arguments.length > 1 && typeof segment1 !== 'number'
+			? this._add(Segment.readAll(arguments))
+			: this._add([ Segment.read(arguments) ])[0];
+	},
+
+	insert: function(index, segment1 ) {
+		return arguments.length > 2 && typeof segment1 !== 'number'
+			? this._add(Segment.readAll(arguments, 1), index)
+			: this._add([ Segment.read(arguments, 1) ], index)[0];
+	},
+
+	addSegment: function() {
+		return this._add([ Segment.read(arguments) ])[0];
+	},
+
+	insertSegment: function(index ) {
+		return this._add([ Segment.read(arguments, 1) ], index)[0];
+	},
+
+	addSegments: function(segments) {
+		return this._add(Segment.readAll(segments));
+	},
+
+	insertSegments: function(index, segments) {
+		return this._add(Segment.readAll(segments), index);
+	},
+
+	removeSegment: function(index) {
+		return this.removeSegments(index, index + 1)[0] || null;
+	},
+
+	removeSegments: function(start, end, _includeCurves) {
+		start = start || 0;
+		end = Base.pick(end, this._segments.length);
+		var segments = this._segments,
+			curves = this._curves,
+			count = segments.length,
+			removed = segments.splice(start, end - start),
+			amount = removed.length;
+		if (!amount)
+			return removed;
+		for (var i = 0; i < amount; i++) {
+			var segment = removed[i];
+			if (segment._selection)
+				this._updateSelection(segment, segment._selection, 0);
+			segment._index = segment._path = null;
+		}
+		for (var i = start, l = segments.length; i < l; i++)
+			segments[i]._index = i;
+		if (curves) {
+			var index = start > 0 && end === count + (this._closed ? 1 : 0)
+					? start - 1
+					: start,
+				curves = curves.splice(index, amount);
+			for (var i = curves.length - 1; i >= 0; i--)
+				curves[i]._path = null;
+			if (_includeCurves)
+				removed._curves = curves.slice(1);
+			this._adjustCurves(index, index);
+		}
+		this._changed(25);
+		return removed;
+	},
+
+	clear: '#removeSegments',
+
+	hasHandles: function() {
+		var segments = this._segments;
+		for (var i = 0, l = segments.length; i < l; i++) {
+			if (segments[i].hasHandles())
+				return true;
+		}
+		return false;
+	},
+
+	clearHandles: function() {
+		var segments = this._segments;
+		for (var i = 0, l = segments.length; i < l; i++)
+			segments[i].clearHandles();
+	},
+
+	getLength: function() {
+		if (this._length == null) {
+			var curves = this.getCurves(),
+				length = 0;
+			for (var i = 0, l = curves.length; i < l; i++)
+				length += curves[i].getLength();
+			this._length = length;
+		}
+		return this._length;
+	},
+
+	getArea: function(_closed) {
+		var cached = _closed === undefined,
+			area = this._area;
+		if (!cached || area == null) {
+			var segments = this._segments,
+				count = segments.length,
+				closed = cached ? this._closed : _closed,
+				last = count - 1;
+			area = 0;
+			for (var i = 0, l = closed ? count : last; i < l; i++) {
+				area += Curve.getArea(Curve.getValues(
+						segments[i], segments[i < last ? i + 1 : 0]));
+			}
+			if (cached)
+				this._area = area;
+		}
+		return area;
+	},
+
+	isClockwise: function() {
+		if (this._clockwise !== undefined)
+			return this._clockwise;
+		return this.getArea() >= 0;
+	},
+
+	setClockwise: function(clockwise) {
+		if (this.isClockwise() != (clockwise = !!clockwise))
+			this.reverse();
+		this._clockwise = clockwise;
+	},
+
+	isFullySelected: function() {
+		var length = this._segments.length;
+		return this.isSelected() && length > 0 && this._segmentSelection
+				=== length * 7;
+	},
+
+	setFullySelected: function(selected) {
+		if (selected)
+			this._selectSegments(true);
+		this.setSelected(selected);
+	},
+
+	setSelection: function setSelection(selection) {
+		if (!(selection & 1))
+			this._selectSegments(false);
+		setSelection.base.call(this, selection);
+	},
+
+	_selectSegments: function(selected) {
+		var segments = this._segments,
+			length = segments.length,
+			selection = selected ? 7 : 0;
+		this._segmentSelection = selection * length;
+		for (var i = 0; i < length; i++)
+			segments[i]._selection = selection;
+	},
+
+	_updateSelection: function(segment, oldSelection, newSelection) {
+		segment._selection = newSelection;
+		var selection = this._segmentSelection += newSelection - oldSelection;
+		if (selection > 0)
+			this.setSelected(true);
+	},
+
+	splitAt: function(location) {
+		var loc = typeof location === 'number'
+				? this.getLocationAt(location) : location,
+			index = loc && loc.index,
+			time = loc && loc.time,
+			tMin = 4e-7,
+			tMax = 1 - tMin;
+		if (time >= tMax) {
+			index++;
+			time = 0;
+		}
+		var curves = this.getCurves();
+		if (index >= 0 && index < curves.length) {
+			if (time >= tMin) {
+				curves[index++].divideAtTime(time);
+			}
+			var segs = this.removeSegments(index, this._segments.length, true),
+				path;
+			if (this._closed) {
+				this.setClosed(false);
+				path = this;
+			} else {
+				path = new Path(Item.NO_INSERT);
+				path.insertAbove(this, true);
+				path.copyAttributes(this);
+			}
+			path._add(segs, 0);
+			this.addSegment(segs[0]);
+			return path;
+		}
+		return null;
+	},
+
+	split: function(index, time) {
+		var curve,
+			location = time === undefined ? index
+				: (curve = this.getCurves()[index])
+					&& curve.getLocationAtTime(time);
+		return location != null ? this.splitAt(location) : null;
+	},
+
+	join: function(path, tolerance) {
+		var epsilon = tolerance || 0;
+		if (path && path !== this) {
+			var segments = path._segments,
+				last1 = this.getLastSegment(),
+				last2 = path.getLastSegment();
+			if (!last2)
+				return this;
+			if (last1 && last1._point.isClose(last2._point, epsilon))
+				path.reverse();
+			var first2 = path.getFirstSegment();
+			if (last1 && last1._point.isClose(first2._point, epsilon)) {
+				last1.setHandleOut(first2._handleOut);
+				this._add(segments.slice(1));
+			} else {
+				var first1 = this.getFirstSegment();
+				if (first1 && first1._point.isClose(first2._point, epsilon))
+					path.reverse();
+				last2 = path.getLastSegment();
+				if (first1 && first1._point.isClose(last2._point, epsilon)) {
+					first1.setHandleIn(last2._handleIn);
+					this._add(segments.slice(0, segments.length - 1), 0);
+				} else {
+					this._add(segments.slice());
+				}
+			}
+			if (path._closed)
+				this._add([segments[0]]);
+			path.remove();
+		}
+		var first = this.getFirstSegment(),
+			last = this.getLastSegment();
+		if (first !== last && first._point.isClose(last._point, epsilon)) {
+			first.setHandleIn(last._handleIn);
+			last.remove();
+			this.setClosed(true);
+		}
+		return this;
+	},
+
+	reduce: function(options) {
+		var curves = this.getCurves(),
+			simplify = options && options.simplify,
+			tolerance = simplify ? 2e-7 : 0;
+		for (var i = curves.length - 1; i >= 0; i--) {
+			var curve = curves[i];
+			if (!curve.hasHandles() && (curve.getLength() < tolerance
+					|| simplify && curve.isCollinear(curve.getNext())))
+				curve.remove();
+		}
+		return this;
+	},
+
+	reverse: function() {
+		this._segments.reverse();
+		for (var i = 0, l = this._segments.length; i < l; i++) {
+			var segment = this._segments[i];
+			var handleIn = segment._handleIn;
+			segment._handleIn = segment._handleOut;
+			segment._handleOut = handleIn;
+			segment._index = i;
+		}
+		this._curves = null;
+		if (this._clockwise !== undefined)
+			this._clockwise = !this._clockwise;
+		this._changed(9);
+	},
+
+	flatten: function(flatness) {
+		var iterator = new PathIterator(this, flatness || 0.25, 256, true),
+			parts = iterator.parts,
+			length = parts.length,
+			segments = [];
+		for (var i = 0; i < length; i++) {
+			segments.push(new Segment(parts[i].curve.slice(0, 2)));
+		}
+		if (!this._closed && length > 0) {
+			segments.push(new Segment(parts[length - 1].curve.slice(6)));
+		}
+		this.setSegments(segments);
+	},
+
+	simplify: function(tolerance) {
+		var segments = new PathFitter(this).fit(tolerance || 2.5);
+		if (segments)
+			this.setSegments(segments);
+		return !!segments;
+	},
+
+	smooth: function(options) {
+		var that = this,
+			opts = options || {},
+			type = opts.type || 'asymmetric',
+			segments = this._segments,
+			length = segments.length,
+			closed = this._closed;
+
+		function getIndex(value, _default) {
+			var index = value && value.index;
+			if (index != null) {
+				var path = value.path;
+				if (path && path !== that)
+					throw new Error(value._class + ' ' + index + ' of ' + path
+							+ ' is not part of ' + that);
+				if (_default && value instanceof Curve)
+					index++;
+			} else {
+				index = typeof value === 'number' ? value : _default;
+			}
+			return Math.min(index < 0 && closed
+					? index % length
+					: index < 0 ? index + length : index, length - 1);
+		}
+
+		var loop = closed && opts.from === undefined && opts.to === undefined,
+			from = getIndex(opts.from, 0),
+			to = getIndex(opts.to, length - 1);
+
+		if (from > to) {
+			if (closed) {
+				from -= length;
+			} else {
+				var tmp = from;
+				from = to;
+				to = tmp;
+			}
+		}
+		if (/^(?:asymmetric|continuous)$/.test(type)) {
+			var asymmetric = type === 'asymmetric',
+				min = Math.min,
+				amount = to - from + 1,
+				n = amount - 1,
+				padding = loop ? min(amount, 4) : 1,
+				paddingLeft = padding,
+				paddingRight = padding,
+				knots = [];
+			if (!closed) {
+				paddingLeft = min(1, from);
+				paddingRight = min(1, length - to - 1);
+			}
+			n += paddingLeft + paddingRight;
+			if (n <= 1)
+				return;
+			for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
+				knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
+			}
+
+			var x = knots[0]._x + 2 * knots[1]._x,
+				y = knots[0]._y + 2 * knots[1]._y,
+				f = 2,
+				n_1 = n - 1,
+				rx = [x],
+				ry = [y],
+				rf = [f],
+				px = [],
+				py = [];
+			for (var i = 1; i < n; i++) {
+				var internal = i < n_1,
+					a = internal ? 1 : asymmetric ? 1 : 2,
+					b = internal ? 4 : asymmetric ? 2 : 7,
+					u = internal ? 4 : asymmetric ? 3 : 8,
+					v = internal ? 2 : asymmetric ? 0 : 1,
+					m = a / f;
+				f = rf[i] = b - m;
+				x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
+				y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
+			}
+
+			px[n_1] = rx[n_1] / rf[n_1];
+			py[n_1] = ry[n_1] / rf[n_1];
+			for (var i = n - 2; i >= 0; i--) {
+				px[i] = (rx[i] - px[i + 1]) / rf[i];
+				py[i] = (ry[i] - py[i + 1]) / rf[i];
+			}
+			px[n] = (3 * knots[n]._x - px[n_1]) / 2;
+			py[n] = (3 * knots[n]._y - py[n_1]) / 2;
+
+			for (var i = paddingLeft, max = n - paddingRight, j = from;
+					i <= max; i++, j++) {
+				var segment = segments[j < 0 ? j + length : j],
+					pt = segment._point,
+					hx = px[i] - pt._x,
+					hy = py[i] - pt._y;
+				if (loop || i < max)
+					segment.setHandleOut(hx, hy);
+				if (loop || i > paddingLeft)
+					segment.setHandleIn(-hx, -hy);
+			}
+		} else {
+			for (var i = from; i <= to; i++) {
+				segments[i < 0 ? i + length : i].smooth(opts,
+						!loop && i === from, !loop && i === to);
+			}
+		}
+	},
+
+	toShape: function(insert) {
+		if (!this._closed)
+			return null;
+
+		var segments = this._segments,
+			type,
+			size,
+			radius,
+			topCenter;
+
+		function isCollinear(i, j) {
+			var seg1 = segments[i],
+				seg2 = seg1.getNext(),
+				seg3 = segments[j],
+				seg4 = seg3.getNext();
+			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+					&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
+					&& seg2._point.subtract(seg1._point).isCollinear(
+						seg4._point.subtract(seg3._point));
+		}
+
+		function isOrthogonal(i) {
+			var seg2 = segments[i],
+				seg1 = seg2.getPrevious(),
+				seg3 = seg2.getNext();
+			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+					&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
+					&& seg2._point.subtract(seg1._point).isOrthogonal(
+						seg3._point.subtract(seg2._point));
+		}
+
+		function isArc(i) {
+			var seg1 = segments[i],
+				seg2 = seg1.getNext(),
+				handle1 = seg1._handleOut,
+				handle2 = seg2._handleIn,
+				kappa = 0.5522847498307936;
+			if (handle1.isOrthogonal(handle2)) {
+				var pt1 = seg1._point,
+					pt2 = seg2._point,
+					corner = new Line(pt1, handle1, true).intersect(
+							new Line(pt2, handle2, true), true);
+				return corner && Numerical.isZero(handle1.getLength() /
+						corner.subtract(pt1).getLength() - kappa)
+					&& Numerical.isZero(handle2.getLength() /
+						corner.subtract(pt2).getLength() - kappa);
+			}
+			return false;
+		}
+
+		function getDistance(i, j) {
+			return segments[i]._point.getDistance(segments[j]._point);
+		}
+
+		if (!this.hasHandles() && segments.length === 4
+				&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {
+			type = Shape.Rectangle;
+			size = new Size(getDistance(0, 3), getDistance(0, 1));
+			topCenter = segments[1]._point.add(segments[2]._point).divide(2);
+		} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
+				&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {
+			type = Shape.Rectangle;
+			size = new Size(getDistance(1, 6), getDistance(0, 3));
+			radius = size.subtract(new Size(getDistance(0, 7),
+					getDistance(1, 2))).divide(2);
+			topCenter = segments[3]._point.add(segments[4]._point).divide(2);
+		} else if (segments.length === 4
+				&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
+			if (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {
+				type = Shape.Circle;
+				radius = getDistance(0, 2) / 2;
+			} else {
+				type = Shape.Ellipse;
+				radius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);
+			}
+			topCenter = segments[1]._point;
+		}
+
+		if (type) {
+			var center = this.getPosition(true),
+				shape = new type({
+					center: center,
+					size: size,
+					radius: radius,
+					insert: false
+				});
+			shape.copyAttributes(this, true);
+			shape._matrix.prepend(this._matrix);
+			shape.rotate(topCenter.subtract(center).getAngle() + 90);
+			if (insert === undefined || insert)
+				shape.insertAbove(this);
+			return shape;
+		}
+		return null;
+	},
+
+	toPath: '#clone',
+
+	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
+		var that = this,
+			style = this.getStyle(),
+			segments = this._segments,
+			numSegments = segments.length,
+			closed = this._closed,
+			tolerancePadding = options._tolerancePadding,
+			strokePadding = tolerancePadding,
+			join, cap, miterLimit,
+			area, loc, res,
+			hitStroke = options.stroke && style.hasStroke(),
+			hitFill = options.fill && style.hasFill(),
+			hitCurves = options.curves,
+			strokeRadius = hitStroke
+					? style.getStrokeWidth() / 2
+					: hitFill && options.tolerance > 0 || hitCurves
+						? 0 : null;
+		if (strokeRadius !== null) {
+			if (strokeRadius > 0) {
+				join = style.getStrokeJoin();
+				cap = style.getStrokeCap();
+				miterLimit = strokeRadius * style.getMiterLimit();
+				strokePadding = strokePadding.add(
+					Path._getStrokePadding(strokeRadius, strokeMatrix));
+			} else {
+				join = cap = 'round';
+			}
+		}
+
+		function isCloseEnough(pt, padding) {
+			return point.subtract(pt).divide(padding).length <= 1;
+		}
+
+		function checkSegmentPoint(seg, pt, name) {
+			if (!options.selected || pt.isSelected()) {
+				var anchor = seg._point;
+				if (pt !== anchor)
+					pt = pt.add(anchor);
+				if (isCloseEnough(pt, strokePadding)) {
+					return new HitResult(name, that, {
+						segment: seg,
+						point: pt
+					});
+				}
+			}
+		}
+
+		function checkSegmentPoints(seg, ends) {
+			return (ends || options.segments)
+				&& checkSegmentPoint(seg, seg._point, 'segment')
+				|| (!ends && options.handles) && (
+					checkSegmentPoint(seg, seg._handleIn, 'handle-in') ||
+					checkSegmentPoint(seg, seg._handleOut, 'handle-out'));
+		}
+
+		function addToArea(point) {
+			area.add(point);
+		}
+
+		function checkSegmentStroke(segment) {
+			if (join !== 'round' || cap !== 'round') {
+				area = new Path({ internal: true, closed: true });
+				if (closed || segment._index > 0
+						&& segment._index < numSegments - 1) {
+					if (join !== 'round' && (segment._handleIn.isZero()
+							|| segment._handleOut.isZero()))
+						Path._addBevelJoin(segment, join, strokeRadius,
+							   miterLimit, null, strokeMatrix, addToArea, true);
+				} else if (cap !== 'round') {
+					Path._addSquareCap(segment, cap, strokeRadius, null,
+							strokeMatrix, addToArea, true);
+				}
+				if (!area.isEmpty()) {
+					var loc;
+					return area.contains(point)
+						|| (loc = area.getNearestLocation(point))
+							&& isCloseEnough(loc.getPoint(), tolerancePadding);
+				}
+			}
+			return isCloseEnough(segment._point, strokePadding);
+		}
+
+		if (options.ends && !options.segments && !closed) {
+			if (res = checkSegmentPoints(segments[0], true)
+					|| checkSegmentPoints(segments[numSegments - 1], true))
+				return res;
+		} else if (options.segments || options.handles) {
+			for (var i = 0; i < numSegments; i++)
+				if (res = checkSegmentPoints(segments[i]))
+					return res;
+		}
+		if (strokeRadius !== null) {
+			loc = this.getNearestLocation(point);
+			if (loc) {
+				var time = loc.getTime();
+				if (time === 0 || time === 1 && numSegments > 1) {
+					if (!checkSegmentStroke(loc.getSegment()))
+						loc = null;
+				} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
+					loc = null;
+				}
+			}
+			if (!loc && join === 'miter' && numSegments > 1) {
+				for (var i = 0; i < numSegments; i++) {
+					var segment = segments[i];
+					if (point.getDistance(segment._point) <= miterLimit
+							&& checkSegmentStroke(segment)) {
+						loc = segment.getLocation();
+						break;
+					}
+				}
+			}
+		}
+		return !loc && hitFill && this._contains(point)
+				|| loc && !hitStroke && !hitCurves
+					? new HitResult('fill', this)
+					: loc
+						? new HitResult(hitStroke ? 'stroke' : 'curve', this, {
+							location: loc,
+							point: loc.getPoint()
+						})
+						: null;
+	}
+
+}, Base.each(Curve._evaluateMethods,
+	function(name) {
+		this[name + 'At'] = function(offset) {
+			var loc = this.getLocationAt(offset);
+			return loc && loc[name]();
+		};
+	},
+{
+	beans: false,
+
+	getLocationOf: function() {
+		var point = Point.read(arguments),
+			curves = this.getCurves();
+		for (var i = 0, l = curves.length; i < l; i++) {
+			var loc = curves[i].getLocationOf(point);
+			if (loc)
+				return loc;
+		}
+		return null;
+	},
+
+	getOffsetOf: function() {
+		var loc = this.getLocationOf.apply(this, arguments);
+		return loc ? loc.getOffset() : null;
+	},
+
+	getLocationAt: function(offset) {
+		var curves = this.getCurves(),
+			length = 0;
+		for (var i = 0, l = curves.length; i < l; i++) {
+			var start = length,
+				curve = curves[i];
+			length += curve.getLength();
+			if (length > offset) {
+				return curve.getLocationAt(offset - start);
+			}
+		}
+		if (curves.length > 0 && offset <= this.getLength())
+			return new CurveLocation(curves[curves.length - 1], 1);
+		return null;
+	}
+
+}),
+new function() {
+
+	function drawHandles(ctx, segments, matrix, size) {
+		var half = size / 2,
+			coords = new Array(6),
+			pX, pY;
+
+		function drawHandle(index) {
+			var hX = coords[index],
+				hY = coords[index + 1];
+			if (pX != hX || pY != hY) {
+				ctx.beginPath();
+				ctx.moveTo(pX, pY);
+				ctx.lineTo(hX, hY);
+				ctx.stroke();
+				ctx.beginPath();
+				ctx.arc(hX, hY, half, 0, Math.PI * 2, true);
+				ctx.fill();
+			}
+		}
+
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var segment = segments[i],
+				selection = segment._selection;
+			segment._transformCoordinates(matrix, coords);
+			pX = coords[0];
+			pY = coords[1];
+			if (selection & 2)
+				drawHandle(2);
+			if (selection & 4)
+				drawHandle(4);
+			ctx.fillRect(pX - half, pY - half, size, size);
+			if (!(selection & 1)) {
+				var fillStyle = ctx.fillStyle;
+				ctx.fillStyle = '#ffffff';
+				ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);
+				ctx.fillStyle = fillStyle;
+			}
+		}
+	}
+
+	function drawSegments(ctx, path, matrix) {
+		var segments = path._segments,
+			length = segments.length,
+			coords = new Array(6),
+			first = true,
+			curX, curY,
+			prevX, prevY,
+			inX, inY,
+			outX, outY;
+
+		function drawSegment(segment) {
+			if (matrix) {
+				segment._transformCoordinates(matrix, coords);
+				curX = coords[0];
+				curY = coords[1];
+			} else {
+				var point = segment._point;
+				curX = point._x;
+				curY = point._y;
+			}
+			if (first) {
+				ctx.moveTo(curX, curY);
+				first = false;
+			} else {
+				if (matrix) {
+					inX = coords[2];
+					inY = coords[3];
+				} else {
+					var handle = segment._handleIn;
+					inX = curX + handle._x;
+					inY = curY + handle._y;
+				}
+				if (inX === curX && inY === curY
+						&& outX === prevX && outY === prevY) {
+					ctx.lineTo(curX, curY);
+				} else {
+					ctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);
+				}
+			}
+			prevX = curX;
+			prevY = curY;
+			if (matrix) {
+				outX = coords[4];
+				outY = coords[5];
+			} else {
+				var handle = segment._handleOut;
+				outX = prevX + handle._x;
+				outY = prevY + handle._y;
+			}
+		}
+
+		for (var i = 0; i < length; i++)
+			drawSegment(segments[i]);
+		if (path._closed && length > 0)
+			drawSegment(segments[0]);
+	}
+
+	return {
+		_draw: function(ctx, param, viewMatrix, strokeMatrix) {
+			var dontStart = param.dontStart,
+				dontPaint = param.dontFinish || param.clip,
+				style = this.getStyle(),
+				hasFill = style.hasFill(),
+				hasStroke = style.hasStroke(),
+				dashArray = style.getDashArray(),
+				dashLength = !paper.support.nativeDash && hasStroke
+						&& dashArray && dashArray.length;
+
+			if (!dontStart)
+				ctx.beginPath();
+
+			if (hasFill || hasStroke && !dashLength || dontPaint) {
+				drawSegments(ctx, this, strokeMatrix);
+				if (this._closed)
+					ctx.closePath();
+			}
+
+			function getOffset(i) {
+				return dashArray[((i % dashLength) + dashLength) % dashLength];
+			}
+
+			if (!dontPaint && (hasFill || hasStroke)) {
+				this._setStyles(ctx, param, viewMatrix);
+				if (hasFill) {
+					ctx.fill(style.getFillRule());
+					ctx.shadowColor = 'rgba(0,0,0,0)';
+				}
+				if (hasStroke) {
+					if (dashLength) {
+						if (!dontStart)
+							ctx.beginPath();
+						var iterator = new PathIterator(this, 0.25, 32, false,
+								strokeMatrix),
+							length = iterator.length,
+							from = -style.getDashOffset(), to,
+							i = 0;
+						from = from % length;
+						while (from > 0) {
+							from -= getOffset(i--) + getOffset(i--);
+						}
+						while (from < length) {
+							to = from + getOffset(i++);
+							if (from > 0 || to > 0)
+								iterator.drawPart(ctx,
+										Math.max(from, 0), Math.max(to, 0));
+							from = to + getOffset(i++);
+						}
+					}
+					ctx.stroke();
+				}
+			}
+		},
+
+		_drawSelected: function(ctx, matrix) {
+			ctx.beginPath();
+			drawSegments(ctx, this, matrix);
+			ctx.stroke();
+			drawHandles(ctx, this._segments, matrix, paper.settings.handleSize);
+		}
+	};
+},
+new function() {
+	function getCurrentSegment(that) {
+		var segments = that._segments;
+		if (segments.length === 0)
+			throw new Error('Use a moveTo() command first');
+		return segments[segments.length - 1];
+	}
+
+	return {
+		moveTo: function() {
+			var segments = this._segments;
+			if (segments.length === 1)
+				this.removeSegment(0);
+			if (!segments.length)
+				this._add([ new Segment(Point.read(arguments)) ]);
+		},
+
+		moveBy: function() {
+			throw new Error('moveBy() is unsupported on Path items.');
+		},
+
+		lineTo: function() {
+			this._add([ new Segment(Point.read(arguments)) ]);
+		},
+
+		cubicCurveTo: function() {
+			var handle1 = Point.read(arguments),
+				handle2 = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this);
+			current.setHandleOut(handle1.subtract(current._point));
+			this._add([ new Segment(to, handle2.subtract(to)) ]);
+		},
+
+		quadraticCurveTo: function() {
+			var handle = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.cubicCurveTo(
+				handle.add(current.subtract(handle).multiply(1 / 3)),
+				handle.add(to.subtract(handle).multiply(1 / 3)),
+				to
+			);
+		},
+
+		curveTo: function() {
+			var through = Point.read(arguments),
+				to = Point.read(arguments),
+				t = Base.pick(Base.read(arguments), 0.5),
+				t1 = 1 - t,
+				current = getCurrentSegment(this)._point,
+				handle = through.subtract(current.multiply(t1 * t1))
+					.subtract(to.multiply(t * t)).divide(2 * t * t1);
+			if (handle.isNaN())
+				throw new Error(
+					'Cannot put a curve through points with parameter = ' + t);
+			this.quadraticCurveTo(handle, to);
+		},
+
+		arcTo: function() {
+			var current = getCurrentSegment(this),
+				from = current._point,
+				to = Point.read(arguments),
+				through,
+				peek = Base.peek(arguments),
+				clockwise = Base.pick(peek, true),
+				center, extent, vector, matrix;
+			if (typeof clockwise === 'boolean') {
+				var middle = from.add(to).divide(2),
+				through = middle.add(middle.subtract(from).rotate(
+						clockwise ? -90 : 90));
+			} else if (Base.remain(arguments) <= 2) {
+				through = to;
+				to = Point.read(arguments);
+			} else {
+				var radius = Size.read(arguments),
+					isZero = Numerical.isZero;
+				if (isZero(radius.width) || isZero(radius.height))
+					return this.lineTo(to);
+				var rotation = Base.read(arguments),
+					clockwise = !!Base.read(arguments),
+					large = !!Base.read(arguments),
+					middle = from.add(to).divide(2),
+					pt = from.subtract(middle).rotate(-rotation),
+					x = pt.x,
+					y = pt.y,
+					abs = Math.abs,
+					rx = abs(radius.width),
+					ry = abs(radius.height),
+					rxSq = rx * rx,
+					rySq = ry * ry,
+					xSq = x * x,
+					ySq = y * y;
+				var factor = Math.sqrt(xSq / rxSq + ySq / rySq);
+				if (factor > 1) {
+					rx *= factor;
+					ry *= factor;
+					rxSq = rx * rx;
+					rySq = ry * ry;
+				}
+				factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
+						(rxSq * ySq + rySq * xSq);
+				if (abs(factor) < 1e-12)
+					factor = 0;
+				if (factor < 0)
+					throw new Error(
+							'Cannot create an arc with the given arguments');
+				center = new Point(rx * y / ry, -ry * x / rx)
+						.multiply((large === clockwise ? -1 : 1)
+							* Math.sqrt(factor))
+						.rotate(rotation).add(middle);
+				matrix = new Matrix().translate(center).rotate(rotation)
+						.scale(rx, ry);
+				vector = matrix._inverseTransform(from);
+				extent = vector.getDirectedAngle(matrix._inverseTransform(to));
+				if (!clockwise && extent > 0)
+					extent -= 360;
+				else if (clockwise && extent < 0)
+					extent += 360;
+			}
+			if (through) {
+				var l1 = new Line(from.add(through).divide(2),
+							through.subtract(from).rotate(90), true),
+					l2 = new Line(through.add(to).divide(2),
+							to.subtract(through).rotate(90), true),
+					line = new Line(from, to),
+					throughSide = line.getSide(through);
+				center = l1.intersect(l2, true);
+				if (!center) {
+					if (!throughSide)
+						return this.lineTo(to);
+					throw new Error(
+							'Cannot create an arc with the given arguments');
+				}
+				vector = from.subtract(center);
+				extent = vector.getDirectedAngle(to.subtract(center));
+				var centerSide = line.getSide(center);
+				if (centerSide === 0) {
+					extent = throughSide * Math.abs(extent);
+				} else if (throughSide === centerSide) {
+					extent += extent < 0 ? 360 : -360;
+				}
+			}
+			var ext = Math.abs(extent),
+				count = ext >= 360 ? 4 : Math.ceil(ext / 90),
+				inc = extent / count,
+				half = inc * Math.PI / 360,
+				z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),
+				segments = [];
+			for (var i = 0; i <= count; i++) {
+				var pt = to,
+					out = null;
+				if (i < count) {
+					out = vector.rotate(90).multiply(z);
+					if (matrix) {
+						pt = matrix._transformPoint(vector);
+						out = matrix._transformPoint(vector.add(out))
+								.subtract(pt);
+					} else {
+						pt = center.add(vector);
+					}
+				}
+				if (i === 0) {
+					current.setHandleOut(out);
+				} else {
+					var _in = vector.rotate(-90).multiply(z);
+					if (matrix) {
+						_in = matrix._transformPoint(vector.add(_in))
+								.subtract(pt);
+					}
+					segments.push(new Segment(pt, _in, out));
+				}
+				vector = vector.rotate(inc);
+			}
+			this._add(segments);
+		},
+
+		lineBy: function() {
+			var to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.lineTo(current.add(to));
+		},
+
+		curveBy: function() {
+			var through = Point.read(arguments),
+				to = Point.read(arguments),
+				parameter = Base.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.curveTo(current.add(through), current.add(to), parameter);
+		},
+
+		cubicCurveBy: function() {
+			var handle1 = Point.read(arguments),
+				handle2 = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.cubicCurveTo(current.add(handle1), current.add(handle2),
+					current.add(to));
+		},
+
+		quadraticCurveBy: function() {
+			var handle = Point.read(arguments),
+				to = Point.read(arguments),
+				current = getCurrentSegment(this)._point;
+			this.quadraticCurveTo(current.add(handle), current.add(to));
+		},
+
+		arcBy: function() {
+			var current = getCurrentSegment(this)._point,
+				point = current.add(Point.read(arguments)),
+				clockwise = Base.pick(Base.peek(arguments), true);
+			if (typeof clockwise === 'boolean') {
+				this.arcTo(point, clockwise);
+			} else {
+				this.arcTo(point, current.add(Point.read(arguments)));
+			}
+		},
+
+		closePath: function(tolerance) {
+			this.setClosed(true);
+			this.join(this, tolerance);
+		}
+	};
+}, {
+
+	_getBounds: function(matrix, options) {
+		var method = options.handle
+				? 'getHandleBounds'
+				: options.stroke
+				? 'getStrokeBounds'
+				: 'getBounds';
+		return Path[method](this._segments, this._closed, this, matrix, options);
+	},
+
+statics: {
+	getBounds: function(segments, closed, path, matrix, options, strokePadding) {
+		var first = segments[0];
+		if (!first)
+			return new Rectangle();
+		var coords = new Array(6),
+			prevCoords = first._transformCoordinates(matrix, new Array(6)),
+			min = prevCoords.slice(0, 2),
+			max = min.slice(),
+			roots = new Array(2);
+
+		function processSegment(segment) {
+			segment._transformCoordinates(matrix, coords);
+			for (var i = 0; i < 2; i++) {
+				Curve._addBounds(
+					prevCoords[i],
+					prevCoords[i + 4],
+					coords[i + 2],
+					coords[i],
+					i, strokePadding ? strokePadding[i] : 0, min, max, roots);
+			}
+			var tmp = prevCoords;
+			prevCoords = coords;
+			coords = tmp;
+		}
+
+		for (var i = 1, l = segments.length; i < l; i++)
+			processSegment(segments[i]);
+		if (closed)
+			processSegment(first);
+		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
+	},
+
+	getStrokeBounds: function(segments, closed, path, matrix, options) {
+		var style = path.getStyle(),
+			stroke = style.hasStroke(),
+			strokeWidth = style.getStrokeWidth(),
+			strokeMatrix = stroke && path._getStrokeMatrix(matrix, options),
+			strokePadding = stroke && Path._getStrokePadding(strokeWidth,
+				strokeMatrix),
+			bounds = Path.getBounds(segments, closed, path, matrix, options,
+				strokePadding);
+		if (!stroke)
+			return bounds;
+		var strokeRadius = strokeWidth / 2,
+			join = style.getStrokeJoin(),
+			cap = style.getStrokeCap(),
+			miterLimit = strokeRadius * style.getMiterLimit(),
+			joinBounds = new Rectangle(new Size(strokePadding));
+
+		function addPoint(point) {
+			bounds = bounds.include(point);
+		}
+
+		function addRound(segment) {
+			bounds = bounds.unite(
+					joinBounds.setCenter(segment._point.transform(matrix)));
+		}
+
+		function addJoin(segment, join) {
+			var handleIn = segment._handleIn,
+				handleOut = segment._handleOut;
+			if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
+					&& handleIn.isCollinear(handleOut)) {
+				addRound(segment);
+			} else {
+				Path._addBevelJoin(segment, join, strokeRadius, miterLimit,
+						matrix, strokeMatrix, addPoint);
+			}
+		}
+
+		function addCap(segment, cap) {
+			if (cap === 'round') {
+				addRound(segment);
+			} else {
+				Path._addSquareCap(segment, cap, strokeRadius, matrix,
+						strokeMatrix, addPoint);
+			}
+		}
+
+		var length = segments.length - (closed ? 0 : 1);
+		for (var i = 1; i < length; i++)
+			addJoin(segments[i], join);
+		if (closed) {
+			addJoin(segments[0], join);
+		} else if (length > 0) {
+			addCap(segments[0], cap);
+			addCap(segments[segments.length - 1], cap);
+		}
+		return bounds;
+	},
+
+	_getStrokePadding: function(radius, matrix) {
+		if (!matrix)
+			return [radius, radius];
+		var hor = new Point(radius, 0).transform(matrix),
+			ver = new Point(0, radius).transform(matrix),
+			phi = hor.getAngleInRadians(),
+			a = hor.getLength(),
+			b = ver.getLength();
+		var sin = Math.sin(phi),
+			cos = Math.cos(phi),
+			tan = Math.tan(phi),
+			tx = Math.atan2(b * tan, a),
+			ty = Math.atan2(b, tan * a);
+		return [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),
+				Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];
+	},
+
+	_addBevelJoin: function(segment, join, radius, miterLimit, matrix,
+			strokeMatrix, addPoint, isArea) {
+		var curve2 = segment.getCurve(),
+			curve1 = curve2.getPrevious(),
+			point = curve2.getPointAtTime(0),
+			normal1 = curve1.getNormalAtTime(1),
+			normal2 = curve2.getNormalAtTime(0),
+			step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
+		normal1.setLength(step);
+		normal2.setLength(step);
+		if (matrix)
+			matrix._transformPoint(point, point);
+		if (strokeMatrix) {
+			strokeMatrix._transformPoint(normal1, normal1);
+			strokeMatrix._transformPoint(normal2, normal2);
+		}
+		if (isArea) {
+			addPoint(point);
+			addPoint(point.add(normal1));
+		}
+		if (join === 'miter') {
+			var corner = new Line(point.add(normal1),
+					new Point(-normal1.y, normal1.x), true
+				).intersect(new Line(point.add(normal2),
+					new Point(-normal2.y, normal2.x), true
+				), true);
+			if (corner && point.getDistance(corner) <= miterLimit) {
+				addPoint(corner);
+				if (!isArea)
+					return;
+			}
+		}
+		if (!isArea)
+			addPoint(point.add(normal1));
+		addPoint(point.add(normal2));
+	},
+
+	_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,
+			addPoint, isArea) {
+		var point = segment._point,
+			loc = segment.getLocation(),
+			normal = loc.getNormal().multiply(radius);
+		if (matrix)
+			matrix._transformPoint(point, point);
+		if (strokeMatrix)
+			strokeMatrix._transformPoint(normal, normal);
+		if (isArea) {
+			addPoint(point.subtract(normal));
+			addPoint(point.add(normal));
+		}
+		if (cap === 'square') {
+			point = point.add(normal.rotate(
+					loc.getTime() === 0 ? -90 : 90));
+		}
+		addPoint(point.add(normal));
+		addPoint(point.subtract(normal));
+	},
+
+	getHandleBounds: function(segments, closed, path, matrix, options) {
+		var style = path.getStyle(),
+			stroke = options.stroke && style.hasStroke(),
+			strokePadding,
+			joinPadding;
+		if (stroke) {
+			var strokeMatrix = path._getStrokeMatrix(matrix, options),
+				strokeRadius = style.getStrokeWidth() / 2,
+				joinRadius = strokeRadius;
+			if (style.getStrokeJoin() === 'miter')
+				joinRadius = strokeRadius * style.getMiterLimit();
+			if (style.getStrokeCap() === 'square')
+				joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
+			strokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);
+			joinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);
+		}
+		var coords = new Array(6),
+			x1 = Infinity,
+			x2 = -x1,
+			y1 = x1,
+			y2 = x2;
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var segment = segments[i];
+			segment._transformCoordinates(matrix, coords);
+			for (var j = 0; j < 6; j += 2) {
+				var padding = j === 0 ? joinPadding : strokePadding,
+					paddingX = padding ? padding[0] : 0,
+					paddingY = padding ? padding[1] : 0,
+					x = coords[j],
+					y = coords[j + 1],
+					xn = x - paddingX,
+					xx = x + paddingX,
+					yn = y - paddingY,
+					yx = y + paddingY;
+				if (xn < x1) x1 = xn;
+				if (xx > x2) x2 = xx;
+				if (yn < y1) y1 = yn;
+				if (yx > y2) y2 = yx;
+			}
+		}
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+	}
+}});
+
+Path.inject({ statics: new function() {
+
+	var kappa = 0.5522847498307936,
+		ellipseSegments = [
+			new Segment([-1, 0], [0, kappa ], [0, -kappa]),
+			new Segment([0, -1], [-kappa, 0], [kappa, 0 ]),
+			new Segment([1, 0], [0, -kappa], [0, kappa ]),
+			new Segment([0, 1], [kappa, 0 ], [-kappa, 0])
+		];
+
+	function createPath(segments, closed, args) {
+		var props = Base.getNamed(args),
+			path = new Path(props && props.insert === false && Item.NO_INSERT);
+		path._add(segments);
+		path._closed = closed;
+		return path.set(props);
+	}
+
+	function createEllipse(center, radius, args) {
+		var segments = new Array(4);
+		for (var i = 0; i < 4; i++) {
+			var segment = ellipseSegments[i];
+			segments[i] = new Segment(
+				segment._point.multiply(radius).add(center),
+				segment._handleIn.multiply(radius),
+				segment._handleOut.multiply(radius)
+			);
+		}
+		return createPath(segments, true, args);
+	}
+
+	return {
+		Line: function() {
+			return createPath([
+				new Segment(Point.readNamed(arguments, 'from')),
+				new Segment(Point.readNamed(arguments, 'to'))
+			], false, arguments);
+		},
+
+		Circle: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				radius = Base.readNamed(arguments, 'radius');
+			return createEllipse(center, new Size(radius), arguments);
+		},
+
+		Rectangle: function() {
+			var rect = Rectangle.readNamed(arguments, 'rectangle'),
+				radius = Size.readNamed(arguments, 'radius', 0,
+						{ readNull: true }),
+				bl = rect.getBottomLeft(true),
+				tl = rect.getTopLeft(true),
+				tr = rect.getTopRight(true),
+				br = rect.getBottomRight(true),
+				segments;
+			if (!radius || radius.isZero()) {
+				segments = [
+					new Segment(bl),
+					new Segment(tl),
+					new Segment(tr),
+					new Segment(br)
+				];
+			} else {
+				radius = Size.min(radius, rect.getSize(true).divide(2));
+				var rx = radius.width,
+					ry = radius.height,
+					hx = rx * kappa,
+					hy = ry * kappa;
+				segments = [
+					new Segment(bl.add(rx, 0), null, [-hx, 0]),
+					new Segment(bl.subtract(0, ry), [0, hy]),
+					new Segment(tl.add(0, ry), null, [0, -hy]),
+					new Segment(tl.add(rx, 0), [-hx, 0], null),
+					new Segment(tr.subtract(rx, 0), null, [hx, 0]),
+					new Segment(tr.add(0, ry), [0, -hy], null),
+					new Segment(br.subtract(0, ry), null, [0, hy]),
+					new Segment(br.subtract(rx, 0), [hx, 0])
+				];
+			}
+			return createPath(segments, true, arguments);
+		},
+
+		RoundRectangle: '#Rectangle',
+
+		Ellipse: function() {
+			var ellipse = Shape._readEllipse(arguments);
+			return createEllipse(ellipse.center, ellipse.radius, arguments);
+		},
+
+		Oval: '#Ellipse',
+
+		Arc: function() {
+			var from = Point.readNamed(arguments, 'from'),
+				through = Point.readNamed(arguments, 'through'),
+				to = Point.readNamed(arguments, 'to'),
+				props = Base.getNamed(arguments),
+				path = new Path(props && props.insert === false
+						&& Item.NO_INSERT);
+			path.moveTo(from);
+			path.arcTo(through, to);
+			return path.set(props);
+		},
+
+		RegularPolygon: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				sides = Base.readNamed(arguments, 'sides'),
+				radius = Base.readNamed(arguments, 'radius'),
+				step = 360 / sides,
+				three = sides % 3 === 0,
+				vector = new Point(0, three ? -radius : radius),
+				offset = three ? -1 : 0.5,
+				segments = new Array(sides);
+			for (var i = 0; i < sides; i++)
+				segments[i] = new Segment(center.add(
+					vector.rotate((i + offset) * step)));
+			return createPath(segments, true, arguments);
+		},
+
+		Star: function() {
+			var center = Point.readNamed(arguments, 'center'),
+				points = Base.readNamed(arguments, 'points') * 2,
+				radius1 = Base.readNamed(arguments, 'radius1'),
+				radius2 = Base.readNamed(arguments, 'radius2'),
+				step = 360 / points,
+				vector = new Point(0, -1),
+				segments = new Array(points);
+			for (var i = 0; i < points; i++)
+				segments[i] = new Segment(center.add(vector.rotate(step * i)
+						.multiply(i % 2 ? radius2 : radius1)));
+			return createPath(segments, true, arguments);
+		}
+	};
+}});
+
+var CompoundPath = PathItem.extend({
+	_class: 'CompoundPath',
+	_serializeFields: {
+		children: []
+	},
+
+	initialize: function CompoundPath(arg) {
+		this._children = [];
+		this._namedChildren = {};
+		if (!this._initialize(arg)) {
+			if (typeof arg === 'string') {
+				this.setPathData(arg);
+			} else {
+				this.addChildren(Array.isArray(arg) ? arg : arguments);
+			}
+		}
+	},
+
+	insertChildren: function insertChildren(index, items, _preserve) {
+		for (var i = items.length - 1; i >= 0; i--) {
+			var item = items[i];
+			if (item instanceof CompoundPath) {
+				items = items.slice();
+				items.splice.apply(items, [i, 1].concat(item.removeChildren()));
+				item.remove();
+			}
+		}
+		items = insertChildren.base.call(this, index, items, _preserve, Path);
+		for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
+			var item = items[i];
+			if (item._clockwise === undefined)
+				item.setClockwise(item._index === 0);
+		}
+		return items;
+	},
+
+	reduce: function reduce(options) {
+		var children = this._children;
+		for (var i = children.length - 1; i >= 0; i--) {
+			var path = children[i].reduce(options);
+			if (path.isEmpty())
+				path.remove();
+		}
+		if (children.length === 0) {
+			var path = new Path(Item.NO_INSERT);
+			path.copyAttributes(this);
+			path.insertAbove(this);
+			this.remove();
+			return path;
+		}
+		return reduce.base.call(this);
+	},
+
+	isClockwise: function() {
+		var child = this.getFirstChild();
+		return child && child.isClockwise();
+	},
+
+	setClockwise: function(clockwise) {
+		if (this.isClockwise() ^ !!clockwise)
+			this.reverse();
+	},
+
+	getFirstSegment: function() {
+		var first = this.getFirstChild();
+		return first && first.getFirstSegment();
+	},
+
+	getLastSegment: function() {
+		var last = this.getLastChild();
+		return last && last.getLastSegment();
+	},
+
+	getCurves: function() {
+		var children = this._children,
+			curves = [];
+		for (var i = 0, l = children.length; i < l; i++)
+			curves.push.apply(curves, children[i].getCurves());
+		return curves;
+	},
+
+	getFirstCurve: function() {
+		var first = this.getFirstChild();
+		return first && first.getFirstCurve();
+	},
+
+	getLastCurve: function() {
+		var last = this.getLastChild();
+		return last && last.getFirstCurve();
+	},
+
+	getArea: function() {
+		var children = this._children,
+			area = 0;
+		for (var i = 0, l = children.length; i < l; i++)
+			area += children[i].getArea();
+		return area;
+	}
+}, {
+	beans: true,
+
+	getPathData: function(_matrix, _precision) {
+		var children = this._children,
+			paths = [];
+		for (var i = 0, l = children.length; i < l; i++) {
+			var child = children[i],
+				mx = child._matrix;
+			paths.push(child.getPathData(_matrix && !mx.isIdentity()
+					? _matrix.appended(mx) : _matrix, _precision));
+		}
+		return paths.join(' ');
+	}
+}, {
+	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
+		return _hitTestChildren.base.call(this, point,
+				options.class === Path || options.type === 'path' ? options
+					: Base.set({}, options, { fill: false }),
+				viewMatrix);
+	},
+
+	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
+		var children = this._children;
+		if (children.length === 0)
+			return;
+
+		param = param.extend({ dontStart: true, dontFinish: true });
+		ctx.beginPath();
+		for (var i = 0, l = children.length; i < l; i++)
+			children[i].draw(ctx, param, strokeMatrix);
+
+		if (!param.clip) {
+			this._setStyles(ctx, param, viewMatrix);
+			var style = this._style;
+			if (style.hasFill()) {
+				ctx.fill(style.getFillRule());
+				ctx.shadowColor = 'rgba(0,0,0,0)';
+			}
+			if (style.hasStroke())
+				ctx.stroke();
+		}
+	},
+
+	_drawSelected: function(ctx, matrix, selectionItems) {
+		var children = this._children;
+		for (var i = 0, l = children.length; i < l; i++) {
+			var child = children[i],
+				mx = child._matrix;
+			if (!selectionItems[child._id]) {
+				child._drawSelected(ctx, mx.isIdentity() ? matrix
+						: matrix.appended(mx));
+			}
+		}
+	}
+},
+new function() {
+	function getCurrentPath(that, check) {
+		var children = that._children;
+		if (check && children.length === 0)
+			throw new Error('Use a moveTo() command first');
+		return children[children.length - 1];
+	}
+
+	return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
+			'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
+			'arcBy'],
+		function(key) {
+			this[key] = function() {
+				var path = getCurrentPath(this, true);
+				path[key].apply(path, arguments);
+			};
+		}, {
+			moveTo: function() {
+				var current = getCurrentPath(this),
+					path = current && current.isEmpty() ? current
+							: new Path(Item.NO_INSERT);
+				if (path !== current)
+					this.addChild(path);
+				path.moveTo.apply(path, arguments);
+			},
+
+			moveBy: function() {
+				var current = getCurrentPath(this, true),
+					last = current && current.getLastSegment(),
+					point = Point.read(arguments);
+				this.moveTo(last ? point.add(last._point) : point);
+			},
+
+			closePath: function(tolerance) {
+				getCurrentPath(this, true).closePath(tolerance);
+			}
+		}
+	);
+}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
+	this[key] = function(param) {
+		var children = this._children,
+			res;
+		for (var i = 0, l = children.length; i < l; i++) {
+			res = children[i][key](param) || res;
+		}
+		return res;
+	};
+}, {}));
+
+PathItem.inject(new function() {
+	var operators = {
+		unite:     { 1: true },
+		intersect: { 2: true },
+		subtract:  { 1: true },
+		exclude:   { 1: true }
+	};
+
+	function preparePath(path, resolve) {
+		var res = path.clone(false).reduce({ simplify: true })
+				.transform(null, true, true);
+		return resolve ? res.resolveCrossings() : res;
+	}
+
+	function createResult(ctor, paths, reduce, path1, path2) {
+		var result = new ctor(Item.NO_INSERT);
+		result.addChildren(paths, true);
+		if (reduce)
+			result = result.reduce({ simplify: true });
+		result.insertAbove(path2 && path1.isSibling(path2)
+				&& path1.getIndex() < path2.getIndex() ? path2 : path1);
+		result.copyAttributes(path1, true);
+		return result;
+	}
+
+	function computeBoolean(path1, path2, operation) {
+		var operator = operators[operation];
+		operator[operation] = true;
+		if (!path1._children && !path1._closed)
+			return computeOpenBoolean(path1, path2, operator);
+		var _path1 = preparePath(path1, true),
+			_path2 = path2 && path1 !== path2 && preparePath(path2, true);
+		if (_path2 && (operator.subtract || operator.exclude)
+				^ (_path2.isClockwise() ^ _path1.isClockwise()))
+			_path2.reverse();
+		var crossings = divideLocations(
+				CurveLocation.expand(_path1.getCrossings(_path2))),
+			segments = [],
+			monoCurves = [];
+
+		function collect(paths) {
+			for (var i = 0, l = paths.length; i < l; i++) {
+				var path = paths[i];
+				segments.push.apply(segments, path._segments);
+				monoCurves.push.apply(monoCurves, path._getMonoCurves());
+				path._overlapsOnly = path._validOverlapsOnly = true;
+			}
+		}
+
+		collect(_path1._children || [_path1]);
+		if (_path2)
+			collect(_path2._children || [_path2]);
+		for (var i = 0, l = crossings.length; i < l; i++) {
+			propagateWinding(crossings[i]._segment, _path1, _path2, monoCurves,
+					operator);
+		}
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var segment = segments[i],
+				inter = segment._intersection;
+			if (segment._winding == null) {
+				propagateWinding(segment, _path1, _path2, monoCurves, operator);
+			}
+			if (!(inter && inter._overlap)) {
+				var path = segment._path;
+				path._overlapsOnly = false;
+				if (operator[segment._winding])
+					path._validOverlapsOnly = false;
+			}
+		}
+		return createResult(CompoundPath, tracePaths(segments, operator), true,
+					path1, path2);
+	}
+
+	function computeOpenBoolean(path1, path2, operator) {
+		if (!path2 || !path2._children && !path2._closed
+				|| !operator.subtract && !operator.intersect)
+			return null;
+		var _path1 = preparePath(path1, false),
+			_path2 = preparePath(path2, false),
+			crossings = _path1.getCrossings(_path2),
+			sub = operator.subtract,
+			paths = [];
+
+		function addPath(path) {
+			if (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {
+				paths.unshift(path);
+				return true;
+			}
+		}
+
+		for (var i = crossings.length - 1; i >= 0; i--) {
+			var path = crossings[i].split();
+			if (path) {
+				if (addPath(path))
+					path.getFirstSegment().setHandleIn(0, 0);
+				_path1.getLastSegment().setHandleOut(0, 0);
+			}
+		}
+		addPath(_path1);
+		return createResult(Group, paths, false, path1, path2);
+	}
+
+	function linkIntersections(from, to) {
+		var prev = from;
+		while (prev) {
+			if (prev === to)
+				return;
+			prev = prev._previous;
+		}
+		while (from._next && from._next !== to)
+			from = from._next;
+		if (!from._next) {
+			while (to._previous)
+				to = to._previous;
+			from._next = to;
+			to._previous = from;
+		}
+	}
+
+	function divideLocations(locations, include) {
+		var results = include && [],
+			tMin = 4e-7,
+			tMax = 1 - tMin,
+			noHandles = false,
+			clearCurves = [],
+			prevCurve,
+			prevTime;
+
+		for (var i = locations.length - 1; i >= 0; i--) {
+			var loc = locations[i];
+			if (include) {
+				if (!include(loc))
+					continue;
+				results.unshift(loc);
+			}
+			var curve = loc._curve,
+				time = loc._time,
+				origTime = time,
+				segment;
+			if (curve !== prevCurve) {
+				noHandles = !curve.hasHandles();
+			} else if (prevTime >= tMin && prevTime <= tMax ) {
+				time /= prevTime;
+			}
+			if (time < tMin) {
+				segment = curve._segment1;
+			} else if (time > tMax) {
+				segment = curve._segment2;
+			} else {
+				var newCurve = curve.divideAtTime(time, true);
+				if (noHandles)
+					clearCurves.push(curve, newCurve);
+				segment = newCurve._segment1;
+			}
+			loc._setSegment(segment);
+			var inter = segment._intersection,
+				dest = loc._intersection;
+			if (inter) {
+				linkIntersections(inter, dest);
+				var other = inter;
+				while (other) {
+					linkIntersections(other._intersection, inter);
+					other = other._next;
+				}
+			} else {
+				segment._intersection = dest;
+			}
+			prevCurve = curve;
+			prevTime = origTime;
+		}
+		for (var i = 0, l = clearCurves.length; i < l; i++) {
+			clearCurves[i].clearHandles();
+		}
+		return results || locations;
+	}
+
+	function getWinding(point, curves, horizontal) {
+		var epsilon = 2e-7,
+			px = point.x,
+			py = point.y,
+			windLeft = 0,
+			windRight = 0,
+			length = curves.length,
+			roots = [],
+			abs = Math.abs;
+		if (horizontal) {
+			var yTop = -Infinity,
+				yBottom = Infinity,
+				yBefore = py - epsilon,
+				yAfter = py + epsilon;
+			for (var i = 0; i < length; i++) {
+				var values = curves[i].values,
+					count = Curve.solveCubic(values, 0, px, roots, 0, 1);
+				for (var j = count - 1; j >= 0; j--) {
+					var y = Curve.getPoint(values, roots[j]).y;
+					if (y < yBefore && y > yTop) {
+						yTop = y;
+					} else if (y > yAfter && y < yBottom) {
+						yBottom = y;
+					}
+				}
+			}
+			yTop = (yTop + py) / 2;
+			yBottom = (yBottom + py) / 2;
+			if (yTop > -Infinity)
+				windLeft = getWinding(new Point(px, yTop), curves).winding;
+			if (yBottom < Infinity)
+				windRight = getWinding(new Point(px, yBottom), curves).winding;
+		} else {
+			var xBefore = px - epsilon,
+				xAfter = px + epsilon,
+				prevWinding,
+				prevXEnd,
+				windLeftOnCurve = 0,
+				windRightOnCurve = 0,
+				isOnCurve = false;
+			for (var i = 0; i < length; i++) {
+				var curve = curves[i],
+					winding = curve.winding,
+					values = curve.values,
+					yStart = values[1],
+					yEnd = values[7];
+				if (curve.last) {
+					prevWinding = curve.last.winding;
+					prevXEnd = curve.last.values[6];
+					isOnCurve = false;
+				}
+				if (py >= yStart && py <= yEnd || py >= yEnd && py <= yStart) {
+					if (winding) {
+						var x = py === yStart ? values[0]
+							: py === yEnd ? values[6]
+							: Curve.solveCubic(values, 1, py, roots, 0, 1) === 1
+							? Curve.getPoint(values, roots[0]).x
+							: null;
+						if (x != null) {
+							if (x >= xBefore && x <= xAfter) {
+								isOnCurve = true;
+							} else if (
+								(py !== yStart || winding !== prevWinding)
+								&& !(py === yStart
+									&& (px - x) * (px - prevXEnd) < 0)) {
+								if (x < xBefore) {
+									windLeft += winding;
+								} else if (x > xAfter) {
+									windRight += winding;
+								}
+							}
+						}
+						prevWinding = winding;
+						prevXEnd = values[6];
+					} else if ((px - values[0]) * (px - values[6]) <= 0) {
+						isOnCurve = true;
+					}
+				}
+				if (isOnCurve && (i >= length - 1 || curves[i + 1].last)) {
+					windLeftOnCurve += 1;
+					windRightOnCurve -= 1;
+				}
+			}
+			if (windLeft === 0 && windRight === 0) {
+				windLeft = windLeftOnCurve;
+				windRight = windRightOnCurve;
+			}
+		}
+		return {
+			winding: Math.max(abs(windLeft), abs(windRight)),
+			contour: !windLeft ^ !windRight
+		};
+	}
+
+	function propagateWinding(segment, path1, path2, monoCurves, operator) {
+		var chain = [],
+			start = segment,
+			totalLength = 0,
+			winding;
+		do {
+			var curve = segment.getCurve(),
+				length = curve.getLength();
+			chain.push({ segment: segment, curve: curve, length: length });
+			totalLength += length;
+			segment = segment.getNext();
+		} while (segment && !segment._intersection && segment !== start);
+		var length = totalLength / 2;
+		for (var j = 0, l = chain.length; j < l; j++) {
+			var entry = chain[j],
+				curveLength = entry.length;
+			if (length <= curveLength) {
+				var curve = entry.curve,
+					path = curve._path,
+					parent = path._parent,
+					t = curve.getTimeAt(length),
+					pt = curve.getPointAtTime(t),
+					hor = Math.abs(curve.getTangentAtTime(t).y)
+							< 1e-7;
+				if (parent instanceof CompoundPath)
+					path = parent;
+				winding = !(operator.subtract && path2 && (
+						path === path1 &&  path2._getWinding(pt, hor) ||
+						path === path2 && !path1._getWinding(pt, hor)))
+							? getWinding(pt, monoCurves, hor)
+							: { winding: 0 };
+				 break;
+			}
+			length -= curveLength;
+		}
+		for (var j = chain.length - 1; j >= 0; j--) {
+			var seg = chain[j].segment;
+			seg._winding = winding.winding;
+			seg._contour = winding.contour;
+		}
+	}
+
+	function tracePaths(segments, operator) {
+		var paths = [],
+			start,
+			otherStart;
+
+		function isValid(seg, excludeContour) {
+			return !!(seg && !seg._visited && (!operator
+					|| operator[seg._winding]
+					|| !excludeContour && operator.unite && seg._contour));
+		}
+
+		function isStart(seg) {
+			return seg === start || seg === otherStart;
+		}
+
+		function findBestIntersection(inter, exclude) {
+			if (!inter._next)
+				return inter;
+			while (inter) {
+				var seg = inter._segment,
+					nextSeg = seg.getNext(),
+					nextInter = nextSeg && nextSeg._intersection;
+				if (seg !== exclude && (isStart(seg) || isStart(nextSeg)
+					|| !seg._visited && !nextSeg._visited
+					&& (!operator || isValid(seg) && (isValid(nextSeg)
+						|| nextInter && isValid(nextInter._segment)))
+					))
+					return inter;
+				inter = inter._next;
+			}
+			return null;
+		}
+
+		for (var i = 0, l = segments.length; i < l; i++) {
+			var path = null,
+				finished = false,
+				seg = segments[i],
+				inter = seg._intersection,
+				handleIn;
+			if (!seg._visited && seg._path._overlapsOnly) {
+				var path1 = seg._path,
+					path2 = inter._segment._path,
+					segments1 = path1._segments,
+					segments2 = path2._segments;
+				if (Base.equals(segments1, segments2)) {
+					if ((operator.unite || operator.intersect)
+							&& path1.getArea()) {
+						paths.push(path1.clone(false));
+					}
+					for (var j = 0, k = segments1.length; j < k; j++) {
+						segments1[j]._visited = segments2[j]._visited = true;
+					}
+				}
+			}
+			if (!isValid(seg, true)
+					|| !seg._path._validOverlapsOnly && inter && inter._overlap)
+				continue;
+			start = otherStart = null;
+			while (true) {
+				inter = inter && findBestIntersection(inter, seg) || inter;
+				var other = inter && inter._segment;
+				if (isStart(seg)) {
+					finished = true;
+				} else if (other) {
+					if (isStart(other)) {
+						finished = true;
+						seg = other;
+					} else if (isValid(other, isValid(seg, true))) {
+						if (operator
+								&& (operator.intersect || operator.subtract)) {
+							seg._visited = true;
+						}
+						seg = other;
+					}
+				}
+				if (finished || seg._visited) {
+					seg._visited = true;
+					break;
+				}
+				if (seg._path._validOverlapsOnly && !isValid(seg))
+					break;
+				if (!path) {
+					path = new Path(Item.NO_INSERT);
+					start = seg;
+					otherStart = other;
+				}
+				var next = seg.getNext();
+				path.add(new Segment(seg._point, handleIn,
+						next && seg._handleOut));
+				seg._visited = true;
+				seg = next || seg._path.getFirstSegment();
+				handleIn = next && next._handleIn;
+				inter = seg._intersection;
+			}
+			if (finished) {
+				path.firstSegment.setHandleIn(handleIn);
+				path.setClosed(true);
+			} else if (path) {
+				var area = path.getArea(true);
+				if (Math.abs(area) >= 2e-7) {
+					console.error('Boolean operation resulted in open path',
+							'segments =', path._segments.length,
+							'length =', path.getLength(),
+							'area=', area);
+				}
+				path = null;
+			}
+			if (path && (path._segments.length > 8
+					|| !Numerical.isZero(path.getArea()))) {
+				paths.push(path);
+				path = null;
+			}
+		}
+		return paths;
+	}
+
+	return {
+		_getWinding: function(point, horizontal) {
+			return getWinding(point, this._getMonoCurves(), horizontal).winding;
+		},
+
+		unite: function(path) {
+			return computeBoolean(this, path, 'unite');
+		},
+
+		intersect: function(path) {
+			return computeBoolean(this, path, 'intersect');
+		},
+
+		subtract: function(path) {
+			return computeBoolean(this, path, 'subtract');
+		},
+
+		exclude: function(path) {
+			return computeBoolean(this, path, 'exclude');
+		},
+
+		divide: function(path) {
+			return createResult(Group, [this.subtract(path),
+					this.intersect(path)], true, this, path);
+		},
+
+		resolveCrossings: function() {
+			var children = this._children,
+				paths = children || [this];
+
+			function hasOverlap(seg) {
+				var inter = seg && seg._intersection;
+				return inter && inter._overlap;
+			}
+
+			var hasOverlaps = false,
+				hasCrossings = false,
+				intersections = this.getIntersections(null, function(inter) {
+					return inter._overlap && (hasOverlaps = true)
+							|| inter.isCrossing() && (hasCrossings = true);
+				});
+			intersections = CurveLocation.expand(intersections);
+			if (hasOverlaps) {
+				var overlaps = divideLocations(intersections, function(inter) {
+					return inter._overlap;
+				});
+				for (var i = overlaps.length - 1; i >= 0; i--) {
+					var seg = overlaps[i]._segment,
+						prev = seg.getPrevious(),
+						next = seg.getNext();
+					if (seg._path && hasOverlap(prev) && hasOverlap(next)) {
+						seg.remove();
+						prev._handleOut.set(0, 0);
+						next._handleIn.set(0, 0);
+						var curve = prev.getCurve();
+						if (curve.isStraight() && curve.getLength() === 0)
+							prev.remove();
+					}
+				}
+			}
+			if (hasCrossings) {
+				divideLocations(intersections, hasOverlaps && function(inter) {
+					var curve1 = inter.getCurve(),
+						curve2 = inter._intersection._curve,
+						seg = inter._segment;
+					if (curve1 && curve2 && curve1._path && curve2._path) {
+						return true;
+					} else if (seg) {
+						seg._intersection = null;
+					}
+				});
+				paths = tracePaths(Base.each(paths, function(path) {
+					this.push.apply(this, path._segments);
+				}, []));
+			}
+			var length = paths.length,
+				item;
+			if (length > 1) {
+				paths = paths.slice().sort(function (a, b) {
+					return b.getBounds().getArea() - a.getBounds().getArea();
+				});
+				var first = paths[0],
+					items = [first],
+					excluded = {},
+					isNonZero = this.getFillRule() === 'nonzero',
+					windings = isNonZero && Base.each(paths, function(path) {
+						this.push(path.isClockwise() ? 1 : -1);
+					}, []);
+				for (var i = 1; i < length; i++) {
+					var path = paths[i],
+						point = path.getInteriorPoint(),
+						isContained = false,
+						container = null,
+						exclude = false;
+					for (var j = i - 1; j >= 0 && !container; j--) {
+						if (paths[j].contains(point)) {
+							if (isNonZero && !isContained) {
+								windings[i] += windings[j];
+								if (windings[i] && windings[j]) {
+									exclude = excluded[i] = true;
+									break;
+								}
+							}
+							isContained = true;
+							container = !excluded[j] && paths[j];
+						}
+					}
+					if (!exclude) {
+						path.setClockwise(container ? !container.isClockwise()
+								: first.isClockwise());
+						items.push(path);
+					}
+				}
+				paths = items;
+				length = items.length;
+			}
+			if (length > 1 && children) {
+				if (paths !== children) {
+					this.setChildren(paths, true);
+				}
+				item = this;
+			} else if (length === 1 && !children) {
+				if (paths[0] !== this)
+					this.setSegments(paths[0].removeSegments());
+				item = this;
+			}
+			if (!item) {
+				item = new CompoundPath(Item.NO_INSERT);
+				item.addChildren(paths, true);
+				item = item.reduce();
+				item.copyAttributes(this);
+				this.replaceWith(item);
+			}
+			return item;
+		}
+	};
+});
+
+Path.inject({
+	_getMonoCurves: function() {
+		var monoCurves = this._monoCurves,
+			last;
+
+		function insertCurve(v) {
+			var y0 = v[1],
+				y1 = v[7],
+				winding = Math.abs((y0 - y1) / (v[0] - v[6]))
+						< 2e-7
+					? 0
+					: y0 > y1
+						? -1
+						: 1,
+				curve = { values: v, winding: winding };
+			monoCurves.push(curve);
+			if (winding)
+				last = curve;
+		}
+
+		function handleCurve(v) {
+			if (Curve.getLength(v) === 0)
+				return;
+			var y0 = v[1],
+				y1 = v[3],
+				y2 = v[5],
+				y3 = v[7];
+			if (Curve.isStraight(v)
+					|| y0 >= y1 === y1 >= y2 && y1 >= y2 === y2 >= y3) {
+				insertCurve(v);
+			} else {
+				var a = 3 * (y1 - y2) - y0 + y3,
+					b = 2 * (y0 + y2) - 4 * y1,
+					c = y1 - y0,
+					tMin = 4e-7,
+					tMax = 1 - tMin,
+					roots = [],
+					n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
+				if (n < 1) {
+					insertCurve(v);
+				} else {
+					roots.sort();
+					var t = roots[0],
+						parts = Curve.subdivide(v, t);
+					insertCurve(parts[0]);
+					if (n > 1) {
+						t = (roots[1] - t) / (1 - t);
+						parts = Curve.subdivide(parts[1], t);
+						insertCurve(parts[0]);
+					}
+					insertCurve(parts[1]);
+				}
+			}
+		}
+
+		if (!monoCurves) {
+			monoCurves = this._monoCurves = [];
+			var curves = this.getCurves(),
+				segments = this._segments;
+			for (var i = 0, l = curves.length; i < l; i++)
+				handleCurve(curves[i].getValues());
+			if (!this._closed && segments.length > 1) {
+				var p1 = segments[segments.length - 1]._point,
+					p2 = segments[0]._point,
+					p1x = p1._x, p1y = p1._y,
+					p2x = p2._x, p2y = p2._y;
+				handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
+			}
+			if (monoCurves.length > 0) {
+				monoCurves[0].last = last;
+			}
+		}
+		return monoCurves;
+	},
+
+	getInteriorPoint: function() {
+		var bounds = this.getBounds(),
+			point = bounds.getCenter(true);
+		if (!this.contains(point)) {
+			var curves = this._getMonoCurves(),
+				roots = [],
+				y = point.y,
+				intercepts = [];
+			for (var i = 0, l = curves.length; i < l; i++) {
+				var values = curves[i].values;
+				if (curves[i].winding === 1
+						&& y > values[1] && y <= values[7]
+						|| y >= values[7] && y < values[1]) {
+					var count = Curve.solveCubic(values, 1, y, roots, 0, 1);
+					for (var j = count - 1; j >= 0; j--) {
+						intercepts.push(Curve.getPoint(values, roots[j]).x);
+					}
+				}
+			}
+			intercepts.sort(function(a, b) { return a - b; });
+			point.x = (intercepts[0] + intercepts[1]) / 2;
+		}
+		return point;
+	}
+});
+
+CompoundPath.inject({
+	_getMonoCurves: function() {
+		var children = this._children,
+			monoCurves = [];
+		for (var i = 0, l = children.length; i < l; i++)
+			monoCurves.push.apply(monoCurves, children[i]._getMonoCurves());
+		return monoCurves;
+	}
+});
+
+var PathIterator = Base.extend({
+	_class: 'PathIterator',
+
+	initialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {
+		var curves = [],
+			parts = [],
+			length = 0,
+			minSpan = 1 / (maxRecursion || 32),
+			segments = path._segments,
+			segment1 = segments[0],
+			segment2;
+
+		function addCurve(segment1, segment2) {
+			var curve = Curve.getValues(segment1, segment2, matrix);
+			curves.push(curve);
+			computeParts(curve, segment1._index, 0, 1);
+		}
+
+		function computeParts(curve, index, t1, t2) {
+			if ((t2 - t1) > minSpan
+					&& !(ignoreStraight && Curve.isStraight(curve))
+					&& !Curve.isFlatEnough(curve, flatness || 0.25)) {
+				var halves = Curve.subdivide(curve, 0.5),
+					tMid = (t1 + t2) / 2;
+				computeParts(halves[0], index, t1, tMid);
+				computeParts(halves[1], index, tMid, t2);
+			} else {
+				var dx = curve[6] - curve[0],
+					dy = curve[7] - curve[1],
+					dist = Math.sqrt(dx * dx + dy * dy);
+				if (dist > 0) {
+					length += dist;
+					parts.push({
+						offset: length,
+						curve: curve,
+						index: index,
+						time: t2,
+					});
+				}
+			}
+		}
+
+		for (var i = 1, l = segments.length; i < l; i++) {
+			segment2 = segments[i];
+			addCurve(segment1, segment2);
+			segment1 = segment2;
+		}
+		if (path._closed)
+			addCurve(segment2, segments[0]);
+		this.curves = curves;
+		this.parts = parts;
+		this.length = length;
+		this.index = 0;
+	},
+
+	_get: function(offset) {
+		var i, j = this.index;
+		for (;;) {
+			i = j;
+			if (j === 0 || this.parts[--j].offset < offset)
+				break;
+		}
+		for (var l = this.parts.length; i < l; i++) {
+			var part = this.parts[i];
+			if (part.offset >= offset) {
+				this.index = i;
+				var prev = this.parts[i - 1];
+				var prevTime = prev && prev.index === part.index ? prev.time : 0,
+					prevOffset = prev ? prev.offset : 0;
+				return {
+					index: part.index,
+					time: prevTime + (part.time - prevTime)
+						* (offset - prevOffset) / (part.offset - prevOffset)
+				};
+			}
+		}
+		var part = this.parts[this.parts.length - 1];
+		return {
+			index: part.index,
+			time: 1
+		};
+	},
+
+	drawPart: function(ctx, from, to) {
+		var start = this._get(from),
+			end = this._get(to);
+		for (var i = start.index, l = end.index; i <= l; i++) {
+			var curve = Curve.getPart(this.curves[i],
+					i === start.index ? start.time : 0,
+					i === end.index ? end.time : 1);
+			if (i === start.index)
+				ctx.moveTo(curve[0], curve[1]);
+			ctx.bezierCurveTo.apply(ctx, curve.slice(2));
+		}
+	}
+}, Base.each(Curve._evaluateMethods,
+	function(name) {
+		this[name + 'At'] = function(offset) {
+			var param = this._get(offset);
+			return Curve[name](this.curves[param.index], param.time);
+		};
+	}, {})
+);
+
+var PathFitter = Base.extend({
+	initialize: function(path) {
+		var points = this.points = [],
+			segments = path._segments,
+			closed = path._closed;
+		for (var i = 0, prev, l = segments.length; i < l; i++) {
+			var point = segments[i].point;
+			if (!prev || !prev.equals(point)) {
+				points.push(prev = point.clone());
+			}
+		}
+		if (closed) {
+			points.unshift(points[points.length - 1]);
+			points.push(points[1]);
+		}
+		this.closed = closed;
+	},
+
+	fit: function(error) {
+		var points = this.points,
+			length = points.length,
+			segments = null;
+		if (length > 0) {
+			segments = [new Segment(points[0])];
+			if (length > 1) {
+				this.fitCubic(segments, error, 0, length - 1,
+						points[1].subtract(points[0]),
+						points[length - 2].subtract(points[length - 1]));
+				if (this.closed) {
+					segments.shift();
+					segments.pop();
+				}
+			}
+		}
+		return segments;
+	},
+
+	fitCubic: function(segments, error, first, last, tan1, tan2) {
+		var points = this.points;
+		if (last - first === 1) {
+			var pt1 = points[first],
+				pt2 = points[last],
+				dist = pt1.getDistance(pt2) / 3;
+			this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
+					pt2.add(tan2.normalize(dist)), pt2]);
+			return;
+		}
+		var uPrime = this.chordLengthParameterize(first, last),
+			maxError = Math.max(error, error * error),
+			split,
+			parametersInOrder = true;
+		for (var i = 0; i <= 4; i++) {
+			var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
+			var max = this.findMaxError(first, last, curve, uPrime);
+			if (max.error < error && parametersInOrder) {
+				this.addCurve(segments, curve);
+				return;
+			}
+			split = max.index;
+			if (max.error >= maxError)
+				break;
+			parametersInOrder = this.reparameterize(first, last, uPrime, curve);
+			maxError = max.error;
+		}
+		var tanCenter = points[split - 1].subtract(points[split + 1]);
+		this.fitCubic(segments, error, first, split, tan1, tanCenter);
+		this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
+	},
+
+	addCurve: function(segments, curve) {
+		var prev = segments[segments.length - 1];
+		prev.setHandleOut(curve[1].subtract(curve[0]));
+		segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
+	},
+
+	generateBezier: function(first, last, uPrime, tan1, tan2) {
+		var epsilon = 1e-12,
+			abs = Math.abs,
+			points = this.points,
+			pt1 = points[first],
+			pt2 = points[last],
+			C = [[0, 0], [0, 0]],
+			X = [0, 0];
+
+		for (var i = 0, l = last - first + 1; i < l; i++) {
+			var u = uPrime[i],
+				t = 1 - u,
+				b = 3 * u * t,
+				b0 = t * t * t,
+				b1 = b * t,
+				b2 = b * u,
+				b3 = u * u * u,
+				a1 = tan1.normalize(b1),
+				a2 = tan2.normalize(b2),
+				tmp = points[first + i]
+					.subtract(pt1.multiply(b0 + b1))
+					.subtract(pt2.multiply(b2 + b3));
+			C[0][0] += a1.dot(a1);
+			C[0][1] += a1.dot(a2);
+			C[1][0] = C[0][1];
+			C[1][1] += a2.dot(a2);
+			X[0] += a1.dot(tmp);
+			X[1] += a2.dot(tmp);
+		}
+
+		var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
+			alpha1, alpha2;
+		if (abs(detC0C1) > epsilon) {
+			var detC0X = C[0][0] * X[1]    - C[1][0] * X[0],
+				detXC1 = X[0]    * C[1][1] - X[1]    * C[0][1];
+			alpha1 = detXC1 / detC0C1;
+			alpha2 = detC0X / detC0C1;
+		} else {
+			var c0 = C[0][0] + C[0][1],
+				c1 = C[1][0] + C[1][1];
+			if (abs(c0) > epsilon) {
+				alpha1 = alpha2 = X[0] / c0;
+			} else if (abs(c1) > epsilon) {
+				alpha1 = alpha2 = X[1] / c1;
+			} else {
+				alpha1 = alpha2 = 0;
+			}
+		}
+
+		var segLength = pt2.getDistance(pt1),
+			eps = epsilon * segLength,
+			handle1,
+			handle2;
+		if (alpha1 < eps || alpha2 < eps) {
+			alpha1 = alpha2 = segLength / 3;
+		} else {
+			var line = pt2.subtract(pt1);
+			handle1 = tan1.normalize(alpha1);
+			handle2 = tan2.normalize(alpha2);
+			if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
+				alpha1 = alpha2 = segLength / 3;
+				handle1 = handle2 = null;
+			}
+		}
+
+		return [pt1,
+				pt1.add(handle1 || tan1.normalize(alpha1)),
+				pt2.add(handle2 || tan2.normalize(alpha2)),
+				pt2];
+	},
+
+	reparameterize: function(first, last, u, curve) {
+		for (var i = first; i <= last; i++) {
+			u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
+		}
+		for (var i = 1, l = u.length; i < l; i++) {
+			if (u[i] <= u[i - 1])
+				return false;
+		}
+		return true;
+	},
+
+	findRoot: function(curve, point, u) {
+		var curve1 = [],
+			curve2 = [];
+		for (var i = 0; i <= 2; i++) {
+			curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);
+		}
+		for (var i = 0; i <= 1; i++) {
+			curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);
+		}
+		var pt = this.evaluate(3, curve, u),
+			pt1 = this.evaluate(2, curve1, u),
+			pt2 = this.evaluate(1, curve2, u),
+			diff = pt.subtract(point),
+			df = pt1.dot(pt1) + diff.dot(pt2);
+		if (Math.abs(df) < 1e-6)
+			return u;
+		return u - diff.dot(pt1) / df;
+	},
+
+	evaluate: function(degree, curve, t) {
+		var tmp = curve.slice();
+		for (var i = 1; i <= degree; i++) {
+			for (var j = 0; j <= degree - i; j++) {
+				tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));
+			}
+		}
+		return tmp[0];
+	},
+
+	chordLengthParameterize: function(first, last) {
+		var u = [0];
+		for (var i = first + 1; i <= last; i++) {
+			u[i - first] = u[i - first - 1]
+					+ this.points[i].getDistance(this.points[i - 1]);
+		}
+		for (var i = 1, m = last - first; i <= m; i++) {
+			u[i] /= u[m];
+		}
+		return u;
+	},
+
+	findMaxError: function(first, last, curve, u) {
+		var index = Math.floor((last - first + 1) / 2),
+			maxDist = 0;
+		for (var i = first + 1; i < last; i++) {
+			var P = this.evaluate(3, curve, u[i - first]);
+			var v = P.subtract(this.points[i]);
+			var dist = v.x * v.x + v.y * v.y;
+			if (dist >= maxDist) {
+				maxDist = dist;
+				index = i;
+			}
+		}
+		return {
+			error: maxDist,
+			index: index
+		};
+	}
+});
+
+var TextItem = Item.extend({
+	_class: 'TextItem',
+	_applyMatrix: false,
+	_canApplyMatrix: false,
+	_serializeFields: {
+		content: null
+	},
+	_boundsOptions: { stroke: false, handle: false },
+
+	initialize: function TextItem(arg) {
+		this._content = '';
+		this._lines = [];
+		var hasProps = arg && Base.isPlainObject(arg)
+				&& arg.x === undefined && arg.y === undefined;
+		this._initialize(hasProps && arg, !hasProps && Point.read(arguments));
+	},
+
+	_equals: function(item) {
+		return this._content === item._content;
+	},
+
+	copyContent: function(source) {
+		this.setContent(source._content);
+	},
+
+	getContent: function() {
+		return this._content;
+	},
+
+	setContent: function(content) {
+		this._content = '' + content;
+		this._lines = this._content.split(/\r\n|\n|\r/mg);
+		this._changed(265);
+	},
+
+	isEmpty: function() {
+		return !this._content;
+	},
+
+	getCharacterStyle: '#getStyle',
+	setCharacterStyle: '#setStyle',
+
+	getParagraphStyle: '#getStyle',
+	setParagraphStyle: '#setStyle'
+});
+
+var PointText = TextItem.extend({
+	_class: 'PointText',
+
+	initialize: function PointText() {
+		TextItem.apply(this, arguments);
+	},
+
+	getPoint: function() {
+		var point = this._matrix.getTranslation();
+		return new LinkedPoint(point.x, point.y, this, 'setPoint');
+	},
+
+	setPoint: function() {
+		var point = Point.read(arguments);
+		this.translate(point.subtract(this._matrix.getTranslation()));
+	},
+
+	_draw: function(ctx, param, viewMatrix) {
+		if (!this._content)
+			return;
+		this._setStyles(ctx, param, viewMatrix);
+		var lines = this._lines,
+			style = this._style,
+			hasFill = style.hasFill(),
+			hasStroke = style.hasStroke(),
+			leading = style.getLeading(),
+			shadowColor = ctx.shadowColor;
+		ctx.font = style.getFontStyle();
+		ctx.textAlign = style.getJustification();
+		for (var i = 0, l = lines.length; i < l; i++) {
+			ctx.shadowColor = shadowColor;
+			var line = lines[i];
+			if (hasFill) {
+				ctx.fillText(line, 0, 0);
+				ctx.shadowColor = 'rgba(0,0,0,0)';
+			}
+			if (hasStroke)
+				ctx.strokeText(line, 0, 0);
+			ctx.translate(0, leading);
+		}
+	},
+
+	_getBounds: function(matrix, options) {
+		var style = this._style,
+			lines = this._lines,
+			numLines = lines.length,
+			justification = style.getJustification(),
+			leading = style.getLeading(),
+			width = this.getView().getTextWidth(style.getFontStyle(), lines),
+			x = 0;
+		if (justification !== 'left')
+			x -= width / (justification === 'center' ? 2: 1);
+		var bounds = new Rectangle(x,
+					numLines ? - 0.75 * leading : 0,
+					width, numLines * leading);
+		return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
+	}
+});
+
+var Color = Base.extend(new function() {
+	var types = {
+		gray: ['gray'],
+		rgb: ['red', 'green', 'blue'],
+		hsb: ['hue', 'saturation', 'brightness'],
+		hsl: ['hue', 'saturation', 'lightness'],
+		gradient: ['gradient', 'origin', 'destination', 'highlight']
+	};
+
+	var componentParsers = {},
+		colorCache = {},
+		colorCtx;
+
+	function fromCSS(string) {
+		var match = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/),
+			components;
+		if (match) {
+			components = [0, 0, 0];
+			for (var i = 0; i < 3; i++) {
+				var value = match[i + 1];
+				components[i] = parseInt(value.length == 1
+						? value + value : value, 16) / 255;
+			}
+		} else if (match = string.match(/^rgba?\((.*)\)$/)) {
+			components = match[1].split(',');
+			for (var i = 0, l = components.length; i < l; i++) {
+				var value = +components[i];
+				components[i] = i < 3 ? value / 255 : value;
+			}
+		} else if (window) {
+			var cached = colorCache[string];
+			if (!cached) {
+				if (!colorCtx) {
+					colorCtx = CanvasProvider.getContext(1, 1);
+					colorCtx.globalCompositeOperation = 'copy';
+				}
+				colorCtx.fillStyle = 'rgba(0,0,0,0)';
+				colorCtx.fillStyle = string;
+				colorCtx.fillRect(0, 0, 1, 1);
+				var data = colorCtx.getImageData(0, 0, 1, 1).data;
+				cached = colorCache[string] = [
+					data[0] / 255,
+					data[1] / 255,
+					data[2] / 255
+				];
+			}
+			components = cached.slice();
+		} else {
+			components = [0, 0, 0];
+		}
+		return components;
+	}
+
+	var hsbIndices = [
+		[0, 3, 1],
+		[2, 0, 1],
+		[1, 0, 3],
+		[1, 2, 0],
+		[3, 1, 0],
+		[0, 1, 2]
+	];
+
+	var converters = {
+		'rgb-hsb': function(r, g, b) {
+			var max = Math.max(r, g, b),
+				min = Math.min(r, g, b),
+				delta = max - min,
+				h = delta === 0 ? 0
+					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
+						: max == g ? (b - r) / delta + 2
+						:            (r - g) / delta + 4) * 60;
+			return [h, max === 0 ? 0 : delta / max, max];
+		},
+
+		'hsb-rgb': function(h, s, b) {
+			h = (((h / 60) % 6) + 6) % 6;
+			var i = Math.floor(h),
+				f = h - i,
+				i = hsbIndices[i],
+				v = [
+					b,
+					b * (1 - s),
+					b * (1 - s * f),
+					b * (1 - s * (1 - f))
+				];
+			return [v[i[0]], v[i[1]], v[i[2]]];
+		},
+
+		'rgb-hsl': function(r, g, b) {
+			var max = Math.max(r, g, b),
+				min = Math.min(r, g, b),
+				delta = max - min,
+				achromatic = delta === 0,
+				h = achromatic ? 0
+					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
+						: max == g ? (b - r) / delta + 2
+						:            (r - g) / delta + 4) * 60,
+				l = (max + min) / 2,
+				s = achromatic ? 0 : l < 0.5
+						? delta / (max + min)
+						: delta / (2 - max - min);
+			return [h, s, l];
+		},
+
+		'hsl-rgb': function(h, s, l) {
+			h = (((h / 360) % 1) + 1) % 1;
+			if (s === 0)
+				return [l, l, l];
+			var t3s = [ h + 1 / 3, h, h - 1 / 3 ],
+				t2 = l < 0.5 ? l * (1 + s) : l + s - l * s,
+				t1 = 2 * l - t2,
+				c = [];
+			for (var i = 0; i < 3; i++) {
+				var t3 = t3s[i];
+				if (t3 < 0) t3 += 1;
+				if (t3 > 1) t3 -= 1;
+				c[i] = 6 * t3 < 1
+					? t1 + (t2 - t1) * 6 * t3
+					: 2 * t3 < 1
+						? t2
+						: 3 * t3 < 2
+							? t1 + (t2 - t1) * ((2 / 3) - t3) * 6
+							: t1;
+			}
+			return c;
+		},
+
+		'rgb-gray': function(r, g, b) {
+			return [r * 0.2989 + g * 0.587 + b * 0.114];
+		},
+
+		'gray-rgb': function(g) {
+			return [g, g, g];
+		},
+
+		'gray-hsb': function(g) {
+			return [0, 0, g];
+		},
+
+		'gray-hsl': function(g) {
+			return [0, 0, g];
+		},
+
+		'gradient-rgb': function() {
+			return [];
+		},
+
+		'rgb-gradient': function() {
+			return [];
+		}
+
+	};
+
+	return Base.each(types, function(properties, type) {
+		componentParsers[type] = [];
+		Base.each(properties, function(name, index) {
+			var part = Base.capitalize(name),
+				hasOverlap = /^(hue|saturation)$/.test(name),
+				parser = componentParsers[type][index] = name === 'gradient'
+					? function(value) {
+						var current = this._components[0];
+						value = Gradient.read(Array.isArray(value) ? value
+								: arguments, 0, { readNull: true });
+						if (current !== value) {
+							if (current)
+								current._removeOwner(this);
+							if (value)
+								value._addOwner(this);
+						}
+						return value;
+					}
+					: type === 'gradient'
+						? function() {
+							return Point.read(arguments, 0, {
+									readNull: name === 'highlight',
+									clone: true
+							});
+						}
+						: function(value) {
+							return value == null || isNaN(value) ? 0 : value;
+						};
+
+			this['get' + part] = function() {
+				return this._type === type
+					|| hasOverlap && /^hs[bl]$/.test(this._type)
+						? this._components[index]
+						: this._convert(type)[index];
+			};
+
+			this['set' + part] = function(value) {
+				if (this._type !== type
+						&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {
+					this._components = this._convert(type);
+					this._properties = types[type];
+					this._type = type;
+				}
+				this._components[index] = parser.call(this, value);
+				this._changed();
+			};
+		}, this);
+	}, {
+		_class: 'Color',
+		_readIndex: true,
+
+		initialize: function Color(arg) {
+			var slice = Array.prototype.slice,
+				args = arguments,
+				reading = this.__read,
+				read = 0,
+				type,
+				components,
+				alpha,
+				values;
+			if (Array.isArray(arg)) {
+				args = arg;
+				arg = args[0];
+			}
+			var argType = arg != null && typeof arg;
+			if (argType === 'string' && arg in types) {
+				type = arg;
+				arg = args[1];
+				if (Array.isArray(arg)) {
+					components = arg;
+					alpha = args[2];
+				} else {
+					if (reading)
+						read = 1;
+					args = slice.call(args, 1);
+					argType = typeof arg;
+				}
+			}
+			if (!components) {
+				values = argType === 'number'
+						? args
+						: argType === 'object' && arg.length != null
+							? arg
+							: null;
+				if (values) {
+					if (!type)
+						type = values.length >= 3
+								? 'rgb'
+								: 'gray';
+					var length = types[type].length;
+					alpha = values[length];
+					if (reading) {
+						read += values === arguments
+							? length + (alpha != null ? 1 : 0)
+							: 1;
+					}
+					if (values.length > length)
+						values = slice.call(values, 0, length);
+				} else if (argType === 'string') {
+					type = 'rgb';
+					components = fromCSS(arg);
+					if (components.length === 4) {
+						alpha = components[3];
+						components.length--;
+					}
+				} else if (argType === 'object') {
+					if (arg.constructor === Color) {
+						type = arg._type;
+						components = arg._components.slice();
+						alpha = arg._alpha;
+						if (type === 'gradient') {
+							for (var i = 1, l = components.length; i < l; i++) {
+								var point = components[i];
+								if (point)
+									components[i] = point.clone();
+							}
+						}
+					} else if (arg.constructor === Gradient) {
+						type = 'gradient';
+						values = args;
+					} else {
+						type = 'hue' in arg
+							? 'lightness' in arg
+								? 'hsl'
+								: 'hsb'
+							: 'gradient' in arg || 'stops' in arg
+									|| 'radial' in arg
+								? 'gradient'
+								: 'gray' in arg
+									? 'gray'
+									: 'rgb';
+						var properties = types[type],
+							parsers = componentParsers[type];
+						this._components = components = [];
+						for (var i = 0, l = properties.length; i < l; i++) {
+							var value = arg[properties[i]];
+							if (value == null && i === 0 && type === 'gradient'
+									&& 'stops' in arg) {
+								value = {
+									stops: arg.stops,
+									radial: arg.radial
+								};
+							}
+							value = parsers[i].call(this, value);
+							if (value != null)
+								components[i] = value;
+						}
+						alpha = arg.alpha;
+					}
+				}
+				if (reading && type)
+					read = 1;
+			}
+			this._type = type || 'rgb';
+			if (!components) {
+				this._components = components = [];
+				var parsers = componentParsers[this._type];
+				for (var i = 0, l = parsers.length; i < l; i++) {
+					var value = parsers[i].call(this, values && values[i]);
+					if (value != null)
+						components[i] = value;
+				}
+			}
+			this._components = components;
+			this._properties = types[this._type];
+			this._alpha = alpha;
+			if (reading)
+				this.__read = read;
+		},
+
+		_set: '#initialize',
+
+		_serialize: function(options, dictionary) {
+			var components = this.getComponents();
+			return Base.serialize(
+					/^(gray|rgb)$/.test(this._type)
+						? components
+						: [this._type].concat(components),
+					options, true, dictionary);
+		},
+
+		_changed: function() {
+			this._canvasStyle = null;
+			if (this._owner)
+				this._owner._changed(65);
+		},
+
+		_convert: function(type) {
+			var converter;
+			return this._type === type
+					? this._components.slice()
+					: (converter = converters[this._type + '-' + type])
+						? converter.apply(this, this._components)
+						: converters['rgb-' + type].apply(this,
+							converters[this._type + '-rgb'].apply(this,
+								this._components));
+		},
+
+		convert: function(type) {
+			return new Color(type, this._convert(type), this._alpha);
+		},
+
+		getType: function() {
+			return this._type;
+		},
+
+		setType: function(type) {
+			this._components = this._convert(type);
+			this._properties = types[type];
+			this._type = type;
+		},
+
+		getComponents: function() {
+			var components = this._components.slice();
+			if (this._alpha != null)
+				components.push(this._alpha);
+			return components;
+		},
+
+		getAlpha: function() {
+			return this._alpha != null ? this._alpha : 1;
+		},
+
+		setAlpha: function(alpha) {
+			this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);
+			this._changed();
+		},
+
+		hasAlpha: function() {
+			return this._alpha != null;
+		},
+
+		equals: function(color) {
+			var col = Base.isPlainValue(color, true)
+					? Color.read(arguments)
+					: color;
+			return col === this || col && this._class === col._class
+					&& this._type === col._type
+					&& this._alpha === col._alpha
+					&& Base.equals(this._components, col._components)
+					|| false;
+		},
+
+		toString: function() {
+			var properties = this._properties,
+				parts = [],
+				isGradient = this._type === 'gradient',
+				f = Formatter.instance;
+			for (var i = 0, l = properties.length; i < l; i++) {
+				var value = this._components[i];
+				if (value != null)
+					parts.push(properties[i] + ': '
+							+ (isGradient ? value : f.number(value)));
+			}
+			if (this._alpha != null)
+				parts.push('alpha: ' + f.number(this._alpha));
+			return '{ ' + parts.join(', ') + ' }';
+		},
+
+		toCSS: function(hex) {
+			var components = this._convert('rgb'),
+				alpha = hex || this._alpha == null ? 1 : this._alpha;
+			function convert(val) {
+				return Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);
+			}
+			components = [
+				convert(components[0]),
+				convert(components[1]),
+				convert(components[2])
+			];
+			if (alpha < 1)
+				components.push(alpha < 0 ? 0 : alpha);
+			return hex
+					? '#' + ((1 << 24) + (components[0] << 16)
+						+ (components[1] << 8)
+						+ components[2]).toString(16).slice(1)
+					: (components.length == 4 ? 'rgba(' : 'rgb(')
+						+ components.join(',') + ')';
+		},
+
+		toCanvasStyle: function(ctx) {
+			if (this._canvasStyle)
+				return this._canvasStyle;
+			if (this._type !== 'gradient')
+				return this._canvasStyle = this.toCSS();
+			var components = this._components,
+				gradient = components[0],
+				stops = gradient._stops,
+				origin = components[1],
+				destination = components[2],
+				canvasGradient;
+			if (gradient._radial) {
+				var radius = destination.getDistance(origin),
+					highlight = components[3];
+				if (highlight) {
+					var vector = highlight.subtract(origin);
+					if (vector.getLength() > radius)
+						highlight = origin.add(vector.normalize(radius - 0.1));
+				}
+				var start = highlight || origin;
+				canvasGradient = ctx.createRadialGradient(start.x, start.y,
+						0, origin.x, origin.y, radius);
+			} else {
+				canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
+						destination.x, destination.y);
+			}
+			for (var i = 0, l = stops.length; i < l; i++) {
+				var stop = stops[i];
+				canvasGradient.addColorStop(stop._offset || i / (l - 1),
+						stop._color.toCanvasStyle());
+			}
+			return this._canvasStyle = canvasGradient;
+		},
+
+		transform: function(matrix) {
+			if (this._type === 'gradient') {
+				var components = this._components;
+				for (var i = 1, l = components.length; i < l; i++) {
+					var point = components[i];
+					matrix._transformPoint(point, point, true);
+				}
+				this._changed();
+			}
+		},
+
+		statics: {
+			_types: types,
+
+			random: function() {
+				var random = Math.random;
+				return new Color(random(), random(), random());
+			}
+		}
+	});
+},
+new function() {
+	var operators = {
+		add: function(a, b) {
+			return a + b;
+		},
+
+		subtract: function(a, b) {
+			return a - b;
+		},
+
+		multiply: function(a, b) {
+			return a * b;
+		},
+
+		divide: function(a, b) {
+			return a / b;
+		}
+	};
+
+	return Base.each(operators, function(operator, name) {
+		this[name] = function(color) {
+			color = Color.read(arguments);
+			var type = this._type,
+				components1 = this._components,
+				components2 = color._convert(type);
+			for (var i = 0, l = components1.length; i < l; i++)
+				components2[i] = operator(components1[i], components2[i]);
+			return new Color(type, components2,
+					this._alpha != null
+							? operator(this._alpha, color.getAlpha())
+							: null);
+		};
+	}, {
+	});
+});
+
+var Gradient = Base.extend({
+	_class: 'Gradient',
+
+	initialize: function Gradient(stops, radial) {
+		this._id = UID.get();
+		if (stops && this._set(stops))
+			stops = radial = null;
+		if (!this._stops)
+			this.setStops(stops || ['white', 'black']);
+		if (this._radial == null) {
+			this.setRadial(typeof radial === 'string' && radial === 'radial'
+					|| radial || false);
+		}
+	},
+
+	_serialize: function(options, dictionary) {
+		return dictionary.add(this, function() {
+			return Base.serialize([this._stops, this._radial],
+					options, true, dictionary);
+		});
+	},
+
+	_changed: function() {
+		for (var i = 0, l = this._owners && this._owners.length; i < l; i++) {
+			this._owners[i]._changed();
+		}
+	},
+
+	_addOwner: function(color) {
+		if (!this._owners)
+			this._owners = [];
+		this._owners.push(color);
+	},
+
+	_removeOwner: function(color) {
+		var index = this._owners ? this._owners.indexOf(color) : -1;
+		if (index != -1) {
+			this._owners.splice(index, 1);
+			if (this._owners.length === 0)
+				this._owners = undefined;
+		}
+	},
+
+	clone: function() {
+		var stops = [];
+		for (var i = 0, l = this._stops.length; i < l; i++) {
+			stops[i] = this._stops[i].clone();
+		}
+		return new Gradient(stops, this._radial);
+	},
+
+	getStops: function() {
+		return this._stops;
+	},
+
+	setStops: function(stops) {
+		if (stops.length < 2) {
+			throw new Error(
+					'Gradient stop list needs to contain at least two stops.');
+		}
+		var _stops = this._stops;
+		if (_stops) {
+			for (var i = 0, l = _stops.length; i < l; i++)
+				_stops[i]._owner = undefined;
+		}
+		_stops = this._stops = GradientStop.readAll(stops, 0, { clone: true });
+		for (var i = 0, l = _stops.length; i < l; i++)
+			_stops[i]._owner = this;
+		this._changed();
+	},
+
+	getRadial: function() {
+		return this._radial;
+	},
+
+	setRadial: function(radial) {
+		this._radial = radial;
+		this._changed();
+	},
+
+	equals: function(gradient) {
+		if (gradient === this)
+			return true;
+		if (gradient && this._class === gradient._class) {
+			var stops1 = this._stops,
+				stops2 = gradient._stops,
+				length = stops1.length;
+			if (length === stops2.length) {
+				for (var i = 0; i < length; i++) {
+					if (!stops1[i].equals(stops2[i]))
+						return false;
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+});
+
+var GradientStop = Base.extend({
+	_class: 'GradientStop',
+
+	initialize: function GradientStop(arg0, arg1) {
+		var color = arg0,
+			offset = arg1;
+		if (typeof arg0 === 'object' && arg1 === undefined) {
+			if (Array.isArray(arg0) && typeof arg0[0] !== 'number') {
+				color = arg0[0];
+				offset = arg0[1];
+			} else if ('color' in arg0 || 'offset' in arg0
+					|| 'rampPoint' in arg0) {
+				color = arg0.color;
+				offset = arg0.offset || arg0.rampPoint || 0;
+			}
+		}
+		this.setColor(color);
+		this.setOffset(offset);
+	},
+
+	clone: function() {
+		return new GradientStop(this._color.clone(), this._offset);
+	},
+
+	_serialize: function(options, dictionary) {
+		var color = this._color,
+			offset = this._offset;
+		return Base.serialize(offset == null ? [color] : [color, offset],
+				options, true, dictionary);
+	},
+
+	_changed: function() {
+		if (this._owner)
+			this._owner._changed(65);
+	},
+
+	getOffset: function() {
+		return this._offset;
+	},
+
+	setOffset: function(offset) {
+		this._offset = offset;
+		this._changed();
+	},
+
+	getRampPoint: '#getOffset',
+	setRampPoint: '#setOffset',
+
+	getColor: function() {
+		return this._color;
+	},
+
+	setColor: function() {
+		var color = Color.read(arguments, 0, { clone: true });
+		if (color)
+			color._owner = this;
+		this._color = color;
+		this._changed();
+	},
+
+	equals: function(stop) {
+		return stop === this || stop && this._class === stop._class
+				&& this._color.equals(stop._color)
+				&& this._offset == stop._offset
+				|| false;
+	}
+});
+
+var Style = Base.extend(new function() {
+	var itemDefaults = {
+		fillColor: null,
+		fillRule: 'nonzero',
+		strokeColor: null,
+		strokeWidth: 1,
+		strokeCap: 'butt',
+		strokeJoin: 'miter',
+		strokeScaling: true,
+		miterLimit: 10,
+		dashOffset: 0,
+		dashArray: [],
+		shadowColor: null,
+		shadowBlur: 0,
+		shadowOffset: new Point(),
+		selectedColor: null
+	},
+	groupDefaults = Base.set({}, itemDefaults, {
+		fontFamily: 'sans-serif',
+		fontWeight: 'normal',
+		fontSize: 12,
+		leading: null,
+		justification: 'left'
+	}),
+	textDefaults = Base.set({}, groupDefaults, {
+		fillColor: new Color()
+	}),
+	flags = {
+		strokeWidth: 97,
+		strokeCap: 97,
+		strokeJoin: 97,
+		strokeScaling: 105,
+		miterLimit: 97,
+		fontFamily: 9,
+		fontWeight: 9,
+		fontSize: 9,
+		font: 9,
+		leading: 9,
+		justification: 9
+	},
+	item = {
+		beans: true
+	},
+	fields = {
+		_class: 'Style',
+		beans: true,
+
+		initialize: function Style(style, owner, project) {
+			this._values = {};
+			this._owner = owner;
+			this._project = owner && owner._project || project || paper.project;
+			this._defaults = !owner || owner instanceof Group ? groupDefaults
+					: owner instanceof TextItem ? textDefaults
+					: itemDefaults;
+			if (style)
+				this.set(style);
+		}
+	};
+
+	Base.each(groupDefaults, function(value, key) {
+		var isColor = /Color$/.test(key),
+			isPoint = key === 'shadowOffset',
+			part = Base.capitalize(key),
+			flag = flags[key],
+			set = 'set' + part,
+			get = 'get' + part;
+
+		fields[set] = function(value) {
+			var owner = this._owner,
+				children = owner && owner._children;
+			if (children && children.length > 0
+					&& !(owner instanceof CompoundPath)) {
+				for (var i = 0, l = children.length; i < l; i++)
+					children[i]._style[set](value);
+			} else if (key in this._defaults) {
+				var old = this._values[key];
+				if (old !== value) {
+					if (isColor) {
+						if (old && old._owner !== undefined)
+							old._owner = undefined;
+						if (value && value.constructor === Color) {
+							if (value._owner)
+								value = value.clone();
+							value._owner = owner;
+						}
+					}
+					this._values[key] = value;
+					if (owner)
+						owner._changed(flag || 65);
+				}
+			}
+		};
+
+		fields[get] = function(_dontMerge) {
+			var owner = this._owner,
+				children = owner && owner._children,
+				value;
+			if (key in this._defaults && (!children || children.length === 0
+					|| _dontMerge || owner instanceof CompoundPath)) {
+				var value = this._values[key];
+				if (value === undefined) {
+					value = this._defaults[key];
+					if (value && value.clone)
+						value = value.clone();
+				} else {
+					var ctor = isColor ? Color : isPoint ? Point : null;
+					if (ctor && !(value && value.constructor === ctor)) {
+						this._values[key] = value = ctor.read([value], 0,
+								{ readNull: true, clone: true });
+						if (value && isColor)
+							value._owner = owner;
+					}
+				}
+			} else if (children) {
+				for (var i = 0, l = children.length; i < l; i++) {
+					var childValue = children[i]._style[get]();
+					if (i === 0) {
+						value = childValue;
+					} else if (!Base.equals(value, childValue)) {
+						return undefined;
+					}
+				}
+			}
+			return value;
+		};
+
+		item[get] = function(_dontMerge) {
+			return this._style[get](_dontMerge);
+		};
+
+		item[set] = function(value) {
+			this._style[set](value);
+		};
+	});
+
+	Base.each({
+		Font: 'FontFamily',
+		WindingRule: 'FillRule'
+	}, function(value, key) {
+		var get = 'get' + key,
+			set = 'set' + key;
+		fields[get] = item[get] = '#get' + value;
+		fields[set] = item[set] = '#set' + value;
+	});
+
+	Item.inject(item);
+	return fields;
+}, {
+	set: function(style) {
+		var isStyle = style instanceof Style,
+			values = isStyle ? style._values : style;
+		if (values) {
+			for (var key in values) {
+				if (key in this._defaults) {
+					var value = values[key];
+					this[key] = value && isStyle && value.clone
+							? value.clone() : value;
+				}
+			}
+		}
+	},
+
+	equals: function(style) {
+		return style === this || style && this._class === style._class
+				&& Base.equals(this._values, style._values)
+				|| false;
+	},
+
+	hasFill: function() {
+		var color = this.getFillColor();
+		return !!color && color.alpha > 0;
+	},
+
+	hasStroke: function() {
+		var color = this.getStrokeColor();
+		return !!color && color.alpha > 0 && this.getStrokeWidth() > 0;
+	},
+
+	hasShadow: function() {
+		var color = this.getShadowColor();
+		return !!color && color.alpha > 0 && (this.getShadowBlur() > 0
+				|| !this.getShadowOffset().isZero());
+	},
+
+	getView: function() {
+		return this._project._view;
+	},
+
+	getFontStyle: function() {
+		var fontSize = this.getFontSize();
+		return this.getFontWeight()
+				+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')
+				+ this.getFontFamily();
+	},
+
+	getFont: '#getFontFamily',
+	setFont: '#setFontFamily',
+
+	getLeading: function getLeading() {
+		var leading = getLeading.base.call(this),
+			fontSize = this.getFontSize();
+		if (/pt|em|%|px/.test(fontSize))
+			fontSize = this.getView().getPixelSize(fontSize);
+		return leading != null ? leading : fontSize * 1.2;
+	}
+
+});
+
+var DomElement = new function() {
+	function handlePrefix(el, name, set, value) {
+		var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],
+			suffix = name[0].toUpperCase() + name.substring(1);
+		for (var i = 0; i < 6; i++) {
+			var prefix = prefixes[i],
+				key = prefix ? prefix + suffix : name;
+			if (key in el) {
+				if (set) {
+					el[key] = value;
+				} else {
+					return el[key];
+				}
+				break;
+			}
+		}
+	}
+
+	return {
+		getStyles: function(el) {
+			var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
+				view = doc && doc.defaultView;
+			return view && view.getComputedStyle(el, '');
+		},
+
+		getBounds: function(el, viewport) {
+			var doc = el.ownerDocument,
+				body = doc.body,
+				html = doc.documentElement,
+				rect;
+			try {
+				rect = el.getBoundingClientRect();
+			} catch (e) {
+				rect = { left: 0, top: 0, width: 0, height: 0 };
+			}
+			var x = rect.left - (html.clientLeft || body.clientLeft || 0),
+				y = rect.top - (html.clientTop || body.clientTop || 0);
+			if (!viewport) {
+				var view = doc.defaultView;
+				x += view.pageXOffset || html.scrollLeft || body.scrollLeft;
+				y += view.pageYOffset || html.scrollTop || body.scrollTop;
+			}
+			return new Rectangle(x, y, rect.width, rect.height);
+		},
+
+		getViewportBounds: function(el) {
+			var doc = el.ownerDocument,
+				view = doc.defaultView,
+				html = doc.documentElement;
+			return new Rectangle(0, 0,
+				view.innerWidth || html.clientWidth,
+				view.innerHeight || html.clientHeight
+			);
+		},
+
+		getOffset: function(el, viewport) {
+			return DomElement.getBounds(el, viewport).getPoint();
+		},
+
+		getSize: function(el) {
+			return DomElement.getBounds(el, true).getSize();
+		},
+
+		isInvisible: function(el) {
+			return DomElement.getSize(el).equals(new Size(0, 0));
+		},
+
+		isInView: function(el) {
+			return !DomElement.isInvisible(el)
+					&& DomElement.getViewportBounds(el).intersects(
+						DomElement.getBounds(el, true));
+		},
+
+		isInserted: function(el) {
+			return document.body.contains(el);
+		},
+
+		getPrefixed: function(el, name) {
+			return el && handlePrefix(el, name);
+		},
+
+		setPrefixed: function(el, name, value) {
+			if (typeof name === 'object') {
+				for (var key in name)
+					handlePrefix(el, key, true, name[key]);
+			} else {
+				handlePrefix(el, name, true, value);
+			}
+		}
+	};
+};
+
+var DomEvent = {
+	add: function(el, events) {
+		if (el) {
+			for (var type in events) {
+				var func = events[type],
+					parts = type.split(/[\s,]+/g);
+				for (var i = 0, l = parts.length; i < l; i++)
+					el.addEventListener(parts[i], func, false);
+			}
+		}
+	},
+
+	remove: function(el, events) {
+		if (el) {
+			for (var type in events) {
+				var func = events[type],
+					parts = type.split(/[\s,]+/g);
+				for (var i = 0, l = parts.length; i < l; i++)
+					el.removeEventListener(parts[i], func, false);
+			}
+		}
+	},
+
+	getPoint: function(event) {
+		var pos = event.targetTouches
+				? event.targetTouches.length
+					? event.targetTouches[0]
+					: event.changedTouches[0]
+				: event;
+		return new Point(
+			pos.pageX || pos.clientX + document.documentElement.scrollLeft,
+			pos.pageY || pos.clientY + document.documentElement.scrollTop
+		);
+	},
+
+	getTarget: function(event) {
+		return event.target || event.srcElement;
+	},
+
+	getRelatedTarget: function(event) {
+		return event.relatedTarget || event.toElement;
+	},
+
+	getOffset: function(event, target) {
+		return DomEvent.getPoint(event).subtract(DomElement.getOffset(
+				target || DomEvent.getTarget(event)));
+	}
+};
+
+DomEvent.requestAnimationFrame = new function() {
+	var nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),
+		requested = false,
+		callbacks = [],
+		timer;
+
+	function handleCallbacks() {
+		var functions = callbacks;
+		callbacks = [];
+		for (var i = 0, l = functions.length; i < l; i++)
+			functions[i]();
+		requested = nativeRequest && callbacks.length;
+		if (requested)
+			nativeRequest(handleCallbacks);
+	}
+
+	return function(callback) {
+		callbacks.push(callback);
+		if (nativeRequest) {
+			if (!requested) {
+				nativeRequest(handleCallbacks);
+				requested = true;
+			}
+		} else if (!timer) {
+			timer = setInterval(handleCallbacks, 1000 / 60);
+		}
+	};
+};
+
+var View = Base.extend(Emitter, {
+	_class: 'View',
+
+	initialize: function View(project, element) {
+
+		function getSize(name) {
+			return element[name] || parseInt(element.getAttribute(name), 10);
+		}
+
+		function getCanvasSize() {
+			var size = DomElement.getSize(element);
+			return size.isNaN() || size.isZero()
+					? new Size(getSize('width'), getSize('height'))
+					: size;
+		}
+
+		var size;
+		if (window && element) {
+			this._id = element.getAttribute('id');
+			if (this._id == null)
+				element.setAttribute('id', this._id = 'view-' + View._id++);
+			DomEvent.add(element, this._viewEvents);
+			var none = 'none';
+			DomElement.setPrefixed(element.style, {
+				userDrag: none,
+				userSelect: none,
+				touchCallout: none,
+				contentZooming: none,
+				tapHighlightColor: 'rgba(0,0,0,0)'
+			});
+
+			if (PaperScope.hasAttribute(element, 'resize')) {
+				var that = this;
+				DomEvent.add(window, this._windowEvents = {
+					resize: function() {
+						that.setViewSize(getCanvasSize());
+					}
+				});
+			}
+
+			size = getCanvasSize();
+
+			if (PaperScope.hasAttribute(element, 'stats')
+					&& typeof Stats !== 'undefined') {
+				this._stats = new Stats();
+				var stats = this._stats.domElement,
+					style = stats.style,
+					offset = DomElement.getOffset(element);
+				style.position = 'absolute';
+				style.left = offset.x + 'px';
+				style.top = offset.y + 'px';
+				document.body.appendChild(stats);
+			}
+		} else {
+			size = new Size(element);
+			element = null;
+		}
+		this._project = project;
+		this._scope = project._scope;
+		this._element = element;
+		if (!this._pixelRatio)
+			this._pixelRatio = window && window.devicePixelRatio || 1;
+		this._setElementSize(size.width, size.height);
+		this._viewSize = size;
+		View._views.push(this);
+		View._viewsById[this._id] = this;
+		(this._matrix = new Matrix())._owner = this;
+		this._zoom = 1;
+		if (!View._focused)
+			View._focused = this;
+		this._frameItems = {};
+		this._frameItemCount = 0;
+		this._itemEvents = { native: {}, virtual: {} };
+		this._autoUpdate = !paper.agent.node;
+		this._needsUpdate = false;
+	},
+
+	remove: function() {
+		if (!this._project)
+			return false;
+		if (View._focused === this)
+			View._focused = null;
+		View._views.splice(View._views.indexOf(this), 1);
+		delete View._viewsById[this._id];
+		var project = this._project;
+		if (project._view === this)
+			project._view = null;
+		DomEvent.remove(this._element, this._viewEvents);
+		DomEvent.remove(window, this._windowEvents);
+		this._element = this._project = null;
+		this.off('frame');
+		this._animate = false;
+		this._frameItems = {};
+		return true;
+	},
+
+	_events: Base.each(
+		Item._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),
+		function(name) {
+			this[name] = {};
+		}, {
+			onFrame: {
+				install: function() {
+					this.play();
+				},
+
+				uninstall: function() {
+					this.pause();
+				}
+			}
+		}
+	),
+
+	_animate: false,
+	_time: 0,
+	_count: 0,
+
+	getAutoUpdate: function() {
+		return this._autoUpdate;
+	},
+
+	setAutoUpdate: function(autoUpdate) {
+		this._autoUpdate = autoUpdate;
+		if (autoUpdate)
+			this.requestUpdate();
+	},
+
+	update: function() {
+	},
+
+	draw: function() {
+		this.update();
+	},
+
+	requestUpdate: function() {
+		if (!this._requested) {
+			var that = this;
+			DomEvent.requestAnimationFrame(function() {
+				that._requested = false;
+				if (that._animate) {
+					that.requestUpdate();
+					var element = that._element;
+					if ((!DomElement.getPrefixed(document, 'hidden')
+							|| PaperScope.getAttribute(element, 'keepalive')
+								=== 'true') && DomElement.isInView(element)) {
+						that._handleFrame();
+					}
+				}
+				if (that._autoUpdate)
+					that.update();
+			});
+			this._requested = true;
+		}
+	},
+
+	play: function() {
+		this._animate = true;
+		this.requestUpdate();
+	},
+
+	pause: function() {
+		this._animate = false;
+	},
+
+	_handleFrame: function() {
+		paper = this._scope;
+		var now = Date.now() / 1000,
+			delta = this._last ? now - this._last : 0;
+		this._last = now;
+		this.emit('frame', new Base({
+			delta: delta,
+			time: this._time += delta,
+			count: this._count++
+		}));
+		if (this._stats)
+			this._stats.update();
+	},
+
+	_animateItem: function(item, animate) {
+		var items = this._frameItems;
+		if (animate) {
+			items[item._id] = {
+				item: item,
+				time: 0,
+				count: 0
+			};
+			if (++this._frameItemCount === 1)
+				this.on('frame', this._handleFrameItems);
+		} else {
+			delete items[item._id];
+			if (--this._frameItemCount === 0) {
+				this.off('frame', this._handleFrameItems);
+			}
+		}
+	},
+
+	_handleFrameItems: function(event) {
+		for (var i in this._frameItems) {
+			var entry = this._frameItems[i];
+			entry.item.emit('frame', new Base(event, {
+				time: entry.time += event.delta,
+				count: entry.count++
+			}));
+		}
+	},
+
+	_changed: function() {
+		this._project._changed(2049);
+		this._bounds = null;
+	},
+
+	getElement: function() {
+		return this._element;
+	},
+
+	getPixelRatio: function() {
+		return this._pixelRatio;
+	},
+
+	getResolution: function() {
+		return this._pixelRatio * 72;
+	},
+
+	getViewSize: function() {
+		var size = this._viewSize;
+		return new LinkedSize(size.width, size.height, this, 'setViewSize');
+	},
+
+	setViewSize: function() {
+		var size = Size.read(arguments),
+			width = size.width,
+			height = size.height,
+			delta = size.subtract(this._viewSize);
+		if (delta.isZero())
+			return;
+		this._setElementSize(width, height);
+		this._viewSize.set(width, height);
+		this.emit('resize', {
+			size: size,
+			delta: delta
+		});
+		this._changed();
+		if (this._autoUpdate)
+			this.requestUpdate();
+	},
+
+	_setElementSize: function(width, height) {
+		var element = this._element;
+		if (element) {
+			if (element.width !== width)
+				element.width = width;
+			if (element.height !== height)
+				element.height = height;
+		}
+	},
+
+	getBounds: function() {
+		if (!this._bounds)
+			this._bounds = this._matrix.inverted()._transformBounds(
+					new Rectangle(new Point(), this._viewSize));
+		return this._bounds;
+	},
+
+	getSize: function() {
+		return this.getBounds().getSize();
+	},
+
+	getCenter: function() {
+		return this.getBounds().getCenter();
+	},
+
+	setCenter: function() {
+		var center = Point.read(arguments);
+		this.translate(this.getCenter().subtract(center));
+	},
+
+	getZoom: function() {
+		return this._zoom;
+	},
+
+	setZoom: function(zoom) {
+		this.transform(new Matrix().scale(zoom / this._zoom,
+			this.getCenter()));
+		this._zoom = zoom;
+	},
+
+	getMatrix: function() {
+		return this._matrix;
+	},
+
+	setMatrix: function() {
+		var matrix = this._matrix;
+		matrix.initialize.apply(matrix, arguments);
+	},
+
+	isVisible: function() {
+		return DomElement.isInView(this._element);
+	},
+
+	isInserted: function() {
+		return DomElement.isInserted(this._element);
+	},
+
+	getPixelSize: function(size) {
+		var element = this._element,
+			pixels;
+		if (element) {
+			var parent = element.parentNode,
+				temp = document.createElement('div');
+			temp.style.fontSize = size;
+			parent.appendChild(temp);
+			pixels = parseFloat(DomElement.getStyles(temp).fontSize);
+			parent.removeChild(temp);
+		} else {
+			pixels = parseFloat(pixels);
+		}
+		return pixels;
+	},
+
+	getTextWidth: function(font, lines) {
+		return 0;
+	}
+}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
+	var rotate = key === 'rotate';
+	this[key] = function() {
+		var value = (rotate ? Base : Point).read(arguments),
+			center = Point.read(arguments, 0, { readNull: true });
+		return this.transform(new Matrix()[key](value,
+				center || this.getCenter(true)));
+	};
+}, {
+	translate: function() {
+		var mx = new Matrix();
+		return this.transform(mx.translate.apply(mx, arguments));
+	},
+
+	transform: function(matrix) {
+		this._matrix.append(matrix);
+	},
+
+	scrollBy: function() {
+		this.translate(Point.read(arguments).negate());
+	}
+}), {
+
+	projectToView: function() {
+		return this._matrix._transformPoint(Point.read(arguments));
+	},
+
+	viewToProject: function() {
+		return this._matrix._inverseTransform(Point.read(arguments));
+	},
+
+	getEventPoint: function(event) {
+		return this.viewToProject(DomEvent.getOffset(event, this._element));
+	},
+
+}, {
+	statics: {
+		_views: [],
+		_viewsById: {},
+		_id: 0,
+
+		create: function(project, element) {
+			if (document && typeof element === 'string')
+				element = document.getElementById(element);
+			var ctor = window ? CanvasView : View;
+			return new ctor(project, element);
+		}
+	}
+},
+new function() {
+	if (!window)
+		return;
+	var prevFocus,
+		tempFocus,
+		dragging = false,
+		mouseDown = false;
+
+	function getView(event) {
+		var target = DomEvent.getTarget(event);
+		return target.getAttribute && View._viewsById[
+				target.getAttribute('id')];
+	}
+
+	function updateFocus() {
+		var view = View._focused;
+		if (!view || !view.isVisible()) {
+			for (var i = 0, l = View._views.length; i < l; i++) {
+				if ((view = View._views[i]).isVisible()) {
+					View._focused = tempFocus = view;
+					break;
+				}
+			}
+		}
+	}
+
+	function handleMouseMove(view, event, point) {
+		view._handleMouseEvent('mousemove', event, point);
+	}
+
+	var navigator = window.navigator,
+		mousedown, mousemove, mouseup;
+	if (navigator.pointerEnabled || navigator.msPointerEnabled) {
+		mousedown = 'pointerdown MSPointerDown';
+		mousemove = 'pointermove MSPointerMove';
+		mouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';
+	} else {
+		mousedown = 'touchstart';
+		mousemove = 'touchmove';
+		mouseup = 'touchend touchcancel';
+		if (!('ontouchstart' in window && navigator.userAgent.match(
+				/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {
+			mousedown += ' mousedown';
+			mousemove += ' mousemove';
+			mouseup += ' mouseup';
+		}
+	}
+
+	var viewEvents = {},
+		docEvents = {
+			mouseout: function(event) {
+				var view = View._focused,
+					target = DomEvent.getRelatedTarget(event);
+				if (view && (!target || target.nodeName === 'HTML')) {
+					var offset = DomEvent.getOffset(event, view._element),
+						x = offset.x,
+						abs = Math.abs,
+						ax = abs(x),
+						max = 1 << 25,
+						diff = ax - max;
+					offset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;
+					handleMouseMove(view, event, view.viewToProject(offset));
+				}
+			},
+
+			scroll: updateFocus
+		};
+
+	viewEvents[mousedown] = function(event) {
+		var view = View._focused = getView(event);
+		if (!dragging) {
+			dragging = true;
+			view._handleMouseEvent('mousedown', event);
+		}
+	};
+
+	docEvents[mousemove] = function(event) {
+		var view = View._focused;
+		if (!mouseDown) {
+			var target = getView(event);
+			if (target) {
+				if (view !== target) {
+					if (view)
+						handleMouseMove(view, event);
+					if (!prevFocus)
+						prevFocus = view;
+					view = View._focused = tempFocus = target;
+				}
+			} else if (tempFocus && tempFocus === view) {
+				if (prevFocus && !prevFocus.isInserted())
+					prevFocus = null;
+				view = View._focused = prevFocus;
+				prevFocus = null;
+				updateFocus();
+			}
+		}
+		if (view)
+			handleMouseMove(view, event);
+	};
+
+	docEvents[mousedown] = function() {
+		mouseDown = true;
+	};
+
+	docEvents[mouseup] = function(event) {
+		var view = View._focused;
+		if (view && dragging)
+			view._handleMouseEvent('mouseup', event);
+		mouseDown = dragging = false;
+	};
+
+	DomEvent.add(document, docEvents);
+
+	DomEvent.add(window, {
+		load: updateFocus
+	});
+
+	var called = false,
+		prevented = false,
+		fallbacks = {
+			doubleclick: 'click',
+			mousedrag: 'mousemove'
+		},
+		wasInView = false,
+		overView,
+		downPoint,
+		lastPoint,
+		downItem,
+		overItem,
+		dragItem,
+		clickItem,
+		clickTime,
+		dblClick;
+
+	function emitMouseEvent(obj, target, type, event, point, prevPoint,
+			stopItem) {
+		var stopped = false,
+			mouseEvent;
+
+		function emit(obj, type) {
+			if (obj.responds(type)) {
+				if (!mouseEvent) {
+					mouseEvent = new MouseEvent(type, event, point,
+							target || obj,
+							prevPoint ? point.subtract(prevPoint) : null);
+				}
+				if (obj.emit(type, mouseEvent)) {
+					called = true;
+					if (mouseEvent.prevented)
+						prevented = true;
+					if (mouseEvent.stopped)
+						return stopped = true;
+				}
+			} else {
+				var fallback = fallbacks[type];
+				if (fallback)
+					return emit(obj, fallback);
+			}
+		}
+
+		while (obj && obj !== stopItem) {
+			if (emit(obj, type))
+				break;
+			obj = obj._parent;
+		}
+		return stopped;
+	}
+
+	function emitMouseEvents(view, hitItem, type, event, point, prevPoint) {
+		view._project.removeOn(type);
+		prevented = called = false;
+		return (dragItem && emitMouseEvent(dragItem, null, type, event,
+					point, prevPoint)
+			|| hitItem && hitItem !== dragItem
+				&& !hitItem.isDescendant(dragItem)
+				&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
+					point, prevPoint, dragItem)
+			|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
+					point, prevPoint));
+	}
+
+	var itemEventsMap = {
+		mousedown: {
+			mousedown: 1,
+			mousedrag: 1,
+			click: 1,
+			doubleclick: 1
+		},
+		mouseup: {
+			mouseup: 1,
+			mousedrag: 1,
+			click: 1,
+			doubleclick: 1
+		},
+		mousemove: {
+			mousedrag: 1,
+			mousemove: 1,
+			mouseenter: 1,
+			mouseleave: 1
+		}
+	};
+
+	return {
+		_viewEvents: viewEvents,
+
+		_handleMouseEvent: function(type, event, point) {
+			var itemEvents = this._itemEvents,
+				hitItems = itemEvents.native[type],
+				nativeMove = type === 'mousemove',
+				tool = this._scope.tool,
+				view = this;
+
+			function responds(type) {
+				return itemEvents.virtual[type] || view.responds(type)
+						|| tool && tool.responds(type);
+			}
+
+			if (nativeMove && dragging && responds('mousedrag'))
+				type = 'mousedrag';
+			if (!point)
+				point = this.getEventPoint(event);
+
+			var inView = this.getBounds().contains(point),
+				hit = hitItems && inView && view._project.hitTest(point, {
+					tolerance: 0,
+					fill: true,
+					stroke: true
+				}),
+				hitItem = hit && hit.item || null,
+				handle = false,
+				mouse = {};
+			mouse[type.substr(5)] = true;
+
+			if (hitItems && hitItem !== overItem) {
+				if (overItem) {
+					emitMouseEvent(overItem, null, 'mouseleave', event, point);
+				}
+				if (hitItem) {
+					emitMouseEvent(hitItem, null, 'mouseenter', event, point);
+				}
+				overItem = hitItem;
+			}
+			if (wasInView ^ inView) {
+				emitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',
+						event, point);
+				overView = inView ? this : null;
+				handle = true;
+			}
+			if ((inView || mouse.drag) && !point.equals(lastPoint)) {
+				emitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',
+						event, point, lastPoint);
+				handle = true;
+			}
+			wasInView = inView;
+			if (mouse.down && inView || mouse.up && downPoint) {
+				emitMouseEvents(this, hitItem, type, event, point, downPoint);
+				if (mouse.down) {
+					dblClick = hitItem === clickItem
+						&& (Date.now() - clickTime < 300);
+					downItem = clickItem = hitItem;
+					dragItem = !prevented && hitItem;
+					downPoint = point;
+				} else if (mouse.up) {
+					if (!prevented && hitItem === downItem) {
+						clickTime = Date.now();
+						emitMouseEvents(this, hitItem, dblClick ? 'doubleclick'
+								: 'click', event, point, downPoint);
+						dblClick = false;
+					}
+					downItem = dragItem = null;
+				}
+				wasInView = false;
+				handle = true;
+			}
+			lastPoint = point;
+			if (handle && tool) {
+				called = tool._handleMouseEvent(type, event, point, mouse)
+					|| called;
+			}
+
+			if (called && !mouse.move || mouse.down && responds('mouseup'))
+				event.preventDefault();
+		},
+
+		_handleKeyEvent: function(type, event, key, character) {
+			var scope = this._scope,
+				tool = scope.tool,
+				keyEvent;
+
+			function emit(obj) {
+				if (obj.responds(type)) {
+					paper = scope;
+					obj.emit(type, keyEvent = keyEvent
+							|| new KeyEvent(type, event, key, character));
+				}
+			}
+
+			if (this.isVisible()) {
+				emit(this);
+				if (tool && tool.responds(type))
+					emit(tool);
+			}
+		},
+
+		_countItemEvent: function(type, sign) {
+			var itemEvents = this._itemEvents,
+				native = itemEvents.native,
+				virtual = itemEvents.virtual;
+			for (var key in itemEventsMap) {
+				native[key] = (native[key] || 0)
+						+ (itemEventsMap[key][type] || 0) * sign;
+			}
+			virtual[type] = (virtual[type] || 0) + sign;
+		},
+
+		statics: {
+			updateFocus: updateFocus
+		}
+	};
+});
+
+var CanvasView = View.extend({
+	_class: 'CanvasView',
+
+	initialize: function CanvasView(project, canvas) {
+		if (!(canvas instanceof window.HTMLCanvasElement)) {
+			var size = Size.read(arguments, 1);
+			if (size.isZero())
+				throw new Error(
+						'Cannot create CanvasView with the provided argument: '
+						+ [].slice.call(arguments, 1));
+			canvas = CanvasProvider.getCanvas(size);
+		}
+		var ctx = this._context = canvas.getContext('2d');
+		ctx.save();
+		this._pixelRatio = 1;
+		if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {
+			var deviceRatio = window.devicePixelRatio || 1,
+				backingStoreRatio = DomElement.getPrefixed(ctx,
+						'backingStorePixelRatio') || 1;
+			this._pixelRatio = deviceRatio / backingStoreRatio;
+		}
+		View.call(this, project, canvas);
+		this._needsUpdate = true;
+	},
+
+	remove: function remove() {
+		this._context.restore();
+		return remove.base.call(this);
+	},
+
+	_setElementSize: function _setElementSize(width, height) {
+		var pixelRatio = this._pixelRatio;
+		_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);
+		if (pixelRatio !== 1) {
+			var element = this._element,
+				ctx = this._context;
+			if (!PaperScope.hasAttribute(element, 'resize')) {
+				var style = element.style;
+				style.width = width + 'px';
+				style.height = height + 'px';
+			}
+			ctx.restore();
+			ctx.save();
+			ctx.scale(pixelRatio, pixelRatio);
+		}
+	},
+
+	getPixelSize: function getPixelSize(size) {
+		var agent = paper.agent,
+			pixels;
+		if (agent && agent.firefox) {
+			pixels = getPixelSize.base.call(this, size);
+		} else {
+			var ctx = this._context,
+				prevFont = ctx.font;
+			ctx.font = size + ' serif';
+			pixels = parseFloat(ctx.font);
+			ctx.font = prevFont;
+		}
+		return pixels;
+	},
+
+	getTextWidth: function(font, lines) {
+		var ctx = this._context,
+			prevFont = ctx.font,
+			width = 0;
+		ctx.font = font;
+		for (var i = 0, l = lines.length; i < l; i++)
+			width = Math.max(width, ctx.measureText(lines[i]).width);
+		ctx.font = prevFont;
+		return width;
+	},
+
+	update: function() {
+		if (!this._needsUpdate)
+			return false;
+		var project = this._project,
+			ctx = this._context,
+			size = this._viewSize;
+		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
+		if (project)
+			project.draw(ctx, this._matrix, this._pixelRatio);
+		this._needsUpdate = false;
+		return true;
+	}
+});
+
+var Event = Base.extend({
+	_class: 'Event',
+
+	initialize: function Event(event) {
+		this.event = event;
+		this.type = event && event.type;
+	},
+
+	prevented: false,
+	stopped: false,
+
+	preventDefault: function() {
+		this.prevented = true;
+		this.event.preventDefault();
+	},
+
+	stopPropagation: function() {
+		this.stopped = true;
+		this.event.stopPropagation();
+	},
+
+	stop: function() {
+		this.stopPropagation();
+		this.preventDefault();
+	},
+
+	getTimeStamp: function() {
+		return this.event.timeStamp;
+	},
+
+	getModifiers: function() {
+		return Key.modifiers;
+	}
+});
+
+var KeyEvent = Event.extend({
+	_class: 'KeyEvent',
+
+	initialize: function KeyEvent(type, event, key, character) {
+		this.type = type;
+		this.event = event;
+		this.key = key;
+		this.character = character;
+	},
+
+	toString: function() {
+		return "{ type: '" + this.type
+				+ "', key: '" + this.key
+				+ "', character: '" + this.character
+				+ "', modifiers: " + this.getModifiers()
+				+ " }";
+	}
+});
+
+var Key = new function() {
+	var keyLookup = {
+			'\t': 'tab',
+			' ': 'space',
+			'\b': 'backspace',
+			'\x7f': 'delete',
+			'Spacebar': 'space',
+			'Del': 'delete',
+			'Win': 'meta',
+			'Esc': 'escape'
+		},
+
+		charLookup = {
+			'tab': '\t',
+			'space': ' ',
+			'enter': '\r'
+		},
+
+		keyMap = {},
+		charMap = {},
+		metaFixMap,
+		downKey,
+
+		modifiers = new Base({
+			shift: false,
+			control: false,
+			alt: false,
+			meta: false,
+			capsLock: false,
+			space: false
+		}).inject({
+			option: {
+				get: function() {
+					return this.alt;
+				}
+			},
+
+			command: {
+				get: function() {
+					var agent = paper && paper.agent;
+					return agent && agent.mac ? this.meta : this.control;
+				}
+			}
+		});
+
+	function getKey(event) {
+		var key = event.key || event.keyIdentifier;
+		key = /^U\+/.test(key)
+				? String.fromCharCode(parseInt(key.substr(2), 16))
+				: /^Arrow[A-Z]/.test(key) ? key.substr(5)
+				: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
+				: key;
+		return keyLookup[key] ||
+				(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());
+	}
+
+	function handleKey(down, key, character, event) {
+		var type = down ? 'keydown' : 'keyup',
+			view = View._focused,
+			name;
+		keyMap[key] = down;
+		if (down) {
+			charMap[key] = character;
+		} else {
+			delete charMap[key];
+		}
+		if (key.length > 1 && (name = Base.camelize(key)) in modifiers) {
+			modifiers[name] = down;
+			var agent = paper && paper.agent;
+			if (name === 'meta' && agent && agent.mac) {
+				if (down) {
+					metaFixMap = {};
+				} else {
+					for (var k in metaFixMap) {
+						if (k in charMap)
+							handleKey(false, k, metaFixMap[k], event);
+					}
+					metaFixMap = null;
+				}
+			}
+		} else if (down && metaFixMap) {
+			metaFixMap[key] = character;
+		}
+		if (view) {
+			view._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,
+					character);
+		}
+	}
+
+	DomEvent.add(document, {
+		keydown: function(event) {
+			var key = getKey(event),
+				agent = paper && paper.agent;
+			if (key.length > 1 || agent && (agent.chrome && (event.altKey
+						|| agent.mac && event.metaKey
+						|| !agent.mac && event.ctrlKey))) {
+				handleKey(true, key,
+						charLookup[key] || (key.length > 1 ? '' : key), event);
+			} else {
+				downKey = key;
+			}
+		},
+
+		keypress: function(event) {
+			if (downKey) {
+				var key = getKey(event),
+					code = event.charCode,
+					character = code >= 32 ? String.fromCharCode(code)
+						: key.length > 1 ? '' : key;
+				if (key !== downKey) {
+					key = character.toLowerCase();
+				}
+				handleKey(true, key, character, event);
+				downKey = null;
+			}
+		},
+
+		keyup: function(event) {
+			var key = getKey(event);
+			if (key in charMap)
+				handleKey(false, key, charMap[key], event);
+		}
+	});
+
+	DomEvent.add(window, {
+		blur: function(event) {
+			for (var key in charMap)
+				handleKey(false, key, charMap[key], event);
+		}
+	});
+
+	return {
+		modifiers: modifiers,
+
+		isDown: function(key) {
+			return !!keyMap[key];
+		}
+	};
+};
+
+var MouseEvent = Event.extend({
+	_class: 'MouseEvent',
+
+	initialize: function MouseEvent(type, event, point, target, delta) {
+		this.type = type;
+		this.event = event;
+		this.point = point;
+		this.target = target;
+		this.delta = delta;
+	},
+
+	toString: function() {
+		return "{ type: '" + this.type
+				+ "', point: " + this.point
+				+ ', target: ' + this.target
+				+ (this.delta ? ', delta: ' + this.delta : '')
+				+ ', modifiers: ' + this.getModifiers()
+				+ ' }';
+	}
+});
+
+var ToolEvent = Event.extend({
+	_class: 'ToolEvent',
+	_item: null,
+
+	initialize: function ToolEvent(tool, type, event) {
+		this.tool = tool;
+		this.type = type;
+		this.event = event;
+	},
+
+	_choosePoint: function(point, toolPoint) {
+		return point ? point : toolPoint ? toolPoint.clone() : null;
+	},
+
+	getPoint: function() {
+		return this._choosePoint(this._point, this.tool._point);
+	},
+
+	setPoint: function(point) {
+		this._point = point;
+	},
+
+	getLastPoint: function() {
+		return this._choosePoint(this._lastPoint, this.tool._lastPoint);
+	},
+
+	setLastPoint: function(lastPoint) {
+		this._lastPoint = lastPoint;
+	},
+
+	getDownPoint: function() {
+		return this._choosePoint(this._downPoint, this.tool._downPoint);
+	},
+
+	setDownPoint: function(downPoint) {
+		this._downPoint = downPoint;
+	},
+
+	getMiddlePoint: function() {
+		if (!this._middlePoint && this.tool._lastPoint) {
+			return this.tool._point.add(this.tool._lastPoint).divide(2);
+		}
+		return this._middlePoint;
+	},
+
+	setMiddlePoint: function(middlePoint) {
+		this._middlePoint = middlePoint;
+	},
+
+	getDelta: function() {
+		return !this._delta && this.tool._lastPoint
+				? this.tool._point.subtract(this.tool._lastPoint)
+				: this._delta;
+	},
+
+	setDelta: function(delta) {
+		this._delta = delta;
+	},
+
+	getCount: function() {
+		return this.tool[/^mouse(down|up)$/.test(this.type)
+				? '_downCount' : '_moveCount'];
+	},
+
+	setCount: function(count) {
+		this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
+			= count;
+	},
+
+	getItem: function() {
+		if (!this._item) {
+			var result = this.tool._scope.project.hitTest(this.getPoint());
+			if (result) {
+				var item = result.item,
+					parent = item._parent;
+				while (/^(Group|CompoundPath)$/.test(parent._class)) {
+					item = parent;
+					parent = parent._parent;
+				}
+				this._item = item;
+			}
+		}
+		return this._item;
+	},
+
+	setItem: function(item) {
+		this._item = item;
+	},
+
+	toString: function() {
+		return '{ type: ' + this.type
+				+ ', point: ' + this.getPoint()
+				+ ', count: ' + this.getCount()
+				+ ', modifiers: ' + this.getModifiers()
+				+ ' }';
+	}
+});
+
+var Tool = PaperScopeItem.extend({
+	_class: 'Tool',
+	_list: 'tools',
+	_reference: 'tool',
+	_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',
+			'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',
+			'onKeyUp'],
+
+	initialize: function Tool(props) {
+		PaperScopeItem.call(this);
+		this._moveCount = -1;
+		this._downCount = -1;
+		this._set(props);
+	},
+
+	getMinDistance: function() {
+		return this._minDistance;
+	},
+
+	setMinDistance: function(minDistance) {
+		this._minDistance = minDistance;
+		if (minDistance != null && this._maxDistance != null
+				&& minDistance > this._maxDistance) {
+			this._maxDistance = minDistance;
+		}
+	},
+
+	getMaxDistance: function() {
+		return this._maxDistance;
+	},
+
+	setMaxDistance: function(maxDistance) {
+		this._maxDistance = maxDistance;
+		if (this._minDistance != null && maxDistance != null
+				&& maxDistance < this._minDistance) {
+			this._minDistance = maxDistance;
+		}
+	},
+
+	getFixedDistance: function() {
+		return this._minDistance == this._maxDistance
+			? this._minDistance : null;
+	},
+
+	setFixedDistance: function(distance) {
+		this._minDistance = this._maxDistance = distance;
+	},
+
+	_handleMouseEvent: function(type, event, point, mouse) {
+		paper = this._scope;
+		if (mouse.drag && !this.responds(type))
+			type = 'mousemove';
+		var move = mouse.move || mouse.drag,
+			responds = this.responds(type),
+			minDistance = this.minDistance,
+			maxDistance = this.maxDistance,
+			called = false,
+			tool = this;
+		function update(minDistance, maxDistance) {
+			var pt = point,
+				toolPoint = move ? tool._point : (tool._downPoint || pt);
+			if (move) {
+				if (tool._moveCount && pt.equals(toolPoint)) {
+					return false;
+				}
+				if (toolPoint && (minDistance != null || maxDistance != null)) {
+					var vector = pt.subtract(toolPoint),
+						distance = vector.getLength();
+					if (distance < (minDistance || 0))
+						return false;
+					if (maxDistance) {
+						pt = toolPoint.add(vector.normalize(
+								Math.min(distance, maxDistance)));
+					}
+				}
+				tool._moveCount++;
+			}
+			tool._point = pt;
+			tool._lastPoint = toolPoint || pt;
+			if (mouse.down) {
+				tool._moveCount = -1;
+				tool._downPoint = pt;
+				tool._downCount++;
+			}
+			return true;
+		}
+
+		function emit() {
+			if (responds) {
+				called = tool.emit(type, new ToolEvent(tool, type, event))
+						|| called;
+			}
+		}
+
+		if (mouse.down) {
+			update();
+			emit();
+		} else if (mouse.up) {
+			update(null, maxDistance);
+			emit();
+		} else if (responds) {
+			while (update(minDistance, maxDistance))
+				emit();
+		}
+		return called;
+	}
+
+});
+
+var Http = {
+	request: function(options) {
+		var xhr = new window.XMLHttpRequest();
+		xhr.open((options.method || 'get').toUpperCase(), options.url,
+				Base.pick(options.async, true));
+		if (options.mimeType)
+			xhr.overrideMimeType(options.mimeType);
+		xhr.onload = function() {
+			var status = xhr.status;
+			if (status === 0 || status === 200) {
+				if (options.onLoad) {
+					options.onLoad.call(xhr, xhr.responseText);
+				}
+			} else {
+				xhr.onerror();
+			}
+		};
+		xhr.onerror = function() {
+			var status = xhr.status,
+				message = 'Could not load "' + options.url + '" (Status: '
+						+ status + ')';
+			if (options.onError) {
+				options.onError(message, status);
+			} else {
+				throw new Error(message);
+			}
+		};
+		return xhr.send(null);
+	}
+};
+
+var CanvasProvider = {
+	canvases: [],
+
+	getCanvas: function(width, height) {
+		if (!window)
+			return null;
+		var canvas,
+			clear = true;
+		if (typeof width === 'object') {
+			height = width.height;
+			width = width.width;
+		}
+		if (this.canvases.length) {
+			canvas = this.canvases.pop();
+		} else {
+			canvas = document.createElement('canvas');
+			clear = false;
+		}
+		var ctx = canvas.getContext('2d');
+		if (!ctx) {
+			throw new Error('Canvas ' + canvas +
+					' is unable toprovide a 2D context.');
+		}
+		if (canvas.width === width && canvas.height === height) {
+			if (clear)
+				ctx.clearRect(0, 0, width + 1, height + 1);
+		} else {
+			canvas.width = width;
+			canvas.height = height;
+		}
+		ctx.save();
+		return canvas;
+	},
+
+	getContext: function(width, height) {
+		var canvas = this.getCanvas(width, height);
+		return canvas ? canvas.getContext('2d') : null;
+	},
+
+	release: function(obj) {
+		var canvas = obj && obj.canvas ? obj.canvas : obj;
+		if (canvas && canvas.getContext) {
+			canvas.getContext('2d').restore();
+			this.canvases.push(canvas);
+		}
+	}
+};
+
+var BlendMode = new function() {
+	var min = Math.min,
+		max = Math.max,
+		abs = Math.abs,
+		sr, sg, sb, sa,
+		br, bg, bb, ba,
+		dr, dg, db;
+
+	function getLum(r, g, b) {
+		return 0.2989 * r + 0.587 * g + 0.114 * b;
+	}
+
+	function setLum(r, g, b, l) {
+		var d = l - getLum(r, g, b);
+		dr = r + d;
+		dg = g + d;
+		db = b + d;
+		var l = getLum(dr, dg, db),
+			mn = min(dr, dg, db),
+			mx = max(dr, dg, db);
+		if (mn < 0) {
+			var lmn = l - mn;
+			dr = l + (dr - l) * l / lmn;
+			dg = l + (dg - l) * l / lmn;
+			db = l + (db - l) * l / lmn;
+		}
+		if (mx > 255) {
+			var ln = 255 - l,
+				mxl = mx - l;
+			dr = l + (dr - l) * ln / mxl;
+			dg = l + (dg - l) * ln / mxl;
+			db = l + (db - l) * ln / mxl;
+		}
+	}
+
+	function getSat(r, g, b) {
+		return max(r, g, b) - min(r, g, b);
+	}
+
+	function setSat(r, g, b, s) {
+		var col = [r, g, b],
+			mx = max(r, g, b),
+			mn = min(r, g, b),
+			md;
+		mn = mn === r ? 0 : mn === g ? 1 : 2;
+		mx = mx === r ? 0 : mx === g ? 1 : 2;
+		md = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;
+		if (col[mx] > col[mn]) {
+			col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);
+			col[mx] = s;
+		} else {
+			col[md] = col[mx] = 0;
+		}
+		col[mn] = 0;
+		dr = col[0];
+		dg = col[1];
+		db = col[2];
+	}
+
+	var modes = {
+		multiply: function() {
+			dr = br * sr / 255;
+			dg = bg * sg / 255;
+			db = bb * sb / 255;
+		},
+
+		screen: function() {
+			dr = br + sr - (br * sr / 255);
+			dg = bg + sg - (bg * sg / 255);
+			db = bb + sb - (bb * sb / 255);
+		},
+
+		overlay: function() {
+			dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;
+			dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;
+			db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;
+		},
+
+		'soft-light': function() {
+			var t = sr * br / 255;
+			dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;
+			t = sg * bg / 255;
+			dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;
+			t = sb * bb / 255;
+			db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;
+		},
+
+		'hard-light': function() {
+			dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;
+			dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;
+			db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;
+		},
+
+		'color-dodge': function() {
+			dr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));
+			dg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));
+			db = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));
+		},
+
+		'color-burn': function() {
+			dr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);
+			dg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);
+			db = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);
+		},
+
+		darken: function() {
+			dr = br < sr ? br : sr;
+			dg = bg < sg ? bg : sg;
+			db = bb < sb ? bb : sb;
+		},
+
+		lighten: function() {
+			dr = br > sr ? br : sr;
+			dg = bg > sg ? bg : sg;
+			db = bb > sb ? bb : sb;
+		},
+
+		difference: function() {
+			dr = br - sr;
+			if (dr < 0)
+				dr = -dr;
+			dg = bg - sg;
+			if (dg < 0)
+				dg = -dg;
+			db = bb - sb;
+			if (db < 0)
+				db = -db;
+		},
+
+		exclusion: function() {
+			dr = br + sr * (255 - br - br) / 255;
+			dg = bg + sg * (255 - bg - bg) / 255;
+			db = bb + sb * (255 - bb - bb) / 255;
+		},
+
+		hue: function() {
+			setSat(sr, sg, sb, getSat(br, bg, bb));
+			setLum(dr, dg, db, getLum(br, bg, bb));
+		},
+
+		saturation: function() {
+			setSat(br, bg, bb, getSat(sr, sg, sb));
+			setLum(dr, dg, db, getLum(br, bg, bb));
+		},
+
+		luminosity: function() {
+			setLum(br, bg, bb, getLum(sr, sg, sb));
+		},
+
+		color: function() {
+			setLum(sr, sg, sb, getLum(br, bg, bb));
+		},
+
+		add: function() {
+			dr = min(br + sr, 255);
+			dg = min(bg + sg, 255);
+			db = min(bb + sb, 255);
+		},
+
+		subtract: function() {
+			dr = max(br - sr, 0);
+			dg = max(bg - sg, 0);
+			db = max(bb - sb, 0);
+		},
+
+		average: function() {
+			dr = (br + sr) / 2;
+			dg = (bg + sg) / 2;
+			db = (bb + sb) / 2;
+		},
+
+		negation: function() {
+			dr = 255 - abs(255 - sr - br);
+			dg = 255 - abs(255 - sg - bg);
+			db = 255 - abs(255 - sb - bb);
+		}
+	};
+
+	var nativeModes = this.nativeModes = Base.each([
+		'source-over', 'source-in', 'source-out', 'source-atop',
+		'destination-over', 'destination-in', 'destination-out',
+		'destination-atop', 'lighter', 'darker', 'copy', 'xor'
+	], function(mode) {
+		this[mode] = true;
+	}, {});
+
+	var ctx = CanvasProvider.getContext(1, 1);
+	if (ctx) {
+		Base.each(modes, function(func, mode) {
+			var darken = mode === 'darken',
+				ok = false;
+			ctx.save();
+			try {
+				ctx.fillStyle = darken ? '#300' : '#a00';
+				ctx.fillRect(0, 0, 1, 1);
+				ctx.globalCompositeOperation = mode;
+				if (ctx.globalCompositeOperation === mode) {
+					ctx.fillStyle = darken ? '#a00' : '#300';
+					ctx.fillRect(0, 0, 1, 1);
+					ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken
+							? 170 : 51;
+				}
+			} catch (e) {}
+			ctx.restore();
+			nativeModes[mode] = ok;
+		});
+		CanvasProvider.release(ctx);
+	}
+
+	this.process = function(mode, srcContext, dstContext, alpha, offset) {
+		var srcCanvas = srcContext.canvas,
+			normal = mode === 'normal';
+		if (normal || nativeModes[mode]) {
+			dstContext.save();
+			dstContext.setTransform(1, 0, 0, 1, 0, 0);
+			dstContext.globalAlpha = alpha;
+			if (!normal)
+				dstContext.globalCompositeOperation = mode;
+			dstContext.drawImage(srcCanvas, offset.x, offset.y);
+			dstContext.restore();
+		} else {
+			var process = modes[mode];
+			if (!process)
+				return;
+			var dstData = dstContext.getImageData(offset.x, offset.y,
+					srcCanvas.width, srcCanvas.height),
+				dst = dstData.data,
+				src = srcContext.getImageData(0, 0,
+					srcCanvas.width, srcCanvas.height).data;
+			for (var i = 0, l = dst.length; i < l; i += 4) {
+				sr = src[i];
+				br = dst[i];
+				sg = src[i + 1];
+				bg = dst[i + 1];
+				sb = src[i + 2];
+				bb = dst[i + 2];
+				sa = src[i + 3];
+				ba = dst[i + 3];
+				process();
+				var a1 = sa * alpha / 255,
+					a2 = 1 - a1;
+				dst[i] = a1 * dr + a2 * br;
+				dst[i + 1] = a1 * dg + a2 * bg;
+				dst[i + 2] = a1 * db + a2 * bb;
+				dst[i + 3] = sa * alpha + a2 * ba;
+			}
+			dstContext.putImageData(dstData, offset.x, offset.y);
+		}
+	};
+};
+
+var SvgElement = new function() {
+	var svg = 'http://www.w3.org/2000/svg',
+		xmlns = 'http://www.w3.org/2000/xmlns',
+		xlink = 'http://www.w3.org/1999/xlink',
+		attributeNamespace = {
+			href: xlink,
+			xlink: xmlns,
+			xmlns: xmlns + '/',
+			'xmlns:xlink': xmlns + '/'
+		};
+
+	function create(tag, attributes, formatter) {
+		return set(document.createElementNS(svg, tag), attributes, formatter);
+	}
+
+	function get(node, name) {
+		var namespace = attributeNamespace[name],
+			value = namespace
+				? node.getAttributeNS(namespace, name)
+				: node.getAttribute(name);
+		return value === 'null' ? null : value;
+	}
+
+	function set(node, attributes, formatter) {
+		for (var name in attributes) {
+			var value = attributes[name],
+				namespace = attributeNamespace[name];
+			if (typeof value === 'number' && formatter)
+				value = formatter.number(value);
+			if (namespace) {
+				node.setAttributeNS(namespace, name, value);
+			} else {
+				node.setAttribute(name, value);
+			}
+		}
+		return node;
+	}
+
+	return {
+		svg: svg,
+		xmlns: xmlns,
+		xlink: xlink,
+
+		create: create,
+		get: get,
+		set: set
+	};
+};
+
+var SvgStyles = Base.each({
+	fillColor: ['fill', 'color'],
+	fillRule: ['fill-rule', 'string'],
+	strokeColor: ['stroke', 'color'],
+	strokeWidth: ['stroke-width', 'number'],
+	strokeCap: ['stroke-linecap', 'string'],
+	strokeJoin: ['stroke-linejoin', 'string'],
+	strokeScaling: ['vector-effect', 'lookup', {
+		true: 'none',
+		false: 'non-scaling-stroke'
+	}, function(item, value) {
+		return !value
+				&& (item instanceof PathItem
+					|| item instanceof Shape
+					|| item instanceof TextItem);
+	}],
+	miterLimit: ['stroke-miterlimit', 'number'],
+	dashArray: ['stroke-dasharray', 'array'],
+	dashOffset: ['stroke-dashoffset', 'number'],
+	fontFamily: ['font-family', 'string'],
+	fontWeight: ['font-weight', 'string'],
+	fontSize: ['font-size', 'number'],
+	justification: ['text-anchor', 'lookup', {
+		left: 'start',
+		center: 'middle',
+		right: 'end'
+	}],
+	opacity: ['opacity', 'number'],
+	blendMode: ['mix-blend-mode', 'style']
+}, function(entry, key) {
+	var part = Base.capitalize(key),
+		lookup = entry[2];
+	this[key] = {
+		type: entry[1],
+		property: key,
+		attribute: entry[0],
+		toSVG: lookup,
+		fromSVG: lookup && Base.each(lookup, function(value, name) {
+			this[value] = name;
+		}, {}),
+		exportFilter: entry[3],
+		get: 'get' + part,
+		set: 'set' + part
+	};
+}, {});
+
+new function() {
+	var formatter;
+
+	function getTransform(matrix, coordinates, center) {
+		var attrs = new Base(),
+			trans = matrix.getTranslation();
+		if (coordinates) {
+			matrix = matrix._shiftless();
+			var point = matrix._inverseTransform(trans);
+			attrs[center ? 'cx' : 'x'] = point.x;
+			attrs[center ? 'cy' : 'y'] = point.y;
+			trans = null;
+		}
+		if (!matrix.isIdentity()) {
+			var decomposed = matrix.decompose();
+			if (decomposed) {
+				var parts = [],
+					angle = decomposed.rotation,
+					scale = decomposed.scaling,
+					skew = decomposed.skewing;
+				if (trans && !trans.isZero())
+					parts.push('translate(' + formatter.point(trans) + ')');
+				if (angle)
+					parts.push('rotate(' + formatter.number(angle) + ')');
+				if (!Numerical.isZero(scale.x - 1)
+						|| !Numerical.isZero(scale.y - 1))
+					parts.push('scale(' + formatter.point(scale) +')');
+				if (skew && skew.x)
+					parts.push('skewX(' + formatter.number(skew.x) + ')');
+				if (skew && skew.y)
+					parts.push('skewY(' + formatter.number(skew.y) + ')');
+				attrs.transform = parts.join(' ');
+			} else {
+				attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';
+			}
+		}
+		return attrs;
+	}
+
+	function exportGroup(item, options) {
+		var attrs = getTransform(item._matrix),
+			children = item._children;
+		var node = SvgElement.create('g', attrs, formatter);
+		for (var i = 0, l = children.length; i < l; i++) {
+			var child = children[i];
+			var childNode = exportSVG(child, options);
+			if (childNode) {
+				if (child.isClipMask()) {
+					var clip = SvgElement.create('clipPath');
+					clip.appendChild(childNode);
+					setDefinition(child, clip, 'clip');
+					SvgElement.set(node, {
+						'clip-path': 'url(#' + clip.id + ')'
+					});
+				} else {
+					node.appendChild(childNode);
+				}
+			}
+		}
+		return node;
+	}
+
+	function exportRaster(item, options) {
+		var attrs = getTransform(item._matrix, true),
+			size = item.getSize(),
+			image = item.getImage();
+		attrs.x -= size.width / 2;
+		attrs.y -= size.height / 2;
+		attrs.width = size.width;
+		attrs.height = size.height;
+		attrs.href = options.embedImages === false && image && image.src
+				|| item.toDataURL();
+		return SvgElement.create('image', attrs, formatter);
+	}
+
+	function exportPath(item, options) {
+		var matchShapes = options.matchShapes;
+		if (matchShapes) {
+			var shape = item.toShape(false);
+			if (shape)
+				return exportShape(shape, options);
+		}
+		var segments = item._segments,
+			length = segments.length,
+			type,
+			attrs = getTransform(item._matrix);
+		if (matchShapes && length >= 2 && !item.hasHandles()) {
+			if (length > 2) {
+				type = item._closed ? 'polygon' : 'polyline';
+				var parts = [];
+				for(var i = 0; i < length; i++)
+					parts.push(formatter.point(segments[i]._point));
+				attrs.points = parts.join(' ');
+			} else {
+				type = 'line';
+				var start = segments[0]._point,
+					end = segments[1]._point;
+				attrs.set({
+					x1: start.x,
+					y1: start.y,
+					x2: end.x,
+					y2: end.y
+				});
+			}
+		} else {
+			type = 'path';
+			attrs.d = item.getPathData(null, options.precision);
+		}
+		return SvgElement.create(type, attrs, formatter);
+	}
+
+	function exportShape(item) {
+		var type = item._type,
+			radius = item._radius,
+			attrs = getTransform(item._matrix, true, type !== 'rectangle');
+		if (type === 'rectangle') {
+			type = 'rect';
+			var size = item._size,
+				width = size.width,
+				height = size.height;
+			attrs.x -= width / 2;
+			attrs.y -= height / 2;
+			attrs.width = width;
+			attrs.height = height;
+			if (radius.isZero())
+				radius = null;
+		}
+		if (radius) {
+			if (type === 'circle') {
+				attrs.r = radius;
+			} else {
+				attrs.rx = radius.width;
+				attrs.ry = radius.height;
+			}
+		}
+		return SvgElement.create(type, attrs, formatter);
+	}
+
+	function exportCompoundPath(item, options) {
+		var attrs = getTransform(item._matrix);
+		var data = item.getPathData(null, options.precision);
+		if (data)
+			attrs.d = data;
+		return SvgElement.create('path', attrs, formatter);
+	}
+
+	function exportSymbolItem(item, options) {
+		var attrs = getTransform(item._matrix, true),
+			definition = item._definition,
+			node = getDefinition(definition, 'symbol'),
+			definitionItem = definition._item,
+			bounds = definitionItem.getBounds();
+		if (!node) {
+			node = SvgElement.create('symbol', {
+				viewBox: formatter.rectangle(bounds)
+			});
+			node.appendChild(exportSVG(definitionItem, options));
+			setDefinition(definition, node, 'symbol');
+		}
+		attrs.href = '#' + node.id;
+		attrs.x += bounds.x;
+		attrs.y += bounds.y;
+		attrs.width = bounds.width;
+		attrs.height = bounds.height;
+		attrs.overflow = 'visible';
+		return SvgElement.create('use', attrs, formatter);
+	}
+
+	function exportGradient(color) {
+		var gradientNode = getDefinition(color, 'color');
+		if (!gradientNode) {
+			var gradient = color.getGradient(),
+				radial = gradient._radial,
+				origin = color.getOrigin(),
+				destination = color.getDestination(),
+				attrs;
+			if (radial) {
+				attrs = {
+					cx: origin.x,
+					cy: origin.y,
+					r: origin.getDistance(destination)
+				};
+				var highlight = color.getHighlight();
+				if (highlight) {
+					attrs.fx = highlight.x;
+					attrs.fy = highlight.y;
+				}
+			} else {
+				attrs = {
+					x1: origin.x,
+					y1: origin.y,
+					x2: destination.x,
+					y2: destination.y
+				};
+			}
+			attrs.gradientUnits = 'userSpaceOnUse';
+			gradientNode = SvgElement.create((radial ? 'radial' : 'linear')
+					+ 'Gradient', attrs, formatter);
+			var stops = gradient._stops;
+			for (var i = 0, l = stops.length; i < l; i++) {
+				var stop = stops[i],
+					stopColor = stop._color,
+					alpha = stopColor.getAlpha();
+				attrs = {
+					offset: stop._offset || i / (l - 1)
+				};
+				if (stopColor)
+					attrs['stop-color'] = stopColor.toCSS(true);
+				if (alpha < 1)
+					attrs['stop-opacity'] = alpha;
+				gradientNode.appendChild(
+						SvgElement.create('stop', attrs, formatter));
+			}
+			setDefinition(color, gradientNode, 'color');
+		}
+		return 'url(#' + gradientNode.id + ')';
+	}
+
+	function exportText(item) {
+		var node = SvgElement.create('text', getTransform(item._matrix, true),
+				formatter);
+		node.textContent = item._content;
+		return node;
+	}
+
+	var exporters = {
+		Group: exportGroup,
+		Layer: exportGroup,
+		Raster: exportRaster,
+		Path: exportPath,
+		Shape: exportShape,
+		CompoundPath: exportCompoundPath,
+		SymbolItem: exportSymbolItem,
+		PointText: exportText
+	};
+
+	function applyStyle(item, node, isRoot) {
+		var attrs = {},
+			parent = !isRoot && item.getParent(),
+			style = [];
+
+		if (item._name != null)
+			attrs.id = item._name;
+
+		Base.each(SvgStyles, function(entry) {
+			var get = entry.get,
+				type = entry.type,
+				value = item[get]();
+			if (entry.exportFilter
+					? entry.exportFilter(item, value)
+					: !parent || !Base.equals(parent[get](), value)) {
+				if (type === 'color' && value != null) {
+					var alpha = value.getAlpha();
+					if (alpha < 1)
+						attrs[entry.attribute + '-opacity'] = alpha;
+				}
+				if (type === 'style') {
+					style.push(entry.attribute + ': ' + value);
+				} else {
+					attrs[entry.attribute] = value == null ? 'none'
+							: type === 'color' ? value.gradient
+								? exportGradient(value, item)
+								: value.toCSS(true)
+							: type === 'array' ? value.join(',')
+							: type === 'lookup' ? entry.toSVG[value]
+							: value;
+				}
+			}
+		});
+
+		if (style.length)
+			attrs.style = style.join(';');
+
+		if (attrs.opacity === 1)
+			delete attrs.opacity;
+
+		if (!item._visible)
+			attrs.visibility = 'hidden';
+
+		return SvgElement.set(node, attrs, formatter);
+	}
+
+	var definitions;
+	function getDefinition(item, type) {
+		if (!definitions)
+			definitions = { ids: {}, svgs: {} };
+		var id = item._id || item.__id || (item.__id = UID.get('svg'));
+		return item && definitions.svgs[type + '-' + id];
+	}
+
+	function setDefinition(item, node, type) {
+		if (!definitions)
+			getDefinition();
+		var typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;
+		node.id = type + '-' + typeId;
+		definitions.svgs[type + '-' + (item._id || item.__id)] = node;
+	}
+
+	function exportDefinitions(node, options) {
+		var svg = node,
+			defs = null;
+		if (definitions) {
+			svg = node.nodeName.toLowerCase() === 'svg' && node;
+			for (var i in definitions.svgs) {
+				if (!defs) {
+					if (!svg) {
+						svg = SvgElement.create('svg');
+						svg.appendChild(node);
+					}
+					defs = svg.insertBefore(SvgElement.create('defs'),
+							svg.firstChild);
+				}
+				defs.appendChild(definitions.svgs[i]);
+			}
+			definitions = null;
+		}
+		return options.asString
+				? new window.XMLSerializer().serializeToString(svg)
+				: svg;
+	}
+
+	function exportSVG(item, options, isRoot) {
+		var exporter = exporters[item._class],
+			node = exporter && exporter(item, options);
+		if (node) {
+			var onExport = options.onExport;
+			if (onExport)
+				node = onExport(item, node, options) || node;
+			var data = JSON.stringify(item._data);
+			if (data && data !== '{}' && data !== 'null')
+				node.setAttribute('data-paper-data', data);
+		}
+		return node && applyStyle(item, node, isRoot);
+	}
+
+	function setOptions(options) {
+		if (!options)
+			options = {};
+		formatter = new Formatter(options.precision);
+		return options;
+	}
+
+	Item.inject({
+		exportSVG: function(options) {
+			options = setOptions(options);
+			return exportDefinitions(exportSVG(this, options, true), options);
+		}
+	});
+
+	Project.inject({
+		exportSVG: function(options) {
+			options = setOptions(options);
+			var children = this._children,
+				view = this.getView(),
+				bounds = Base.pick(options.bounds, 'view'),
+				mx = options.matrix || bounds === 'view' && view._matrix,
+				matrix = mx && Matrix.read([mx]),
+				rect = bounds === 'view'
+					? new Rectangle([0, 0], view.getViewSize())
+					: bounds === 'content'
+						? Item._getBounds(children, matrix, { stroke: true })
+						: Rectangle.read([bounds], 0, { readNull: true }),
+				attrs = {
+					version: '1.1',
+					xmlns: SvgElement.svg,
+					'xmlns:xlink': SvgElement.xlink,
+				};
+			if (rect) {
+				attrs.width = rect.width;
+				attrs.height = rect.height;
+				if (rect.x || rect.y)
+					attrs.viewBox = formatter.rectangle(rect);
+			}
+			var node = SvgElement.create('svg', attrs, formatter),
+				parent = node;
+			if (matrix && !matrix.isIdentity()) {
+				parent = node.appendChild(SvgElement.create('g',
+						getTransform(matrix), formatter));
+			}
+			for (var i = 0, l = children.length; i < l; i++) {
+				parent.appendChild(exportSVG(children[i], options, true));
+			}
+			return exportDefinitions(node, options);
+		}
+	});
+};
+
+new function() {
+
+	var definitions = {},
+		rootSize;
+
+	function getValue(node, name, isString, allowNull, allowPercent) {
+		var value = SvgElement.get(node, name),
+			res = value == null
+				? allowNull
+					? null
+					: isString ? '' : 0
+				: isString
+					? value
+					: parseFloat(value);
+		return /%\s*$/.test(value)
+			? (res / 100) * (allowPercent ? 1
+				: rootSize[/x|^width/.test(name) ? 'width' : 'height'])
+			: res;
+	}
+
+	function getPoint(node, x, y, allowNull, allowPercent) {
+		x = getValue(node, x || 'x', false, allowNull, allowPercent);
+		y = getValue(node, y || 'y', false, allowNull, allowPercent);
+		return allowNull && (x == null || y == null) ? null
+				: new Point(x, y);
+	}
+
+	function getSize(node, w, h, allowNull, allowPercent) {
+		w = getValue(node, w || 'width', false, allowNull, allowPercent);
+		h = getValue(node, h || 'height', false, allowNull, allowPercent);
+		return allowNull && (w == null || h == null) ? null
+				: new Size(w, h);
+	}
+
+	function convertValue(value, type, lookup) {
+		return value === 'none' ? null
+				: type === 'number' ? parseFloat(value)
+				: type === 'array' ?
+					value ? value.split(/[\s,]+/g).map(parseFloat) : []
+				: type === 'color' ? getDefinition(value) || value
+				: type === 'lookup' ? lookup[value]
+				: value;
+	}
+
+	function importGroup(node, type, options, isRoot) {
+		var nodes = node.childNodes,
+			isClip = type === 'clippath',
+			isDefs = type === 'defs',
+			item = new Group(),
+			project = item._project,
+			currentStyle = project._currentStyle,
+			children = [];
+		if (!isClip && !isDefs) {
+			item = applyAttributes(item, node, isRoot);
+			project._currentStyle = item._style.clone();
+		}
+		if (isRoot) {
+			var defs = node.querySelectorAll('defs');
+			for (var i = 0, l = defs.length; i < l; i++) {
+				importNode(defs[i], options, false);
+			}
+		}
+		for (var i = 0, l = nodes.length; i < l; i++) {
+			var childNode = nodes[i],
+				child;
+			if (childNode.nodeType === 1
+					&& !/^defs$/i.test(childNode.nodeName)
+					&& (child = importNode(childNode, options, false))
+					&& !(child instanceof SymbolDefinition))
+				children.push(child);
+		}
+		item.addChildren(children);
+		if (isClip)
+			item = applyAttributes(item.reduce(), node, isRoot);
+		project._currentStyle = currentStyle;
+		if (isClip || isDefs) {
+			item.remove();
+			item = null;
+		}
+		return item;
+	}
+
+	function importPoly(node, type) {
+		var coords = node.getAttribute('points').match(
+					/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),
+			points = [];
+		for (var i = 0, l = coords.length; i < l; i += 2)
+			points.push(new Point(
+					parseFloat(coords[i]),
+					parseFloat(coords[i + 1])));
+		var path = new Path(points);
+		if (type === 'polygon')
+			path.closePath();
+		return path;
+	}
+
+	function importPath(node) {
+		return PathItem.create(node.getAttribute('d'));
+	}
+
+	function importGradient(node, type) {
+		var id = (getValue(node, 'href', true) || '').substring(1),
+			radial = type === 'radialgradient',
+			gradient;
+		if (id) {
+			gradient = definitions[id].getGradient();
+			if (gradient._radial ^ radial) {
+				gradient = gradient.clone();
+				gradient._radial = radial;
+			}
+		} else {
+			var nodes = node.childNodes,
+				stops = [];
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				var child = nodes[i];
+				if (child.nodeType === 1)
+					stops.push(applyAttributes(new GradientStop(), child));
+			}
+			gradient = new Gradient(stops, radial);
+		}
+		var origin, destination, highlight,
+			scaleToBounds = getValue(node, 'gradientUnits', true) !==
+				'userSpaceOnUse';
+		if (radial) {
+			origin = getPoint(node, 'cx', 'cy', false, scaleToBounds);
+			destination = origin.add(
+					getValue(node, 'r', false, false, scaleToBounds), 0);
+			highlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);
+		} else {
+			origin = getPoint(node, 'x1', 'y1', false, scaleToBounds);
+			destination = getPoint(node, 'x2', 'y2', false, scaleToBounds);
+		}
+		var color = applyAttributes(
+				new Color(gradient, origin, destination, highlight), node);
+		color._scaleToBounds = scaleToBounds;
+		return null;
+	}
+
+	var importers = {
+		'#document': function (node, type, options, isRoot) {
+			var nodes = node.childNodes;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				var child = nodes[i];
+				if (child.nodeType === 1)
+					return importNode(child, options, isRoot);
+			}
+		},
+		g: importGroup,
+		svg: importGroup,
+		clippath: importGroup,
+		polygon: importPoly,
+		polyline: importPoly,
+		path: importPath,
+		lineargradient: importGradient,
+		radialgradient: importGradient,
+
+		image: function (node) {
+			var raster = new Raster(getValue(node, 'href', true));
+			raster.on('load', function() {
+				var size = getSize(node);
+				this.setSize(size);
+				var center = this._matrix._transformPoint(
+						getPoint(node).add(size.divide(2)));
+				this.translate(center);
+			});
+			return raster;
+		},
+
+		symbol: function(node, type, options, isRoot) {
+			return new SymbolDefinition(
+					importGroup(node, type, options, isRoot), true);
+		},
+
+		defs: importGroup,
+
+		use: function(node) {
+			var id = (getValue(node, 'href', true) || '').substring(1),
+				definition = definitions[id],
+				point = getPoint(node);
+			return definition
+					? definition instanceof SymbolDefinition
+						? definition.place(point)
+						: definition.clone().translate(point)
+					: null;
+		},
+
+		circle: function(node) {
+			return new Shape.Circle(
+					getPoint(node, 'cx', 'cy'),
+					getValue(node, 'r'));
+		},
+
+		ellipse: function(node) {
+			return new Shape.Ellipse({
+				center: getPoint(node, 'cx', 'cy'),
+				radius: getSize(node, 'rx', 'ry')
+			});
+		},
+
+		rect: function(node) {
+			return new Shape.Rectangle(new Rectangle(
+						getPoint(node),
+						getSize(node)
+					), getSize(node, 'rx', 'ry'));
+			},
+
+		line: function(node) {
+			return new Path.Line(
+					getPoint(node, 'x1', 'y1'),
+					getPoint(node, 'x2', 'y2'));
+		},
+
+		text: function(node) {
+			var text = new PointText(getPoint(node).add(
+					getPoint(node, 'dx', 'dy')));
+			text.setContent(node.textContent.trim() || '');
+			return text;
+		}
+	};
+
+	function applyTransform(item, value, name, node) {
+		if (item.transform) {
+			var transforms = (node.getAttribute(name) || '').split(/\)\s*/g),
+				matrix = new Matrix();
+			for (var i = 0, l = transforms.length; i < l; i++) {
+				var transform = transforms[i];
+				if (!transform)
+					break;
+				var parts = transform.split(/\(\s*/),
+					command = parts[0],
+					v = parts[1].split(/[\s,]+/g);
+				for (var j = 0, m = v.length; j < m; j++)
+					v[j] = parseFloat(v[j]);
+				switch (command) {
+				case 'matrix':
+					matrix.append(
+							new Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));
+					break;
+				case 'rotate':
+					matrix.rotate(v[0], v[1], v[2]);
+					break;
+				case 'translate':
+					matrix.translate(v[0], v[1]);
+					break;
+				case 'scale':
+					matrix.scale(v);
+					break;
+				case 'skewX':
+					matrix.skew(v[0], 0);
+					break;
+				case 'skewY':
+					matrix.skew(0, v[0]);
+					break;
+				}
+			}
+			item.transform(matrix);
+		}
+	}
+
+	function applyOpacity(item, value, name) {
+		var key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',
+			color = item[key] && item[key]();
+		if (color)
+			color.setAlpha(parseFloat(value));
+	}
+
+	var attributes = Base.set(Base.each(SvgStyles, function(entry) {
+		this[entry.attribute] = function(item, value) {
+			if (item[entry.set]) {
+				item[entry.set](convertValue(value, entry.type, entry.fromSVG));
+				if (entry.type === 'color') {
+					var color = item[entry.get]();
+					if (color) {
+						if (color._scaleToBounds) {
+							var bounds = item.getBounds();
+							color.transform(new Matrix()
+								.translate(bounds.getPoint())
+								.scale(bounds.getSize()));
+						}
+						if (item instanceof Shape) {
+							color.transform(new Matrix().translate(
+								item.getPosition(true).negate()));
+						}
+					}
+				}
+			}
+		};
+	}, {}), {
+		id: function(item, value) {
+			definitions[value] = item;
+			if (item.setName)
+				item.setName(value);
+		},
+
+		'clip-path': function(item, value) {
+			var clip = getDefinition(value);
+			if (clip) {
+				clip = clip.clone();
+				clip.setClipMask(true);
+				if (item instanceof Group) {
+					item.insertChild(0, clip);
+				} else {
+					return new Group(clip, item);
+				}
+			}
+		},
+
+		gradientTransform: applyTransform,
+		transform: applyTransform,
+
+		'fill-opacity': applyOpacity,
+		'stroke-opacity': applyOpacity,
+
+		visibility: function(item, value) {
+			if (item.setVisible)
+				item.setVisible(value === 'visible');
+		},
+
+		display: function(item, value) {
+			if (item.setVisible)
+				item.setVisible(value !== null);
+		},
+
+		'stop-color': function(item, value) {
+			if (item.setColor)
+				item.setColor(value);
+		},
+
+		'stop-opacity': function(item, value) {
+			if (item._color)
+				item._color.setAlpha(parseFloat(value));
+		},
+
+		offset: function(item, value) {
+			if (item.setOffset) {
+				var percent = value.match(/(.*)%$/);
+				item.setOffset(percent ? percent[1] / 100 : parseFloat(value));
+			}
+		},
+
+		viewBox: function(item, value, name, node, styles) {
+			var rect = new Rectangle(convertValue(value, 'array')),
+				size = getSize(node, null, null, true),
+				group,
+				matrix;
+			if (item instanceof Group) {
+				var scale = size ? size.divide(rect.getSize()) : 1,
+				matrix = new Matrix().scale(scale)
+						.translate(rect.getPoint().negate());
+				group = item;
+			} else if (item instanceof SymbolDefinition) {
+				if (size)
+					rect.setSize(size);
+				group = item._item;
+			}
+			if (group)  {
+				if (getAttribute(node, 'overflow', styles) !== 'visible') {
+					var clip = new Shape.Rectangle(rect);
+					clip.setClipMask(true);
+					group.addChild(clip);
+				}
+				if (matrix)
+					group.transform(matrix);
+			}
+		}
+	});
+
+	function getAttribute(node, name, styles) {
+		var attr = node.attributes[name],
+			value = attr && attr.value;
+		if (!value) {
+			var style = Base.camelize(name);
+			value = node.style[style];
+			if (!value && styles.node[style] !== styles.parent[style])
+				value = styles.node[style];
+		}
+		return !value ? undefined
+				: value === 'none' ? null
+				: value;
+	}
+
+	function applyAttributes(item, node, isRoot) {
+		var parent = node.parentNode,
+			styles = {
+				node: DomElement.getStyles(node) || {},
+				parent: !isRoot && !/^defs$/i.test(parent.tagName)
+						&& DomElement.getStyles(parent) || {}
+			};
+		Base.each(attributes, function(apply, name) {
+			var value = getAttribute(node, name, styles);
+			item = value !== undefined && apply(item, value, name, node, styles)
+					|| item;
+		});
+		return item;
+	}
+
+	function getDefinition(value) {
+		var match = value && value.match(/\((?:["'#]*)([^"')]+)/),
+			res = match && definitions[match[1]
+				.replace(window.location.href.split('#')[0] + '#', '')];
+		if (res && res._scaleToBounds) {
+			res = res.clone();
+			res._scaleToBounds = true;
+		}
+		return res;
+	}
+
+	function importNode(node, options, isRoot) {
+		var type = node.nodeName.toLowerCase(),
+			isElement = type !== '#document',
+			body = document.body,
+			container,
+			parent,
+			next;
+		if (isRoot && isElement) {
+			rootSize = getSize(node, null, null, true)
+					|| paper.getView().getSize();
+			container = SvgElement.create('svg', {
+				style: 'stroke-width: 1px; stroke-miterlimit: 10'
+			});
+			parent = node.parentNode;
+			next = node.nextSibling;
+			container.appendChild(node);
+			body.appendChild(container);
+		}
+		var settings = paper.settings,
+			applyMatrix = settings.applyMatrix,
+			insertItems = settings.insertItems;
+		settings.applyMatrix = false;
+		settings.insertItems = false;
+		var importer = importers[type],
+			item = importer && importer(node, type, options, isRoot) || null;
+		settings.insertItems = insertItems;
+		settings.applyMatrix = applyMatrix;
+		if (item) {
+			if (isElement && !(item instanceof Group))
+				item = applyAttributes(item, node, isRoot);
+			var onImport = options.onImport,
+				data = isElement && node.getAttribute('data-paper-data');
+			if (onImport)
+				item = onImport(node, item, options) || item;
+			if (options.expandShapes && item instanceof Shape) {
+				item.remove();
+				item = item.toPath();
+			}
+			if (data)
+				item._data = JSON.parse(data);
+		}
+		if (container) {
+			body.removeChild(container);
+			if (parent) {
+				if (next) {
+					parent.insertBefore(node, next);
+				} else {
+					parent.appendChild(node);
+				}
+			}
+		}
+		if (isRoot) {
+			definitions = {};
+			if (item && Base.pick(options.applyMatrix, applyMatrix))
+				item.matrix.apply(true, true);
+		}
+		return item;
+	}
+
+	function importSVG(source, options, owner) {
+		if (!source)
+			return null;
+		options = typeof options === 'function' ? { onLoad: options }
+				: options || {};
+		var scope = paper,
+			item = null;
+
+		function onLoad(svg) {
+			try {
+				var node = typeof svg === 'object' ? svg : new window.DOMParser()
+						.parseFromString(svg, 'image/svg+xml');
+				if (!node.nodeName) {
+					node = null;
+					throw new Error('Unsupported SVG source: ' + source);
+				}
+				paper = scope;
+				item = importNode(node, options, true);
+				if (!options || options.insert !== false) {
+					owner._insertItem(undefined, item);
+				}
+				var onLoad = options.onLoad;
+				if (onLoad)
+					onLoad(item, svg);
+			} catch (e) {
+				onError(e);
+			}
+		}
+
+		function onError(message, status) {
+			var onError = options.onError;
+			if (onError) {
+				onError(message, status);
+			} else {
+				throw new Error(message);
+			}
+		}
+
+		if (typeof source === 'string' && !/^.*</.test(source)) {
+			var node = document.getElementById(source);
+			if (node) {
+				onLoad(node);
+			} else {
+				Http.request({
+					url: source,
+					async: true,
+					onLoad: onLoad,
+					onError: onError
+				});
+			}
+		} else if (typeof File !== 'undefined' && source instanceof File) {
+			var reader = new FileReader();
+			reader.onload = function() {
+				onLoad(reader.result);
+			};
+			reader.onerror = function() {
+				onError(reader.error);
+			};
+			return reader.readAsText(source);
+		} else {
+			onLoad(source);
+		}
+
+		return item;
+	}
+
+	Item.inject({
+		importSVG: function(node, options) {
+			return importSVG(node, options, this);
+		}
+	});
+
+	Project.inject({
+		importSVG: function(node, options) {
+			this.activate();
+			return importSVG(node, options, this);
+		}
+	});
+};
+
+Base.exports.PaperScript = function() {
+	var exports, define,
+		scope = this;
+!function(e,r){return"object"==typeof exports&&"object"==typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):void r(e.acorn||(e.acorn={}))}(this,function(e){"use strict";function r(e){fe=e||{};for(var r in he)Object.prototype.hasOwnProperty.call(fe,r)||(fe[r]=he[r]);me=fe.sourceFile||null}function t(e,r){var t=ve(de,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=be,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;r<e.length;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;a<e.length;++a){for(var o=0;o<n.length;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;a<n.length;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return new Function("str",t)}function a(){this.line=Ae,this.column=be-Se}function o(){Ae=1,be=Se=0,Ee=!0,u()}function i(e,r){ge=be,fe.locations&&(ke=new a),we=e,u(),Ce=r,Ee=e.beforeExpr}function s(){var e=fe.onComment&&fe.locations&&new a,r=be,n=de.indexOf("*/",be+=2);if(-1===n&&t(be-2,"Unterminated comment"),be=n+2,fe.locations){Kr.lastIndex=r;for(var o;(o=Kr.exec(de))&&o.index<be;)++Ae,Se=o.index+o[0].length}fe.onComment&&fe.onComment(!0,de.slice(r+2,n),r,be,e,fe.locations&&new a)}function c(){for(var e=be,r=fe.onComment&&fe.locations&&new a,t=de.charCodeAt(be+=2);pe>be&&10!==t&&13!==t&&8232!==t&&8233!==t;)++be,t=de.charCodeAt(be);fe.onComment&&fe.onComment(!1,de.slice(e+2,be),e,be,r,fe.locations&&new a)}function u(){for(;pe>be;){var e=de.charCodeAt(be);if(32===e)++be;else if(13===e){++be;var r=de.charCodeAt(be);10===r&&++be,fe.locations&&(++Ae,Se=be)}else if(10===e||8232===e||8233===e)++be,fe.locations&&(++Ae,Se=be);else if(e>8&&14>e)++be;else if(47===e){var r=de.charCodeAt(be+1);if(42===r)s();else{if(47!==r)break;c()}}else if(160===e)++be;else{if(!(e>=5760&&Jr.test(String.fromCharCode(e))))break;++be}}}function l(){var e=de.charCodeAt(be+1);return e>=48&&57>=e?E(!0):(++be,i(xr))}function f(){var e=de.charCodeAt(be+1);return Ee?(++be,k()):61===e?x(Er,2):x(wr,1)}function d(){var e=de.charCodeAt(be+1);return 61===e?x(Er,2):x(jr,1)}function p(e){var r=de.charCodeAt(be+1);return r===e?x(124===e?Ir:Lr,2):61===r?x(Er,2):x(124===e?Ur:Rr,1)}function m(){var e=de.charCodeAt(be+1);return 61===e?x(Er,2):x(Fr,1)}function h(e){var r=de.charCodeAt(be+1);return r===e?45==r&&62==de.charCodeAt(be+2)&&Gr.test(de.slice(Le,be))?(be+=3,c(),u(),g()):x(Ar,2):61===r?x(Er,2):x(qr,1)}function v(e){var r=de.charCodeAt(be+1),t=1;return r===e?(t=62===e&&62===de.charCodeAt(be+2)?3:2,61===de.charCodeAt(be+t)?x(Er,t+1):x(Tr,t)):33==r&&60==e&&45==de.charCodeAt(be+2)&&45==de.charCodeAt(be+3)?(be+=4,c(),u(),g()):(61===r&&(t=61===de.charCodeAt(be+2)?3:2),x(Vr,t))}function b(e){var r=de.charCodeAt(be+1);return 61===r?x(Or,61===de.charCodeAt(be+2)?3:2):x(61===e?Cr:Sr,1)}function y(e){switch(e){case 46:return l();case 40:return++be,i(hr);case 41:return++be,i(vr);case 59:return++be,i(yr);case 44:return++be,i(br);case 91:return++be,i(fr);case 93:return++be,i(dr);case 123:return++be,i(pr);case 125:return++be,i(mr);case 58:return++be,i(gr);case 63:return++be,i(kr);case 48:var r=de.charCodeAt(be+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return d();case 124:case 38:return p(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(Sr,1)}return!1}function g(e){if(e?be=ye+1:ye=be,fe.locations&&(xe=new a),e)return k();if(be>=pe)return i(Be);var r=de.charCodeAt(be);if(Qr(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$r.test(o))return L();t(be,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=de.slice(be,be+r);be+=r,i(e,t)}function k(){for(var e,r,n="",a=be;;){be>=pe&&t(a,"Unterminated regular expression");var o=de.charAt(be);if(Gr.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++be}var n=de.slice(a,be);++be;var s=I();s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag");try{var c=new RegExp(n,s)}catch(u){u instanceof SyntaxError&&t(a,u.message),t(u)}return i(qe,c)}function w(e,r){for(var t=be,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=de.charCodeAt(be);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++be,n=n*e+i}return be===t||null!=r&&be-t!==r?null:n}function C(){be+=2;var e=w(16);return null==e&&t(ye+2,"Expected hexadecimal number"),Qr(de.charCodeAt(be))&&t(be,"Identifier directly after number"),i(Te,e)}function E(e){var r=be,n=!1,a=48===de.charCodeAt(be);e||null!==w(10)||t(r,"Invalid number"),46===de.charCodeAt(be)&&(++be,w(10),n=!0);var o=de.charCodeAt(be);69!==o&&101!==o||(o=de.charCodeAt(++be),43!==o&&45!==o||++be,null===w(10)&&t(r,"Invalid number"),n=!0),Qr(de.charCodeAt(be))&&t(be,"Identifier directly after number");var s,c=de.slice(r,be);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Oe?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(Te,s)}function A(e){be++;for(var r="";;){be>=pe&&t(ye,"Unterminated string constant");var n=de.charCodeAt(be);if(n===e)return++be,i(je,r);if(92===n){n=de.charCodeAt(++be);var a=/^[0-7]+/.exec(de.slice(be,be+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,-1);if("0"===a&&(a=null),++be,a)Oe&&t(be-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),be+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+="	";break;case 98:r+="\b";break;case 118:r+="\x0B";break;case 102:r+="\f";break;case 48:r+="\x00";break;case 13:10===de.charCodeAt(be)&&++be;case 10:fe.locations&&(Se=be,++Ae);break;default:r+=String.fromCharCode(n)}}else 13!==n&&10!==n&&8232!==n&&8233!==n||t(ye,"Unterminated string constant"),r+=String.fromCharCode(n),++be}}function S(e){var r=w(16,e);return null===r&&t(ye,"Bad character escape sequence"),r}function I(){Br=!1;for(var e,r=!0,n=be;;){var a=de.charCodeAt(be);if(Yr(a))Br&&(e+=de.charAt(be)),++be;else{if(92!==a)break;Br||(e=de.slice(n,be)),Br=!0,117!=de.charCodeAt(++be)&&t(be,"Expecting Unicode escape sequence \\uXXXX"),++be;var o=S(4),i=String.fromCharCode(o);i||t(be-1,"Invalid Unicode escape"),(r?Qr(o):Yr(o))||t(be-4,"Invalid Unicode escape"),e+=i}r=!1}return Br?e:de.slice(n,be)}function L(){var e=I(),r=De;return!Br&&Wr(e)&&(r=lr[e]),i(r,e)}function U(){Ie=ye,Le=ge,Ue=ke,g()}function F(e){if(Oe=e,be=ye,fe.locations)for(;Se>be;)Se=de.lastIndexOf("\n",Se-2)+1,--Ae;u(),g()}function R(){this.type=null,this.start=ye,this.end=null}function O(){this.start=xe,this.end=null,null!==me&&(this.source=me)}function V(){var e=new R;return fe.locations&&(e.loc=new O),fe.directSourceFile&&(e.sourceFile=fe.directSourceFile),fe.ranges&&(e.range=[ye,0]),e}function T(e){var r=new R;return r.start=e.start,fe.locations&&(r.loc=new O,r.loc.start=e.loc.start),fe.ranges&&(r.range=[e.range[0],0]),r}function q(e,r){return e.type=r,e.end=Le,fe.locations&&(e.loc.end=Ue),fe.ranges&&(e.range[1]=Le),e}function j(e){return fe.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return we===e?(U(),!0):void 0}function B(){return!fe.strictSemicolons&&(we===Be||we===mr||Gr.test(de.slice(Le,ye)))}function M(){D(yr)||B()||X()}function z(e){we===e?U():X()}function X(){t(ye,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Oe&&"Identifier"===e.type&&Nr(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ie=Le=be,fe.locations&&(Ue=new a),Fe=Oe=null,Re=[],g();var r=e||V(),t=!0;for(e||(r.body=[]);we!==Be;){var n=J();r.body.push(n),t&&j(n)&&F(!0),t=!1}return q(r,"Program")}function J(){(we===wr||we===Er&&"/="==Ce)&&g(!0);var e=we,r=V();switch(e){case Me:case Ne:U();var n=e===Me;D(yr)||B()?r.label=null:we!==De?X():(r.label=le(),M());for(var a=0;a<Re.length;++a){var o=Re[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Re.length&&t(r.start,"Unsyntactic "+e.keyword),q(r,n?"BreakStatement":"ContinueStatement");case We:return U(),M(),q(r,"DebuggerStatement");case Pe:return U(),Re.push(Zr),r.body=J(),Re.pop(),z(tr),r.test=P(),M(),q(r,"DoWhileStatement");case _e:if(U(),Re.push(Zr),z(hr),we===yr)return $(r,null);if(we===rr){var i=V();return U(),G(i,!0),q(i,"VariableDeclaration"),1===i.declarations.length&&D(ur)?_(r,i):$(r,i)}var i=K(!1,!0);return D(ur)?(N(i),_(r,i)):$(r,i);case Ge:return U(),ce(r,!0);case Ke:return U(),r.test=P(),r.consequent=J(),r.alternate=D(He)?J():null,q(r,"IfStatement");case Qe:return Fe||fe.allowReturnOutsideFunction||t(ye,"'return' outside of function"),U(),D(yr)||B()?r.argument=null:(r.argument=K(),M()),q(r,"ReturnStatement");case Ye:U(),r.discriminant=P(),r.cases=[],z(pr),Re.push(et);for(var s,c;we!=mr;)if(we===ze||we===Je){var u=we===ze;s&&q(s,"SwitchCase"),r.cases.push(s=V()),s.consequent=[],U(),u?s.test=K():(c&&t(Ie,"Multiple default clauses"),c=!0,s.test=null),z(gr)}else s||X(),s.consequent.push(J());return s&&q(s,"SwitchCase"),U(),Re.pop(),q(r,"SwitchStatement");case Ze:return U(),Gr.test(de.slice(Le,ye))&&t(Le,"Illegal newline after throw"),r.argument=K(),M(),q(r,"ThrowStatement");case er:if(U(),r.block=H(),r.handler=null,we===Xe){var l=V();U(),z(hr),l.param=le(),Oe&&Nr(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(vr),l.guard=null,l.body=H(),r.handler=q(l,"CatchClause")}return r.guardedHandlers=Ve,r.finalizer=D($e)?H():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),q(r,"TryStatement");case rr:return U(),G(r),M(),q(r,"VariableDeclaration");case tr:return U(),r.test=P(),Re.push(Zr),r.body=J(),Re.pop(),q(r,"WhileStatement");case nr:return Oe&&t(ye,"'with' in strict mode"),U(),r.object=P(),r.body=J(),q(r,"WithStatement");case pr:return H();case yr:return U(),q(r,"EmptyStatement");default:var f=Ce,d=K();if(e===De&&"Identifier"===d.type&&D(gr)){for(var a=0;a<Re.length;++a)Re[a].name===f&&t(d.start,"Label '"+f+"' is already declared");var p=we.isLoop?"loop":we===Ye?"switch":null;return Re.push({name:f,kind:p}),r.body=J(),Re.pop(),r.label=d,q(r,"LabeledStatement")}return r.expression=d,M(),q(r,"ExpressionStatement")}}function P(){z(hr);var e=K();return z(vr),e}function H(e){var r,t=V(),n=!0,a=!1;for(t.body=[],z(pr);!D(mr);){var o=J();t.body.push(o),n&&e&&j(o)&&(r=a,F(a=!0)),n=!1}return a&&!r&&F(!1),q(t,"BlockStatement")}function $(e,r){return e.init=r,z(yr),e.test=we===yr?null:K(),z(yr),e.update=we===vr?null:K(),z(vr),e.body=J(),Re.pop(),q(e,"ForStatement")}function _(e,r){return e.left=r,e.right=K(),z(vr),e.body=J(),Re.pop(),q(e,"ForInStatement")}function G(e,r){for(e.declarations=[],e.kind="var";;){var n=V();if(n.id=le(),Oe&&Nr(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(Cr)?K(!0,r):null,e.declarations.push(q(n,"VariableDeclarator")),!D(br))break}return e}function K(e,r){var t=Q(r);if(!e&&we===br){var n=T(t);for(n.expressions=[t];D(br);)n.expressions.push(Q(r));return q(n,"SequenceExpression")}return t}function Q(e){var r=Y(e);if(we.isAssign){var t=T(r);return t.operator=Ce,t.left=r,U(),t.right=Q(e),N(r),q(t,"AssignmentExpression")}return r}function Y(e){var r=Z(e);if(D(kr)){var t=T(r);return t.test=r,t.consequent=K(!0),z(gr),t.alternate=K(!0,e),q(t,"ConditionalExpression")}return r}function Z(e){return ee(re(),-1,e)}function ee(e,r,t){var n=we.binop;if(null!=n&&(!t||we!==ur)&&n>r){var a=T(e);a.left=e,a.operator=Ce;var o=we;U(),a.right=ee(re(),n,t);var i=q(a,o===Ir||o===Lr?"LogicalExpression":"BinaryExpression");return ee(i,r,t)}return e}function re(){if(we.prefix){var e=V(),r=we.isUpdate;return e.operator=Ce,e.prefix=!0,Ee=!0,U(),e.argument=re(),r?N(e.argument):Oe&&"delete"===e.operator&&"Identifier"===e.argument.type&&t(e.start,"Deleting local variable in strict mode"),q(e,r?"UpdateExpression":"UnaryExpression")}for(var n=te();we.postfix&&!B();){var e=T(n);e.operator=Ce,e.prefix=!1,e.argument=n,N(n),U(),n=q(e,"UpdateExpression")}return n}function te(){return ne(ae())}function ne(e,r){if(D(xr)){var t=T(e);return t.object=e,t.property=le(!0),t.computed=!1,ne(q(t,"MemberExpression"),r)}if(D(fr)){var t=T(e);return t.object=e,t.property=K(),t.computed=!0,z(dr),ne(q(t,"MemberExpression"),r)}if(!r&&D(hr)){var t=T(e);return t.callee=e,t.arguments=ue(vr,!1),ne(q(t,"CallExpression"),r)}return e}function ae(){switch(we){case or:var e=V();return U(),q(e,"ThisExpression");case De:return le();case Te:case je:case qe:var e=V();return e.value=Ce,e.raw=de.slice(ye,ge),U(),q(e,"Literal");case ir:case sr:case cr:var e=V();return e.value=we.atomValue,e.raw=we.keyword,U(),q(e,"Literal");case hr:var r=xe,t=ye;U();var n=K();return n.start=t,n.end=ge,fe.locations&&(n.loc.start=r,n.loc.end=ke),fe.ranges&&(n.range=[t,ge]),z(vr),n;case fr:var e=V();return U(),e.elements=ue(dr,!0,!0),q(e,"ArrayExpression");case pr:return ie();case Ge:var e=V();return U(),ce(e,!1);case ar:return oe();default:X()}}function oe(){var e=V();return U(),e.callee=ne(ae(),!0),D(hr)?e.arguments=ue(vr,!1):e.arguments=Ve,q(e,"NewExpression")}function ie(){var e=V(),r=!0,n=!1;for(e.properties=[],U();!D(mr);){if(r)r=!1;else if(z(br),fe.allowTrailingCommas&&D(mr))break;var a,o={key:se()},i=!1;if(D(gr)?(o.value=K(!0),a=o.kind="init"):fe.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=se(),we!==hr&&X(),o.value=ce(V(),!1)):X(),"Identifier"===o.key.type&&(Oe||n))for(var s=0;s<e.properties.length;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Oe&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return q(e,"ObjectExpression")}function se(){return we===Te||we===je?ae():le(!0)}function ce(e,r){we===De?e.id=le():r?X():e.id=null,e.params=[];var n=!0;for(z(hr);!D(vr);)n?n=!1:z(br),e.params.push(le());var a=Fe,o=Re;if(Fe=!0,Re=[],e.body=H(!0),Fe=a,Re=o,Oe||e.body.body.length&&j(e.body.body[0]))for(var i=e.id?-1:0;i<e.params.length;++i){var s=0>i?e.id:e.params[i];if((Xr(s.name)||Nr(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return q(e,r?"FunctionDeclaration":"FunctionExpression")}function ue(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(br),r&&fe.allowTrailingCommas&&D(e))break;t&&we===br?n.push(null):n.push(K(!0))}return n}function le(e){var r=V();return e&&"everywhere"==fe.forbidReserved&&(e=!1),we===De?(!e&&(fe.forbidReserved&&(3===fe.ecmaVersion?Mr:zr)(Ce)||Oe&&Xr(Ce))&&-1==de.slice(ye,ge).indexOf("\\")&&t(ye,"The keyword '"+Ce+"' is reserved"),r.name=Ce):e&&we.keyword?r.name=we.keyword:X(),Ee=!1,U(),q(r,"Identifier")}e.version="0.5.0";var fe,de,pe,me;e.parse=function(e,t){return de=String(e),pe=de.length,r(t),o(),W(fe.program)};var he=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,allowReturnOutsideFunction:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null},ve=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kr.lastIndex=n;var a=Kr.exec(e);if(!(a&&a.index<r))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return Le=ge,g(e),a.start=ye,a.end=ge,a.startLoc=xe,a.endLoc=ke,a.type=we,a.value=Ce,a}de=String(e),pe=de.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(be=e,fe.locations){Ae=1,Se=Kr.lastIndex=0;for(var t;(t=Kr.exec(de))&&t.index<e;)++Ae,Se=t.index+t[0].length}Ee=r,u()},n};var be,ye,ge,xe,ke,we,Ce,Ee,Ae,Se,Ie,Le,Ue,Fe,Re,Oe,Ve=[],Te={type:"num"},qe={type:"regexp"},je={type:"string"},De={type:"name"},Be={type:"eof"},Me={keyword:"break"},ze={keyword:"case",beforeExpr:!0},Xe={keyword:"catch"},Ne={keyword:"continue"},We={keyword:"debugger"},Je={keyword:"default"},Pe={keyword:"do",isLoop:!0},He={keyword:"else",beforeExpr:!0},$e={keyword:"finally"},_e={keyword:"for",isLoop:!0},Ge={keyword:"function"},Ke={keyword:"if"},Qe={keyword:"return",beforeExpr:!0},Ye={keyword:"switch"},Ze={keyword:"throw",beforeExpr:!0},er={keyword:"try"},rr={keyword:"var"},tr={keyword:"while",isLoop:!0},nr={keyword:"with"},ar={keyword:"new",beforeExpr:!0},or={keyword:"this"},ir={keyword:"null",atomValue:null},sr={keyword:"true",atomValue:!0},cr={keyword:"false",atomValue:!1},ur={keyword:"in",binop:7,beforeExpr:!0},lr={"break":Me,"case":ze,"catch":Xe,"continue":Ne,"debugger":We,"default":Je,"do":Pe,"else":He,"finally":$e,"for":_e,"function":Ge,"if":Ke,"return":Qe,"switch":Ye,"throw":Ze,"try":er,"var":rr,"while":tr,"with":nr,"null":ir,"true":sr,"false":cr,"new":ar,"in":ur,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":or,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},fr={type:"[",beforeExpr:!0},dr={type:"]"},pr={type:"{",beforeExpr:!0},mr={type:"}"},hr={type:"(",beforeExpr:!0},vr={type:")"},br={type:",",beforeExpr:!0},yr={type:";",beforeExpr:!0},gr={type:":",beforeExpr:!0},xr={type:"."},kr={type:"?",beforeExpr:!0},wr={binop:10,beforeExpr:!0},Cr={isAssign:!0,beforeExpr:!0},Er={isAssign:!0,beforeExpr:!0},Ar={postfix:!0,prefix:!0,isUpdate:!0},Sr={prefix:!0,beforeExpr:!0},Ir={binop:1,beforeExpr:!0},Lr={binop:2,beforeExpr:!0},Ur={binop:3,beforeExpr:!0},Fr={binop:4,beforeExpr:!0},Rr={binop:5,beforeExpr:!0},Or={binop:6,beforeExpr:!0},Vr={binop:7,beforeExpr:!0},Tr={binop:8,beforeExpr:!0},qr={binop:9,prefix:!0,beforeExpr:!0},jr={binop:10,beforeExpr:!0};e.tokTypes={bracketL:fr,bracketR:dr,braceL:pr,braceR:mr,parenL:hr,parenR:vr,comma:br,semi:yr,colon:gr,dot:xr,question:kr,slash:wr,eq:Cr,name:De,eof:Be,num:Te,regexp:qe,string:je};for(var Dr in lr)e.tokTypes["_"+Dr]=lr[Dr];var Br,Mr=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),zr=n("class enum extends super const export import"),Xr=n("implements interface let package private protected public static yield"),Nr=n("eval arguments"),Wr=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Jr=/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/,Pr="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",Hr="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$r=new RegExp("["+Pr+"]"),_r=new RegExp("["+Pr+Hr+"]"),Gr=/[\n\r\u2028\u2029]/,Kr=/\r\n|[\n\r\u2028\u2029]/g,Qr=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$r.test(String.fromCharCode(e))},Yr=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&_r.test(String.fromCharCode(e))},Zr={kind:"loop"},et={kind:"switch"}});
+
+	var binaryOperators = {
+		'+': '__add',
+		'-': '__subtract',
+		'*': '__multiply',
+		'/': '__divide',
+		'%': '__modulo',
+		'==': '__equals',
+		'!=': '__equals'
+	};
+
+	var unaryOperators = {
+		'-': '__negate',
+		'+': null
+	};
+
+	var fields = Base.each(
+		['add', 'subtract', 'multiply', 'divide', 'modulo', 'equals', 'negate'],
+		function(name) {
+			this['__' + name] = '#' + name;
+		},
+		{}
+	);
+	Point.inject(fields);
+	Size.inject(fields);
+	Color.inject(fields);
+
+	function __$__(left, operator, right) {
+		var handler = binaryOperators[operator];
+		if (left && left[handler]) {
+			var res = left[handler](right);
+			return operator === '!=' ? !res : res;
+		}
+		switch (operator) {
+		case '+': return left + right;
+		case '-': return left - right;
+		case '*': return left * right;
+		case '/': return left / right;
+		case '%': return left % right;
+		case '==': return left == right;
+		case '!=': return left != right;
+		}
+	}
+
+	function $__(operator, value) {
+		var handler = unaryOperators[operator];
+		if (handler && value && value[handler])
+			return value[handler]();
+		switch (operator) {
+		case '+': return +value;
+		case '-': return -value;
+		}
+	}
+
+	function parse(code, options) {
+		return scope.acorn.parse(code, options);
+	}
+
+	function compile(code, options) {
+		if (!code)
+			return '';
+		options = options || {};
+
+		var insertions = [];
+
+		function getOffset(offset) {
+			for (var i = 0, l = insertions.length; i < l; i++) {
+				var insertion = insertions[i];
+				if (insertion[0] >= offset)
+					break;
+				offset += insertion[1];
+			}
+			return offset;
+		}
+
+		function getCode(node) {
+			return code.substring(getOffset(node.range[0]),
+					getOffset(node.range[1]));
+		}
+
+		function getBetween(left, right) {
+			return code.substring(getOffset(left.range[1]),
+					getOffset(right.range[0]));
+		}
+
+		function replaceCode(node, str) {
+			var start = getOffset(node.range[0]),
+				end = getOffset(node.range[1]),
+				insert = 0;
+			for (var i = insertions.length - 1; i >= 0; i--) {
+				if (start > insertions[i][0]) {
+					insert = i + 1;
+					break;
+				}
+			}
+			insertions.splice(insert, 0, [start, str.length - end + start]);
+			code = code.substring(0, start) + str + code.substring(end);
+		}
+
+		function walkAST(node, parent) {
+			if (!node)
+				return;
+			for (var key in node) {
+				if (key === 'range' || key === 'loc')
+					continue;
+				var value = node[key];
+				if (Array.isArray(value)) {
+					for (var i = 0, l = value.length; i < l; i++)
+						walkAST(value[i], node);
+				} else if (value && typeof value === 'object') {
+					walkAST(value, node);
+				}
+			}
+			switch (node.type) {
+			case 'UnaryExpression':
+				if (node.operator in unaryOperators
+						&& node.argument.type !== 'Literal') {
+					var arg = getCode(node.argument);
+					replaceCode(node, '$__("' + node.operator + '", '
+							+ arg + ')');
+				}
+				break;
+			case 'BinaryExpression':
+				if (node.operator in binaryOperators
+						&& node.left.type !== 'Literal') {
+					var left = getCode(node.left),
+						right = getCode(node.right),
+						between = getBetween(node.left, node.right),
+						operator = node.operator;
+					replaceCode(node, '__$__(' + left + ','
+							+ between.replace(new RegExp('\\' + operator),
+								'"' + operator + '"')
+							+ ', ' + right + ')');
+				}
+				break;
+			case 'UpdateExpression':
+			case 'AssignmentExpression':
+				var parentType = parent && parent.type;
+				if (!(
+						parentType === 'ForStatement'
+						|| parentType === 'BinaryExpression'
+							&& /^[=!<>]/.test(parent.operator)
+						|| parentType === 'MemberExpression' && parent.computed
+				)) {
+					if (node.type === 'UpdateExpression') {
+						var arg = getCode(node.argument),
+							exp = '__$__(' + arg + ', "' + node.operator[0]
+									+ '", 1)',
+							str = arg + ' = ' + exp;
+						if (!node.prefix
+								&& (parentType === 'AssignmentExpression'
+									|| parentType === 'VariableDeclarator')) {
+							if (getCode(parent.left || parent.id) === arg)
+								str = exp;
+							str = arg + '; ' + str;
+						}
+						replaceCode(node, str);
+					} else {
+						if (/^.=$/.test(node.operator)
+								&& node.left.type !== 'Literal') {
+							var left = getCode(node.left),
+								right = getCode(node.right);
+							replaceCode(node, left + ' = __$__(' + left + ', "'
+									+ node.operator[0] + '", ' + right + ')');
+						}
+					}
+				}
+				break;
+			}
+		}
+
+		function encodeVLQ(value) {
+			var res = '',
+				base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+			value = (Math.abs(value) << 1) + (value < 0 ? 1 : 0);
+			while (value || !res) {
+				var next = value & (32 - 1);
+				value >>= 5;
+				if (value)
+					next |= 32;
+				res += base64[next];
+			}
+			return res;
+		}
+
+		var url = options.url || '',
+			agent = paper.agent,
+			version = agent.versionNumber,
+			offsetCode = false,
+			sourceMaps = options.sourceMaps,
+			source = options.source || code,
+			lineBreaks = /\r\n|\n|\r/mg,
+			offset = options.offset || 0,
+			map;
+		if (sourceMaps && (agent.chrome && version >= 30
+				|| agent.webkit && version >= 537.76
+				|| agent.firefox && version >= 23
+				|| agent.node)) {
+			if (agent.node) {
+				offset -= 2;
+			} else if (window && url && !window.location.href.indexOf(url)) {
+				var html = document.getElementsByTagName('html')[0].innerHTML;
+				offset = html.substr(0, html.indexOf(code) + 1).match(
+						lineBreaks).length + 1;
+			}
+			offsetCode = offset > 0 && !(
+					agent.chrome && version >= 36 ||
+					agent.safari && version >= 600 ||
+					agent.firefox && version >= 40 ||
+					agent.node);
+			var mappings = ['AA' + encodeVLQ(offsetCode ? 0 : offset) + 'A'];
+			mappings.length = (code.match(lineBreaks) || []).length + 1
+					+ (offsetCode ? offset : 0);
+			map = {
+				version: 3,
+				file: url,
+				names:[],
+				mappings: mappings.join(';AACA'),
+				sourceRoot: '',
+				sources: [url],
+				sourcesContent: [source]
+			};
+		}
+		walkAST(parse(code, { ranges: true }));
+		if (map) {
+			if (offsetCode) {
+				code = new Array(offset + 1).join('\n') + code;
+			}
+			if (/^(inline|both)$/.test(sourceMaps)) {
+				code += "\n//# sourceMappingURL=data:application/json;base64,"
+						+ window.btoa(unescape(encodeURIComponent(
+							JSON.stringify(map))));
+			}
+			code += "\n//# sourceURL=" + (url || 'paperscript');
+		}
+		return {
+			url: url,
+			source: source,
+			code: code,
+			map: map
+		};
+	}
+
+	function execute(code, scope, options) {
+		paper = scope;
+		var view = scope.getView(),
+			tool = /\btool\.\w+|\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\b/
+					.test(code) && !/\bnew\s+Tool\b/.test(code)
+						? new Tool() : null,
+			toolHandlers = tool ? tool._events : [],
+			handlers = ['onFrame', 'onResize'].concat(toolHandlers),
+			params = [],
+			args = [],
+			func,
+			compiled = typeof code === 'object' ? code : compile(code, options);
+		code = compiled.code;
+		function expose(scope, hidden) {
+			for (var key in scope) {
+				if ((hidden || !/^_/.test(key)) && new RegExp('([\\b\\s\\W]|^)'
+						+ key.replace(/\$/g, '\\$') + '\\b').test(code)) {
+					params.push(key);
+					args.push(scope[key]);
+				}
+			}
+		}
+		expose({ __$__: __$__, $__: $__, paper: scope, view: view, tool: tool },
+				true);
+		expose(scope);
+		handlers = Base.each(handlers, function(key) {
+			if (new RegExp('\\s+' + key + '\\b').test(code)) {
+				params.push(key);
+				this.push(key + ': ' + key);
+			}
+		}, []).join(', ');
+		if (handlers)
+			code += '\nreturn { ' + handlers + ' };';
+		var agent = paper.agent;
+		if (document && (agent.chrome
+				|| agent.firefox && agent.versionNumber < 40)) {
+			var script = document.createElement('script'),
+				head = document.head || document.getElementsByTagName('head')[0];
+			if (agent.firefox)
+				code = '\n' + code;
+			script.appendChild(document.createTextNode(
+				'paper._execute = function(' + params + ') {' + code + '\n}'
+			));
+			head.appendChild(script);
+			func = paper._execute;
+			delete paper._execute;
+			head.removeChild(script);
+		} else {
+			func = Function(params, code);
+		}
+		var res = func.apply(scope, args) || {};
+		Base.each(toolHandlers, function(key) {
+			var value = res[key];
+			if (value)
+				tool[key] = value;
+		});
+		if (view) {
+			if (res.onResize)
+				view.setOnResize(res.onResize);
+			view.emit('resize', {
+				size: view.size,
+				delta: new Point()
+			});
+			if (res.onFrame)
+				view.setOnFrame(res.onFrame);
+			view.requestUpdate();
+		}
+		return compiled;
+	}
+
+	function loadScript(script) {
+		if (/^text\/(?:x-|)paperscript$/.test(script.type)
+				&& PaperScope.getAttribute(script, 'ignore') !== 'true') {
+			var canvasId = PaperScope.getAttribute(script, 'canvas'),
+				canvas = document.getElementById(canvasId),
+				src = script.src || script.getAttribute('data-src'),
+				async = PaperScope.hasAttribute(script, 'async'),
+				scopeAttribute = 'data-paper-scope';
+			if (!canvas)
+				throw new Error('Unable to find canvas with id "'
+						+ canvasId + '"');
+			var scope = PaperScope.get(canvas.getAttribute(scopeAttribute))
+						|| new PaperScope().setup(canvas);
+			canvas.setAttribute(scopeAttribute, scope._id);
+			if (src) {
+				Http.request({
+					url: src,
+					async: async,
+					mimeType: 'text/plain',
+					onLoad: function(code) {
+						execute(code, scope, src);
+					}
+				});
+			} else {
+				execute(script.innerHTML, scope, script.baseURI);
+			}
+			script.setAttribute('data-paper-ignore', 'true');
+			return scope;
+		}
+	}
+
+	function loadAll() {
+		Base.each(document && document.getElementsByTagName('script'),
+				loadScript);
+	}
+
+	function load(script) {
+		return script ? loadScript(script) : loadAll();
+	}
+
+	if (window) {
+		if (document.readyState === 'complete') {
+			setTimeout(loadAll);
+		} else {
+			DomEvent.add(window, { load: loadAll });
+		}
+	}
+
+	return {
+		compile: compile,
+		execute: execute,
+		load: load,
+		parse: parse
+	};
+
+}.call(this);
+
+paper = new (PaperScope.inject(Base.exports, {
+	enumerable: true,
+	Base: Base,
+	Numerical: Numerical,
+	Key: Key,
+	DomEvent: DomEvent,
+	DomElement: DomElement,
+	document: document,
+	window: window,
+	Symbol: SymbolDefinition,
+	PlacedSymbol: SymbolItem
+}))();
+
+if (paper.agent.node)
+	require('./node/extend')(paper);
+
+if (typeof define === 'function' && define.amd) {
+	define('paper', paper);
+} else if (typeof module === 'object' && module) {
+	module.exports = paper;
+}
+
+return paper;
+}.call(this, typeof self === 'object' ? self : null);
diff --git a/dist/paper-full.min.js b/dist/paper-full.min.js
new file mode 100644
index 00000000..ca636a6b
--- /dev/null
+++ b/dist/paper-full.min.js
@@ -0,0 +1,39 @@
+/*!
+ * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
+ * http://scratchdisk.com/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ *
+ * Date: Sat Jul 9 20:56:58 2016 +0200
+ *
+ ***
+ *
+ * Straps.js - Class inheritance library with support for bean-style accessors
+ *
+ * Copyright (c) 2006 - 2016 Juerg Lehni
+ * http://scratchdisk.com/
+ *
+ * Distributed under the MIT license.
+ *
+ ***
+ *
+ * Acorn.js
+ * http://marijnhaverbeke.nl/acorn/
+ *
+ * Acorn is a tiny, fast JavaScript parser written in JavaScript,
+ * created by Marijn Haverbeke and released under an MIT license.
+ *
+ */
+var paper=function(t,e){var n=t?t.window:require("./node/window"),i=n&&n.document;t=t||n;var r=new function(){function t(t,e,n,i,a){function o(s,o){o=o||(o=u(e,s))&&(o.get?o:o.value),"string"==typeof o&&"#"===o[0]&&(o=t[o.substring(1)]||o);var l,f="function"==typeof o,d=o,_=a||f&&!o.base?o&&o.get?s in t:t[s]:null;a&&_||(f&&_&&(o.base=_),f&&i!==!1&&(l=s.match(/^([gs]et|is)(([A-Z])(.*))$/))&&(h[l[3].toLowerCase()+l[4]]=l[2]),d&&!f&&d.get&&"function"==typeof d.get&&r.isPlainObject(d)||(d={value:d,writable:!0}),(u(t,s)||{configurable:!0}).configurable&&(d.configurable=!0,d.enumerable=n),c(t,s,d))}var h={};if(e){for(var l in e)e.hasOwnProperty(l)&&!s.test(l)&&o(l);for(var l in h){var f=h[l],d=t["set"+f],_=t["get"+f]||d&&t["is"+f];!_||i!==!0&&0!==_.length||o(l,{get:_,set:d})}}return t}function n(t,e,n){return t&&("length"in t&&!t.getLength&&"number"==typeof t.length?a:o).call(t,e,n=n||t),n}function i(t,e,n){for(var i=n,r=e.length;i<r;i++){var s=e[i];for(var a in s)s.hasOwnProperty(a)&&(t[a]=s[a])}return t}var s=/^(statics|enumerable|beans|preserve)$/,a=[].forEach||function(t,e){for(var n=0,i=this.length;n<i;n++)t.call(e,this[n],n,this)},o=function(t,e){for(var n in this)this.hasOwnProperty(n)&&t.call(e,this[n],n,this)},h=Object.create||function(t){return{__proto__:t}},u=Object.getOwnPropertyDescriptor||function(t,e){var n=t.__lookupGetter__&&t.__lookupGetter__(e);return n?{get:n,set:t.__lookupSetter__(e),enumerable:!0,configurable:!0}:t.hasOwnProperty(e)?{value:t[e],enumerable:!0,configurable:!0,writable:!0}:null},l=Object.defineProperty||function(t,e,n){return(n.get||n.set)&&t.__defineGetter__?(n.get&&t.__defineGetter__(e,n.get),n.set&&t.__defineSetter__(e,n.set)):t[e]=n.value,t},c=function(t,e,n){return delete t[e],l(t,e,n)};return t(function(){i(this,arguments,0)},{inject:function(e){if(e){var n=e.statics===!0?e:e.statics,i=e.beans,r=e.preserve;n!==e&&t(this.prototype,e,e.enumerable,i,r),t(this,n,!0,i,r)}for(var s=1,a=arguments.length;s<a;s++)this.inject(arguments[s]);return this},extend:function(){for(var e,n,i,r=this,s=0,a=arguments.length;s<a&&(!e||!n);s++)i=arguments[s],e=e||i.initialize,n=n||i.prototype;return e=e||function(){r.apply(this,arguments)},n=e.prototype=n||h(this.prototype),c(n,"constructor",{value:e,writable:!0,configurable:!0}),t(e,this,!0),arguments.length&&this.inject.apply(e,arguments),e.base=r,e}},!0).inject({inject:function(){for(var e=0,n=arguments.length;e<n;e++){var i=arguments[e];i&&t(this,i,i.enumerable,i.beans,i.preserve)}return this},extend:function(){var t=h(this);return t.inject.apply(t,arguments)},each:function(t,e){return n(this,t,e)},set:function(){return i(this,arguments,0)},clone:function(){return new this.constructor(this)},statics:{each:n,create:h,define:c,describe:u,set:function(t){return i(t,arguments,1)},clone:function(t){return i(new t.constructor,arguments,0)},isPlainObject:function(t){var e=null!=t&&t.constructor;return e&&(e===Object||e===r||"Object"===e.name)},pick:function(t,n){return t!==e?t:n}}})};"undefined"!=typeof module&&(module.exports=r),r.inject({toString:function(){return null!=this._id?(this._class||"Object")+(this._name?" '"+this._name+"'":" @"+this._id):"{ "+r.each(this,function(t,e){if(!/^_/.test(e)){var n=typeof t;this.push(e+": "+("number"===n?h.instance.number(t):"string"===n?"'"+t+"'":t))}},[]).join(", ")+" }"},getClassName:function(){return this._class||""},importJSON:function(t){return r.importJSON(t,this)},exportJSON:function(t){return r.exportJSON(this,t)},toJSON:function(){return r.serialize(this)},_set:function(t){if(t&&r.isPlainObject(t))return r.filter(this,t)},statics:{exports:{enumerable:!0},extend:function rt(){var t=rt.base.apply(this,arguments),e=t.prototype._class;return e&&!r.exports[e]&&(r.exports[e]=t),t},equals:function(t,e){if(t===e)return!0;if(t&&t.equals)return t.equals(e);if(e&&e.equals)return e.equals(t);if(t&&e&&"object"==typeof t&&"object"==typeof e){if(Array.isArray(t)&&Array.isArray(e)){var n=t.length;if(n!==e.length)return!1;for(;n--;)if(!r.equals(t[n],e[n]))return!1}else{var i=Object.keys(t),n=i.length;if(n!==Object.keys(e).length)return!1;for(;n--;){var s=i[n];if(!e.hasOwnProperty(s)||!r.equals(t[s],e[s]))return!1}}return!0}return!1},read:function(t,n,i,s){if(this===r){var a=this.peek(t,n);return t.__index++,a}var o=this.prototype,h=o._readIndex,u=n||h&&t.__index||0;s||(s=t.length-u);var l=t[u];return l instanceof this||i&&i.readNull&&null==l&&s<=1?(h&&(t.__index=u+1),l&&i&&i.clone?l.clone():l):(l=r.create(this.prototype),h&&(l.__read=!0),l=l.initialize.apply(l,u>0||s<t.length?Array.prototype.slice.call(t,u,u+s):t)||l,h&&(t.__index=u+l.__read,l.__read=e),l)},peek:function(t,e){return t[t.__index=e||t.__index||0]},remain:function(t){return t.length-(t.__index||0)},readAll:function(t,e,n){for(var i,r=[],s=e||0,a=t.length;s<a;s++)r.push(Array.isArray(i=t[s])?this.read(i,0,n):this.read(t,s,n,1));return r},readNamed:function(t,n,i,s,a){var o=this.getNamed(t,n),h=o!==e;if(h){var u=t._filtered;u||(u=t._filtered=r.create(t[0]),u._filtering=t[0]),u[n]=e}return this.read(h?[o]:t,i,s,a)},getNamed:function(t,n){var i=t[0];if(t._hasObject===e&&(t._hasObject=1===t.length&&r.isPlainObject(i)),t._hasObject)return n?i[n]:t._filtered||i},hasNamed:function(t,e){return!!this.getNamed(t,e)},filter:function(t,n,i){for(var r=Object.keys(n._filtering||n),s=0,a=r.length;s<a;s++){var o=r[s];if(!i||!i[o]){var h=n[o];h!==e&&(t[o]=h)}}return t},isPlainValue:function(t,e){return this.isPlainObject(t)||Array.isArray(t)||e&&"string"==typeof t},serialize:function(t,e,n,i){e=e||{};var s,a=!i;if(a&&(e.formatter=new h(e.precision),i={length:0,definitions:{},references:{},add:function(t,e){var n="#"+t._id,i=this.references[n];if(!i){this.length++;var r=e.call(t),s=t._class;s&&r[0]!==s&&r.unshift(s),this.definitions[n]=r,i=this.references[n]=[n]}return i}}),t&&t._serialize){s=t._serialize(e,i);var o=t._class;!o||t._compactSerialize||!a&&n||s[0]===o||s.unshift(o)}else if(Array.isArray(t)){s=[];for(var u=0,l=t.length;u<l;u++)s[u]=r.serialize(t[u],e,n,i)}else if(r.isPlainObject(t)){s={};for(var c=Object.keys(t),u=0,l=c.length;u<l;u++){var f=c[u];s[f]=r.serialize(t[f],e,n,i)}}else s="number"==typeof t?e.formatter.number(t,e.precision):t;return a&&i.length>0?[["dictionary",i.definitions],s]:s},deserialize:function(t,e,n,i,s){var a=t,o=!n,h=o&&t&&t.length&&"dictionary"===t[0][0];if(n=n||{},Array.isArray(t)){var u=t[0],l="dictionary"===u;if(1==t.length&&/^#/.test(u))return n.dictionary[u];u=r.exports[u],a=[];for(var c=u?1:0,f=t.length;c<f;c++)a.push(r.deserialize(t[c],e,n,l,h));if(u){var d=a;e?a=e(u,d,o||s):(a=r.create(u.prototype),u.apply(a,d))}}else if(r.isPlainObject(t)){a={},i&&(n.dictionary=a);for(var _ in t)a[_]=r.deserialize(t[_],e,n)}return h?a[1]:a},exportJSON:function(t,e){var n=r.serialize(t,e);return e&&e.asString===!1?n:JSON.stringify(n)},importJSON:function(t,e){return r.deserialize("string"==typeof t?JSON.parse(t):t,function(t,n,i){var s=i&&e&&e.constructor===t,a=s?e:r.create(t.prototype);if(1===n.length&&a instanceof w&&(s||!(a instanceof b))){var o=n[0];r.isPlainObject(o)&&(o.insert=!1)}return(s?a._set:t).apply(a,n),s&&(e=null),a})},splice:function(t,n,i,r){var s=n&&n.length,a=i===e;i=a?t.length:i,i>t.length&&(i=t.length);for(var o=0;o<s;o++)n[o]._index=i+o;if(a)return t.push.apply(t,n),[];var h=[i,r];n&&h.push.apply(h,n);for(var u=t.splice.apply(t,h),o=0,l=u.length;o<l;o++)u[o]._index=e;for(var o=i+s,l=t.length;o<l;o++)t[o]._index=o;return u},capitalize:function(t){return t.replace(/\b[a-z]/g,function(t){return t.toUpperCase()})},camelize:function(t){return t.replace(/-(.)/g,function(t,e){return e.toUpperCase()})},hyphenate:function(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}}});var s={on:function(t,e){if("string"!=typeof t)r.each(t,function(t,e){this.on(e,t)},this);else{var n=this._eventTypes,i=n&&n[t],s=this._callbacks=this._callbacks||{};s=s[t]=s[t]||[],s.indexOf(e)===-1&&(s.push(e),i&&i.install&&1===s.length&&i.install.call(this,t))}return this},off:function(t,e){if("string"!=typeof t)return void r.each(t,function(t,e){this.off(e,t)},this);var n,i=this._eventTypes,s=i&&i[t],a=this._callbacks&&this._callbacks[t];return a&&(!e||(n=a.indexOf(e))!==-1&&1===a.length?(s&&s.uninstall&&s.uninstall.call(this,t),delete this._callbacks[t]):n!==-1&&a.splice(n,1)),this},once:function(t,e){return this.on(t,function(){e.apply(this,arguments),this.off(t,e)})},emit:function(t,e){var n=this._callbacks&&this._callbacks[t];if(!n)return!1;var i=[].slice.call(arguments,1),r=e&&e.target&&!e.currentTarget;n=n.slice(),r&&(e.currentTarget=this);for(var s=0,a=n.length;s<a;s++)if(n[s].apply(this,i)===!1){e&&e.stop&&e.stop();break}return r&&delete e.currentTarget,!0},responds:function(t){return!(!this._callbacks||!this._callbacks[t])},attach:"#on",detach:"#off",fire:"#emit",_installEvents:function(t){var e=this._eventTypes,n=this._callbacks,i=t?"install":"uninstall";if(e)for(var r in n)if(n[r].length>0){var s=e[r],a=s&&s[i];a&&a.call(this,r)}},statics:{inject:function st(t){var e=t._events;if(e){var n={};r.each(e,function(e,i){var s="string"==typeof e,a=s?e:i,o=r.capitalize(a),h=a.substring(2).toLowerCase();n[h]=s?{}:e,a="_"+a,t["get"+o]=function(){return this[a]},t["set"+o]=function(t){var e=this[a];e&&this.off(h,e),t&&this.on(h,t),this[a]=t}}),t._eventTypes=n}return st.base.apply(this,arguments)}}},a=r.extend({_class:"PaperScope",initialize:function at(){paper=this,this.settings=new r({applyMatrix:!0,insertItems:!0,handleSize:4,hitTolerance:0}),this.project=null,this.projects=[],this.tools=[],this.palettes=[],this._id=at._id++,at._scopes[this._id]=this;var e=at.prototype;if(!this.support){var n=tt.getContext(1,1)||{};e.support={nativeDash:"setLineDash"in n||"mozDash"in n,nativeBlendModes:et.nativeModes},tt.release(n)}if(!this.agent){var i=t.navigator.userAgent.toLowerCase(),s=(/(darwin|win|mac|linux|freebsd|sunos)/.exec(i)||[])[0],a="darwin"===s?"mac":s,o=e.agent=e.browser={platform:a};a&&(o[a]=!0),i.replace(/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,function(t,e,n,i,r){if(!o.chrome){var s="opera"===e?i:/^(node|trident)$/.test(e)?r:n;o.version=s,o.versionNumber=parseFloat(s),e="trident"===e?"msie":e,o.name=e,o[e]=!0}}),o.chrome&&delete o.webkit,o.atom&&delete o.chrome}},version:"0.10.2",getView:function(){var t=this.project;return t&&t._view},getPaper:function(){return this},execute:function(t,e){paper.PaperScript.execute(t,this,e),Z.updateFocus()},install:function(t){var e=this;r.each(["project","view","tool"],function(n){r.define(t,n,{configurable:!0,get:function(){return e[n]}})});for(var n in this)!/^_/.test(n)&&this[n]&&(t[n]=this[n])},setup:function(t){return paper=this,this.project=new y(t),this},createCanvas:function(t,e){return tt.getCanvas(t,e)},activate:function(){paper=this},clear:function(){for(var t=this.projects,e=this.tools,n=this.palettes,i=t.length-1;i>=0;i--)t[i].remove();for(var i=e.length-1;i>=0;i--)e[i].remove();for(var i=n.length-1;i>=0;i--)n[i].remove()},remove:function(){this.clear(),delete a._scopes[this._id]},statics:new function(){function t(t){return t+="Attribute",function(e,n){return e[t](n)||e[t]("data-paper-"+n)}}return{_scopes:{},_id:0,get:function(t){return this._scopes[t]||null},getAttribute:t("get"),hasAttribute:t("has")}}}),o=r.extend(s,{initialize:function(t){this._scope=paper,this._index=this._scope[this._list].push(this)-1,!t&&this._scope[this._reference]||this.activate()},activate:function(){if(!this._scope)return!1;var t=this._scope[this._reference];return t&&t!==this&&t.emit("deactivate"),this._scope[this._reference]=this,this.emit("activate",t),!0},isActive:function(){return this._scope[this._reference]===this},remove:function(){return null!=this._index&&(r.splice(this._scope[this._list],null,this._index,1),this._scope[this._reference]==this&&(this._scope[this._reference]=null),this._scope=null,!0)},getView:function(){return this._scope.getView()}}),h=r.extend({initialize:function(t){this.precision=r.pick(t,5),this.multiplier=Math.pow(10,this.precision)},number:function(t){return this.precision<16?Math.round(t*this.multiplier)/this.multiplier:t},pair:function(t,e,n){return this.number(t)+(n||",")+this.number(e)},point:function(t,e){return this.number(t.x)+(e||",")+this.number(t.y)},size:function(t,e){return this.number(t.width)+(e||",")+this.number(t.height)},rectangle:function(t,e){return this.point(t,e)+(e||",")+this.size(t,e)}});h.instance=new h;var u=new function(){function t(t,e,n){return t<e?e:t>n?n:t}function e(t,e,n){function i(t){var e=134217729*t,n=t-e,i=n+e,r=t-i;return[i,r]}var r=e*e-t*n,a=e*e+t*n;if(3*s(r)<a){var o=i(t),h=i(e),u=i(n),l=e*e,c=h[0]*h[0]-l+2*h[0]*h[1]+h[1]*h[1],f=t*n,d=o[0]*u[0]-f+o[0]*u[1]+o[1]*u[0]+o[1]*u[1];r=l-f+(c-d)}return r}function n(){var t=Math.max.apply(Math,arguments);return t&&(t<1e-8||t>1e8)?o(2,-Math.round(h(t))):0}var i=[[.5773502691896257],[0,.7745966692414834],[.33998104358485626,.8611363115940526],[0,.5384693101056831,.906179845938664],[.2386191860831969,.6612093864662645,.932469514203152],[0,.4058451513773972,.7415311855993945,.9491079123427585],[.1834346424956498,.525532409916329,.7966664774136267,.9602898564975363],[0,.3242534234038089,.6133714327005904,.8360311073266358,.9681602395076261],[.14887433898163122,.4333953941292472,.6794095682990244,.8650633666889845,.9739065285171717],[0,.26954315595234496,.5190961292068118,.7301520055740494,.8870625997680953,.978228658146057],[.1252334085114689,.3678314989981802,.5873179542866175,.7699026741943047,.9041172563704749,.9815606342467192],[0,.2304583159551348,.44849275103644687,.6423493394403402,.8015780907333099,.9175983992229779,.9841830547185881],[.10805494870734367,.31911236892788974,.5152486363581541,.6872929048116855,.827201315069765,.9284348836635735,.9862838086968123],[0,.20119409399743451,.3941513470775634,.5709721726085388,.7244177313601701,.8482065834104272,.937273392400706,.9879925180204854],[.09501250983763744,.2816035507792589,.45801677765722737,.6178762444026438,.755404408355003,.8656312023878318,.9445750230732326,.9894009349916499]],r=[[1],[.8888888888888888,.5555555555555556],[.6521451548625461,.34785484513745385],[.5688888888888889,.47862867049936647,.23692688505618908],[.46791393457269104,.3607615730481386,.17132449237917036],[.4179591836734694,.3818300505051189,.27970539148927664,.1294849661688697],[.362683783378362,.31370664587788727,.22238103445337448,.10122853629037626],[.3302393550012598,.31234707704000286,.26061069640293544,.1806481606948574,.08127438836157441],[.29552422471475287,.26926671930999635,.21908636251598204,.1494513491505806,.06667134430868814],[.2729250867779006,.26280454451024665,.23319376459199048,.18629021092773426,.1255803694649046,.05566856711617366],[.24914704581340277,.2334925365383548,.20316742672306592,.16007832854334622,.10693932599531843,.04717533638651183],[.2325515532308739,.22628318026289723,.2078160475368885,.17814598076194574,.13887351021978725,.09212149983772845,.04048400476531588],[.2152638534631578,.2051984637212956,.18553839747793782,.15720316715819355,.12151857068790319,.08015808715976021,.03511946033175186],[.2025782419255613,.19843148532711158,.1861610000155622,.16626920581699392,.13957067792615432,.10715922046717194,.07036604748810812,.03075324199611727],[.1894506104550685,.18260341504492358,.16915651939500254,.14959598881657674,.12462897125553388,.09515851168249279,.062253523938647894,.027152459411754096]],s=Math.abs,a=Math.sqrt,o=Math.pow,h=Math.log2||function(t){return Math.log(t)*Math.LOG2E},l=1e-12,c=1.12e-16;return{TOLERANCE:1e-6,EPSILON:l,MACHINE_EPSILON:c,CURVETIME_EPSILON:4e-7,GEOMETRIC_EPSILON:2e-7,WINDING_EPSILON:2e-7,TRIGONOMETRIC_EPSILON:1e-7,CLIPPING_EPSILON:1e-9,KAPPA:4*(a(2)-1)/3,isZero:function(t){return t>=-l&&t<=l},clamp:t,integrate:function(t,e,n,s){for(var a=i[s-2],o=r[s-2],h=.5*(n-e),u=h+e,l=0,c=s+1>>1,f=1&s?o[l++]*t(u):0;l<c;){var d=h*a[l];f+=o[l++]*(t(u+d)+t(u-d))}return h*f},findRoot:function(t,e,n,i,r,a,o){for(var h=0;h<a;h++){var u=t(n),l=u/e(n),c=n-l;if(s(l)<o)return c;u>0?(r=n,n=c<=i?.5*(i+r):c):(i=n,n=c>=r?.5*(i+r):c)}return n},solveQuadratic:function(i,r,o,h,u,f){var d,_=1/0;if(s(i)<l){if(s(r)<l)return s(o)<l?-1:0;d=-o/r}else{r*=-.5;var g=e(i,r,o);if(g&&s(g)<c){var v=n(s(i),s(r),s(o));v&&(i*=v,r*=v,o*=v,g=e(i,r,o))}if(g>=-c){var p=g<0?0:a(g),m=r+(r<0?-p:p);0===m?(d=o/i,_=-d):(d=m/i,_=o/m)}}var y=0,w=null==u,x=u-l,b=f+l;return isFinite(d)&&(w||d>x&&d<b)&&(h[y++]=w?d:t(d,u,f)),_!==d&&isFinite(_)&&(w||_>x&&_<b)&&(h[y++]=w?_:t(_,u,f)),y},solveCubic:function(e,i,r,h,f,d,_){function g(t){v=t;var n=e*v;p=n+i,m=p*v+r,y=(n+p)*v+m,w=m*v+h}var v,p,m,y,w,x=n(s(e),s(i),s(r),s(h));if(x&&(e*=x,i*=x,r*=x,h*=x),s(e)<l)e=i,p=r,m=h,v=1/0;else if(s(h)<l)p=i,m=r,v=0;else{g(-(i/e)/3);var b=w/e,C=o(s(b),1/3),S=b<0?-1:1,k=-y/e,I=k>0?1.324717957244746*Math.max(C,a(k)):C,P=v-S*I;if(P!==v){do g(P),P=0===y?v:v-w/y/(1+c);while(S*P>S*v);s(e)*v*v>s(h/v)&&(m=-h/v,p=(m-r)/v)}}var M=u.solveQuadratic(e,p,m,f,d,_),A=null==d;return isFinite(v)&&(0===M||M>0&&v!==f[0]&&v!==f[1])&&(A||v>d-l&&v<_+l)&&(f[M++]=A?v:t(v,d,_)),M}}},l={_id:1,_pools:{},get:function(t){if(t){var e=this._pools[t];return e||(e=this._pools[t]={_id:1}),e._id++}return this._id++}},c=r.extend({_class:"Point",_readIndex:!0,initialize:function(t,e){var n=typeof t;if("number"===n){var i="number"==typeof e;this.x=t,this.y=i?e:t,this.__read&&(this.__read=i?2:1)}else if("undefined"===n||null===t)this.x=this.y=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===n?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.x=r[0],this.y=r.length>1?r[1]:r[0]):"x"in r?(this.x=r.x,this.y=r.y):"width"in r?(this.x=r.width,this.y=r.height):"angle"in r?(this.x=r.length,this.y=0,this.setAngle(r.angle)):(this.x=this.y=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.x=t,this.y=e,this},equals:function(t){return this===t||t&&(this.x===t.x&&this.y===t.y||Array.isArray(t)&&this.x===t[0]&&this.y===t[1])||!1},clone:function(){return new c(this.x,this.y)},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y)]},getLength:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},setLength:function(t){if(this.isZero()){var e=this._angle||0;this.set(Math.cos(e)*t,Math.sin(e)*t)}else{var n=t/this.getLength();u.isZero(n)&&this.getAngle(),this.set(this.x*n,this.y*n)}},getAngle:function(){return 180*this.getAngleInRadians.apply(this,arguments)/Math.PI},setAngle:function(t){this.setAngleInRadians.call(this,t*Math.PI/180)},getAngleInDegrees:"#getAngle",setAngleInDegrees:"#setAngle",getAngleInRadians:function(){if(arguments.length){var t=c.read(arguments),e=this.getLength()*t.getLength();if(u.isZero(e))return NaN;var n=this.dot(t)/e;return Math.acos(n<-1?-1:n>1?1:n)}return this.isZero()?this._angle||0:this._angle=Math.atan2(this.y,this.x)},setAngleInRadians:function(t){if(this._angle=t,!this.isZero()){var e=this.getLength();this.set(Math.cos(t)*e,Math.sin(t)*e)}},getQuadrant:function(){return this.x>=0?this.y>=0?1:4:this.y>=0?2:3}},{beans:!1,getDirectedAngle:function(){var t=c.read(arguments);return 180*Math.atan2(this.cross(t),this.dot(t))/Math.PI},getDistance:function(){var t=c.read(arguments),e=t.x-this.x,n=t.y-this.y,i=e*e+n*n,s=r.read(arguments);return s?i:Math.sqrt(i)},normalize:function(t){t===e&&(t=1);var n=this.getLength(),i=0!==n?t/n:0,r=new c(this.x*i,this.y*i);return i>=0&&(r._angle=this._angle),r},rotate:function(t,e){if(0===t)return this.clone();t=t*Math.PI/180;var n=e?this.subtract(e):this,i=Math.sin(t),r=Math.cos(t);return n=new c(n.x*r-n.y*i,n.x*i+n.y*r),e?n.add(e):n},transform:function(t){return t?t._transformPoint(this):this},add:function(){var t=c.read(arguments);return new c(this.x+t.x,this.y+t.y)},subtract:function(){var t=c.read(arguments);return new c(this.x-t.x,this.y-t.y)},multiply:function(){var t=c.read(arguments);return new c(this.x*t.x,this.y*t.y)},divide:function(){var t=c.read(arguments);return new c(this.x/t.x,this.y/t.y)},modulo:function(){var t=c.read(arguments);return new c(this.x%t.x,this.y%t.y)},negate:function(){return new c((-this.x),(-this.y))},isInside:function(){return g.read(arguments).contains(this)},isClose:function(){var t=c.read(arguments),e=r.read(arguments);return this.getDistance(t)<=e},isCollinear:function(){var t=c.read(arguments);return c.isCollinear(this.x,this.y,t.x,t.y)},isColinear:"#isCollinear",isOrthogonal:function(){var t=c.read(arguments);return c.isOrthogonal(this.x,this.y,t.x,t.y)},isZero:function(){return u.isZero(this.x)&&u.isZero(this.y)},isNaN:function(){return isNaN(this.x)||isNaN(this.y)},dot:function(){var t=c.read(arguments);return this.x*t.x+this.y*t.y},cross:function(){var t=c.read(arguments);return this.x*t.y-this.y*t.x},project:function(){var t=c.read(arguments),e=t.isZero()?0:this.dot(t)/t.dot(t);return new c(t.x*e,t.y*e)},statics:{min:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.min(t.x,e.x),Math.min(t.y,e.y))},max:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.max(t.x,e.x),Math.max(t.y,e.y))},random:function(){return new c(Math.random(),Math.random())},isCollinear:function(t,e,n,i){return Math.abs(t*i-e*n)<=1e-7*Math.sqrt((t*t+e*e)*(n*n+i*i))},isOrthogonal:function(t,e,n,i){return Math.abs(t*n+e*i)<=1e-7*Math.sqrt((t*t+e*e)*(n*n+i*i))}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new c(e(this.x),e(this.y))}},{})),f=c.extend({initialize:function(t,e,n,i){this._x=t,this._y=e,this._owner=n,this._setter=i},set:function(t,e,n){return this._x=t,this._y=e,n||this._owner[this._setter](this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner[this._setter](this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner[this._setter](this)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){return"setPosition"===this._setter?4:0}}),d=r.extend({_class:"Size",_readIndex:!0,initialize:function(t,e){var n=typeof t;if("number"===n){var i="number"==typeof e;this.width=t,this.height=i?e:t,this.__read&&(this.__read=i?2:1)}else if("undefined"===n||null===t)this.width=this.height=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===n?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.width=r[0],this.height=r.length>1?r[1]:r[0]):"width"in r?(this.width=r.width,this.height=r.height):"x"in r?(this.width=r.x,this.height=r.y):(this.width=this.height=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.width=t,this.height=e,this},equals:function(t){return t===this||t&&(this.width===t.width&&this.height===t.height||Array.isArray(t)&&this.width===t[0]&&this.height===t[1])||!1},clone:function(){return new d(this.width,this.height)},toString:function(){var t=h.instance;return"{ width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.width),e.number(this.height)]},add:function(){var t=d.read(arguments);return new d(this.width+t.width,this.height+t.height)},subtract:function(){var t=d.read(arguments);return new d(this.width-t.width,this.height-t.height)},multiply:function(){var t=d.read(arguments);return new d(this.width*t.width,this.height*t.height)},divide:function(){var t=d.read(arguments);return new d(this.width/t.width,this.height/t.height)},modulo:function(){var t=d.read(arguments);return new d(this.width%t.width,this.height%t.height)},negate:function(){return new d((-this.width),(-this.height))},isZero:function(){return u.isZero(this.width)&&u.isZero(this.height)},isNaN:function(){return isNaN(this.width)||isNaN(this.height)},statics:{min:function(t,e){return new d(Math.min(t.width,e.width),Math.min(t.height,e.height))},max:function(t,e){return new d(Math.max(t.width,e.width),Math.max(t.height,e.height))},random:function(){return new d(Math.random(),Math.random())}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new d(e(this.width),e(this.height))}},{})),_=d.extend({initialize:function(t,e,n,i){this._width=t,this._height=e,this._owner=n,this._setter=i},set:function(t,e,n){return this._width=t,this._height=e,n||this._owner[this._setter](this),this},getWidth:function(){return this._width},setWidth:function(t){this._width=t,this._owner[this._setter](this)},getHeight:function(){return this._height},setHeight:function(t){this._height=t,this._owner[this._setter](this)}}),g=r.extend({_class:"Rectangle",_readIndex:!0,beans:!0,initialize:function(t,n,i,s){var a=typeof t,o=0;if("number"===a?(this.x=t,this.y=n,this.width=i,this.height=s,o=4):"undefined"===a||null===t?(this.x=this.y=this.width=this.height=0,o=null===t?1:0):1===arguments.length&&(Array.isArray(t)?(this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],o=1):t.x!==e||t.width!==e?(this.x=t.x||0,this.y=t.y||0,this.width=t.width||0,this.height=t.height||0,o=1):t.from===e&&t.to===e&&(this.x=this.y=this.width=this.height=0,this._set(t),o=1)),!o){var h=c.readNamed(arguments,"from"),u=r.peek(arguments);if(this.x=h.x,this.y=h.y,u&&u.x!==e||r.hasNamed(arguments,"to")){var l=c.readNamed(arguments,"to");this.width=l.x-h.x,this.height=l.y-h.y,this.width<0&&(this.x=l.x,this.width=-this.width),this.height<0&&(this.y=l.y,this.height=-this.height)}else{var f=d.read(arguments);this.width=f.width,this.height=f.height}o=arguments.__index}this.__read&&(this.__read=o)},set:function(t,e,n,i){return this.x=t,this.y=e,this.width=n,this.height=i,this},clone:function(){return new g(this.x,this.y,this.width,this.height)},equals:function(t){var e=r.isPlainValue(t)?g.read(arguments):t;return e===this||e&&this.x===e.x&&this.y===e.y&&this.width===e.width&&this.height===e.height||!1},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+", width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y),e.number(this.width),e.number(this.height)]},getPoint:function(t){var e=t?c:f;return new e(this.x,this.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.x=t.x,this.y=t.y},getSize:function(t){var e=t?d:_;return new e(this.width,this.height,this,"setSize")},setSize:function(){var t=d.read(arguments);this._fixX&&(this.x+=(this.width-t.width)*this._fixX),this._fixY&&(this.y+=(this.height-t.height)*this._fixY),this.width=t.width,this.height=t.height,this._fixW=1,this._fixH=1},getLeft:function(){return this.x},setLeft:function(t){this._fixW||(this.width-=t-this.x),this.x=t,this._fixX=0},getTop:function(){return this.y},setTop:function(t){this._fixH||(this.height-=t-this.y),this.y=t,this._fixY=0},getRight:function(){return this.x+this.width},setRight:function(t){this._fixX!==e&&1!==this._fixX&&(this._fixW=0),this._fixW?this.x=t-this.width:this.width=t-this.x,this._fixX=1},getBottom:function(){return this.y+this.height},setBottom:function(t){this._fixY!==e&&1!==this._fixY&&(this._fixH=0),this._fixH?this.y=t-this.height:this.height=t-this.y,this._fixY=1},getCenterX:function(){return this.x+.5*this.width},setCenterX:function(t){this.x=t-.5*this.width,this._fixX=.5},getCenterY:function(){return this.y+.5*this.height},setCenterY:function(t){this.y=t-.5*this.height,this._fixY=.5},getCenter:function(t){var e=t?c:f;return new e(this.getCenterX(),this.getCenterY(),this,"setCenter")},setCenter:function(){var t=c.read(arguments);return this.setCenterX(t.x),this.setCenterY(t.y),this},getArea:function(){return this.width*this.height},isEmpty:function(){return 0===this.width||0===this.height},contains:function(t){return t&&t.width!==e||4===(Array.isArray(t)?t:arguments).length?this._containsRectangle(g.read(arguments)):this._containsPoint(c.read(arguments))},_containsPoint:function(t){var e=t.x,n=t.y;return e>=this.x&&n>=this.y&&e<=this.x+this.width&&n<=this.y+this.height},_containsRectangle:function(t){var e=t.x,n=t.y;return e>=this.x&&n>=this.y&&e+t.width<=this.x+this.width&&n+t.height<=this.y+this.height},intersects:function(){var t=g.read(arguments);return t.x+t.width>this.x&&t.y+t.height>this.y&&t.x<this.x+this.width&&t.y<this.y+this.height},touches:function(){var t=g.read(arguments);return t.x+t.width>=this.x&&t.y+t.height>=this.y&&t.x<=this.x+this.width&&t.y<=this.y+this.height},intersect:function(){var t=g.read(arguments),e=Math.max(this.x,t.x),n=Math.max(this.y,t.y),i=Math.min(this.x+this.width,t.x+t.width),r=Math.min(this.y+this.height,t.y+t.height);return new g(e,n,i-e,r-n)},unite:function(){var t=g.read(arguments),e=Math.min(this.x,t.x),n=Math.min(this.y,t.y),i=Math.max(this.x+this.width,t.x+t.width),r=Math.max(this.y+this.height,t.y+t.height);return new g(e,n,i-e,r-n)},include:function(){var t=c.read(arguments),e=Math.min(this.x,t.x),n=Math.min(this.y,t.y),i=Math.max(this.x+this.width,t.x),r=Math.max(this.y+this.height,t.y);return new g(e,n,i-e,r-n)},expand:function(){var t=d.read(arguments),e=t.width,n=t.height;return new g(this.x-e/2,this.y-n/2,this.width+e,this.height+n)},scale:function(t,n){return this.expand(this.width*t-this.width,this.height*(n===e?t:n)-this.height)}},r.each([["Top","Left"],["Top","Right"],["Bottom","Left"],["Bottom","Right"],["Left","Center"],["Top","Center"],["Right","Center"],["Bottom","Center"]],function(t,e){var n=t.join(""),i=/^[RL]/.test(n);e>=4&&(t[1]+=i?"Y":"X");var r=t[i?0:1],s=t[i?1:0],a="get"+r,o="get"+s,h="set"+r,u="set"+s,l="get"+n,d="set"+n;this[l]=function(t){var e=t?c:f;return new e(this[a](),this[o](),this,d)},this[d]=function(){var t=c.read(arguments);this[h](t.x),this[u](t.y)}},{beans:!0})),v=g.extend({initialize:function(t,e,n,i,r,s){this.set(t,e,n,i,!0),this._owner=r,this._setter=s},set:function(t,e,n,i,r){return this._x=t,this._y=e,this._width=n,this._height=i,r||this._owner[this._setter](this),this}},new function(){var t=g.prototype;return r.each(["x","y","width","height"],function(t){var e=r.capitalize(t),n="_"+t;this["get"+e]=function(){return this[n]},this["set"+e]=function(t){this[n]=t,this._dontNotify||this._owner[this._setter](this)}},r.each(["Point","Size","Center","Left","Top","Right","Bottom","CenterX","CenterY","TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],function(e){var n="set"+e;this[n]=function(){this._dontNotify=!0,t[n].apply(this,arguments),this._dontNotify=!1,this._owner[this._setter](this)}},{isSelected:function(){return!!(2&this._owner._selection)},setSelected:function(t){var e=this._owner;e.changeSelection&&e.changeSelection(2,t)}}))}),p=r.extend({_class:"Matrix",initialize:function ot(t){var e=arguments.length,n=!0;if(6===e?this.set.apply(this,arguments):1===e?t instanceof ot?this.set(t._a,t._b,t._c,t._d,t._tx,t._ty):Array.isArray(t)?this.set.apply(this,t):n=!1:0===e?this.reset():n=!1,!n)throw new Error("Unsupported matrix parameters")},set:function(t,e,n,i,r,s,a){return this._a=t,this._b=e,this._c=n,this._d=i,this._tx=r,this._ty=s,a||this._changed(),this},_serialize:function(t,e){return r.serialize(this.getValues(),t,!0,e)},_changed:function(){var t=this._owner;t&&(t._applyMatrix?t.transform(null,!0):t._changed(9))},clone:function(){return new p(this._a,this._b,this._c,this._d,this._tx,this._ty)},equals:function(t){return t===this||t&&this._a===t._a&&this._b===t._b&&this._c===t._c&&this._d===t._d&&this._tx===t._tx&&this._ty===t._ty},toString:function(){var t=h.instance;return"[["+[t.number(this._a),t.number(this._c),t.number(this._tx)].join(", ")+"], ["+[t.number(this._b),t.number(this._d),t.number(this._ty)].join(", ")+"]]"},reset:function(t){return this._a=this._d=1,this._b=this._c=this._tx=this._ty=0,t||this._changed(),this},apply:function(t,e){var n=this._owner;return!!n&&(n.transform(null,!0,r.pick(t,!0),e),this.isIdentity())},translate:function(){var t=c.read(arguments),e=t.x,n=t.y;return this._tx+=e*this._a+n*this._c,
+this._ty+=e*this._b+n*this._d,this._changed(),this},scale:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});return e&&this.translate(e),this._a*=t.x,this._b*=t.x,this._c*=t.y,this._d*=t.y,e&&this.translate(e.negate()),this._changed(),this},rotate:function(t){t*=Math.PI/180;var e=c.read(arguments,1),n=e.x,i=e.y,r=Math.cos(t),s=Math.sin(t),a=n-n*r+i*s,o=i-n*s-i*r,h=this._a,u=this._b,l=this._c,f=this._d;return this._a=r*h+s*l,this._b=r*u+s*f,this._c=-s*h+r*l,this._d=-s*u+r*f,this._tx+=a*h+o*l,this._ty+=a*u+o*f,this._changed(),this},shear:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});e&&this.translate(e);var n=this._a,i=this._b;return this._a+=t.y*this._c,this._b+=t.y*this._d,this._c+=t.x*n,this._d+=t.x*i,e&&this.translate(e.negate()),this._changed(),this},skew:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0}),n=Math.PI/180,i=new c(Math.tan(t.x*n),Math.tan(t.y*n));return this.shear(i,e)},append:function(t){if(t){var e=this._a,n=this._b,i=this._c,r=this._d,s=t._a,a=t._c,o=t._b,h=t._d,u=t._tx,l=t._ty;this._a=s*e+o*i,this._c=a*e+h*i,this._b=s*n+o*r,this._d=a*n+h*r,this._tx+=u*e+l*i,this._ty+=u*n+l*r,this._changed()}return this},prepend:function(t){if(t){var e=this._a,n=this._b,i=this._c,r=this._d,s=this._tx,a=this._ty,o=t._a,h=t._c,u=t._b,l=t._d,c=t._tx,f=t._ty;this._a=o*e+h*n,this._c=o*i+h*r,this._b=u*e+l*n,this._d=u*i+l*r,this._tx=o*s+h*a+c,this._ty=u*s+l*a+f,this._changed()}return this},appended:function(t){return this.clone().append(t)},prepended:function(t){return this.clone().prepend(t)},invert:function(){var t=this._a,e=this._b,n=this._c,i=this._d,r=this._tx,s=this._ty,a=t*i-e*n,o=null;return a&&!isNaN(a)&&isFinite(r)&&isFinite(s)&&(this._a=i/a,this._b=-e/a,this._c=-n/a,this._d=t/a,this._tx=(n*s-i*r)/a,this._ty=(e*r-t*s)/a,o=this),o},inverted:function(){return this.clone().invert()},concatenate:"#append",preConcatenate:"#prepend",chain:"#appended",_shiftless:function(){return new p(this._a,this._b,this._c,this._d,0,0)},_orNullIfIdentity:function(){return this.isIdentity()?null:this},isIdentity:function(){return 1===this._a&&0===this._b&&0===this._c&&1===this._d&&0===this._tx&&0===this._ty},isInvertible:function(){var t=this._a*this._d-this._c*this._b;return t&&!isNaN(t)&&isFinite(this._tx)&&isFinite(this._ty)},isSingular:function(){return!this.isInvertible()},transform:function(t,e,n){return arguments.length<3?this._transformPoint(c.read(arguments)):this._transformCoordinates(t,e,n)},_transformPoint:function(t,e,n){var i=t.x,r=t.y;return e||(e=new c),e.set(i*this._a+r*this._c+this._tx,i*this._b+r*this._d+this._ty,n)},_transformCoordinates:function(t,e,n){for(var i=0,r=2*n;i<r;i+=2){var s=t[i],a=t[i+1];e[i]=s*this._a+a*this._c+this._tx,e[i+1]=s*this._b+a*this._d+this._ty}return e},_transformCorners:function(t){var e=t.x,n=t.y,i=e+t.width,r=n+t.height,s=[e,n,i,n,i,r,e,r];return this._transformCoordinates(s,s,4)},_transformBounds:function(t,e,n){for(var i=this._transformCorners(t),r=i.slice(0,2),s=r.slice(),a=2;a<8;a++){var o=i[a],h=1&a;o<r[h]?r[h]=o:o>s[h]&&(s[h]=o)}return e||(e=new g),e.set(r[0],r[1],s[0]-r[0],s[1]-r[1],n)},inverseTransform:function(){return this._inverseTransform(c.read(arguments))},_inverseTransform:function(t,e,n){var i=this._a,r=this._b,s=this._c,a=this._d,o=this._tx,h=this._ty,u=i*a-r*s,l=null;if(u&&!isNaN(u)&&isFinite(o)&&isFinite(h)){var f=t.x-this._tx,d=t.y-this._ty;e||(e=new c),l=e.set((f*a-d*s)/u,(d*i-f*r)/u,n)}return l},decompose:function(){var t,e,n,i=this._a,r=this._b,s=this._c,a=this._d,o=i*a-r*s,h=Math.sqrt,u=Math.atan2,l=180/Math.PI;if(0!==i||0!==r){var f=h(i*i+r*r);t=Math.acos(i/f)*(r>0?1:-1),e=[f,o/f],n=[u(i*s+r*a,f*f),0]}else if(0!==s||0!==a){var d=h(s*s+a*a);t=Math.asin(s/d)*(a>0?1:-1),e=[o/d,d],n=[0,u(i*s+r*a,d*d)]}else t=0,n=e=[0,0];return{translation:this.getTranslation(),rotation:t*l,scaling:new c(e),skewing:new c(n[0]*l,n[1]*l)}},getValues:function(){return[this._a,this._b,this._c,this._d,this._tx,this._ty]},getTranslation:function(){return new c(this._tx,this._ty)},getScaling:function(){return(this.decompose()||{}).scaling},getRotation:function(){return(this.decompose()||{}).rotation},applyToContext:function(t){this.isIdentity()||t.transform(this._a,this._b,this._c,this._d,this._tx,this._ty)}},r.each(["a","b","c","d","tx","ty"],function(t){var e=r.capitalize(t),n="_"+t;this["get"+e]=function(){return this[n]},this["set"+e]=function(t){this[n]=t,this._changed()}},{})),m=r.extend({_class:"Line",initialize:function(t,e,n,i,r){var s=!1;arguments.length>=4?(this._px=t,this._py=e,this._vx=n,this._vy=i,s=r):(this._px=t.x,this._py=t.y,this._vx=e.x,this._vy=e.y,s=n),s||(this._vx-=this._px,this._vy-=this._py)},getPoint:function(){return new c(this._px,this._py)},getVector:function(){return new c(this._vx,this._vy)},getLength:function(){return this.getVector().getLength()},intersect:function(t,e){return m.intersect(this._px,this._py,this._vx,this._vy,t._px,t._py,t._vx,t._vy,!0,e)},getSide:function(t,e){return m.getSide(this._px,this._py,this._vx,this._vy,t.x,t.y,!0,e)},getDistance:function(t){return Math.abs(m.getSignedDistance(this._px,this._py,this._vx,this._vy,t.x,t.y,!0))},isCollinear:function(t){return c.isCollinear(this._vx,this._vy,t._vx,t._vy)},isOrthogonal:function(t){return c.isOrthogonal(this._vx,this._vy,t._vx,t._vy)},statics:{intersect:function(t,e,n,i,r,s,a,o,h,l){h||(n-=t,i-=e,a-=r,o-=s);var f=n*o-i*a;if(!u.isZero(f)){var d=t-r,_=e-s,g=(a*_-o*d)/f,v=(n*_-i*d)/f,p=1e-12,m=-p,y=1+p;if(l||m<g&&g<y&&m<v&&v<y)return l||(g=g<=0?0:g>=1?1:g),new c(t+g*n,e+g*i)}},getSide:function(t,e,n,i,r,s,a,o){a||(n-=t,i-=e);var h=r-t,u=s-e,l=h*i-u*n;return 0!==l||o||(l=(h*n+h*n)/(n*n+i*i),l>=0&&l<=1&&(l=0)),l<0?-1:l>0?1:0},getSignedDistance:function(t,e,n,i,r,s,a){return a||(n-=t,i-=e),0===n?i>0?r-t:t-r:0===i?n<0?s-e:e-s:((r-t)*i-(s-e)*n)/Math.sqrt(n*n+i*i)}}}),y=o.extend({_class:"Project",_list:"projects",_reference:"project",_compactSerialize:!0,initialize:function(t){o.call(this,!0),this._children=[],this._namedChildren={},this._activeLayer=null,this._currentStyle=new V(null,null,this),this._view=Z.create(this,t||tt.getCanvas(1,1)),this._selectionItems={},this._selectionCount=0,this._updateVersion=0},_serialize:function(t,e){return r.serialize(this._children,t,!0,e)},_changed:function(t,e){if(1&t){var n=this._view;n&&(n._needsUpdate=!0,!n._requested&&n._autoUpdate&&n.requestUpdate())}var i=this._changes;if(i&&e){var r=this._changesById,s=e._id,a=r[s];a?a.flags|=t:i.push(r[s]={item:e,flags:t})}},clear:function(){for(var t=this._children,e=t.length-1;e>=0;e--)t[e].remove()},isEmpty:function(){return 0===this._children.length},remove:function ht(){return!!ht.base.call(this)&&(this._view&&this._view.remove(),!0)},getView:function(){return this._view},getCurrentStyle:function(){return this._currentStyle},setCurrentStyle:function(t){this._currentStyle.initialize(t)},getIndex:function(){return this._index},getOptions:function(){return this._scope.settings},getLayers:function(){return this._children},getActiveLayer:function(){return this._activeLayer||new b({project:this,insert:!0})},getSymbolDefinitions:function(){var t=[],e={};return this.getItems({"class":k,match:function(n){var i=n._definition,r=i._id;return e[r]||(e[r]=!0,t.push(i)),!1}}),t},getSymbols:"getSymbolDefinitions",getSelectedItems:function(){var t=this._selectionItems,e=[];for(var n in t){var i=t[n],r=i._selection;1&r&&i.isInserted()?e.push(i):r||this._updateSelection(i)}return e},_updateSelection:function(t){var e=t._id,n=this._selectionItems;t._selection?n[e]!==t&&(this._selectionCount++,n[e]=t):n[e]===t&&(this._selectionCount--,delete n[e])},selectAll:function(){for(var t=this._children,e=0,n=t.length;e<n;e++)t[e].setFullySelected(!0)},deselectAll:function(){var t=this._selectionItems;for(var e in t)t[e].setFullySelected(!1)},addLayer:function(t){return this.insertLayer(e,t)},insertLayer:function(t,e){if(e instanceof b){e._remove(!1,!0),r.splice(this._children,[e],t,0),e._setProject(this,!0);var n=e._name;n&&e.setName(n),this._changes&&e._changed(5),this._activeLayer||(this._activeLayer=e)}else e=null;return e},_insertItem:function(t,n,i,r){return n=this.insertLayer(t,n)||(this._activeLayer||this._insertItem(e,new b(w.NO_INSERT),!0,!0)).insertChild(t,n,i),r&&n.activate&&n.activate(),n},getItems:function(t){return w._getItems(this,t)},getItem:function(t){return w._getItems(this,t,null,null,!0)[0]||null},importJSON:function(t){this.activate();var e=this._activeLayer;return r.importJSON(t,e&&e.isEmpty()&&e)},removeOn:function(t){var e=this._removeSets;if(e){"mouseup"===t&&(e.mousedrag=null);var n=e[t];if(n){for(var i in n){var r=n[i];for(var s in e){var a=e[s];a&&a!=n&&delete a[r._id]}r.remove()}e[t]=null}}},draw:function(t,e,n){this._updateVersion++,t.save(),e.applyToContext(t);for(var i=this._children,s=new r({offset:new c(0,0),pixelRatio:n,viewMatrix:e.isIdentity()?null:e,matrices:[new p],updateMatrix:!0}),a=0,o=i.length;a<o;a++)i[a].draw(t,s);if(t.restore(),this._selectionCount>0){t.save(),t.strokeWidth=1;var h=this._selectionItems,u=this._scope.settings.handleSize,l=this._updateVersion;for(var f in h)h[f]._drawSelection(t,e,u,h,l);t.restore()}}}),w=r.extend(s,{statics:{extend:function ut(t){return t._serializeFields&&(t._serializeFields=r.set({},this.prototype._serializeFields,t._serializeFields)),ut.base.apply(this,arguments)},NO_INSERT:{insert:!1}},_class:"Item",_name:null,_applyMatrix:!0,_canApplyMatrix:!0,_canScaleStroke:!1,_pivot:null,_visible:!0,_blendMode:"normal",_opacity:1,_locked:!1,_guide:!1,_clipMask:!1,_selection:0,_selectBounds:!0,_selectChildren:!1,_serializeFields:{name:null,applyMatrix:null,matrix:new p,pivot:null,visible:!0,blendMode:"normal",opacity:1,locked:!1,guide:!1,clipMask:!1,selected:!1,data:{}}},new function(){var t=["onMouseDown","onMouseUp","onMouseDrag","onClick","onDoubleClick","onMouseMove","onMouseEnter","onMouseLeave"];return r.each(t,function(t){this._events[t]={install:function(t){this.getView()._countItemEvent(t,1)},uninstall:function(t){this.getView()._countItemEvent(t,-1)}}},{_events:{onFrame:{install:function(){this.getView()._animateItem(this,!0)},uninstall:function(){this.getView()._animateItem(this,!1)}},onLoad:{},onError:{}},statics:{_itemHandlers:t}})},{initialize:function(){},_initialize:function(t,n){var i=t&&r.isPlainObject(t),s=i&&t.internal===!0,a=this._matrix=new p,o=i&&t.project||paper.project,h=paper.settings;return this._id=s?null:l.get(),this._parent=this._index=null,this._applyMatrix=this._canApplyMatrix&&h.applyMatrix,n&&a.translate(n),a._owner=this,this._style=new V(o._currentStyle,this,o),s||i&&t.insert===!1||!h.insertItems&&(!i||t.insert!==!0)?this._setProject(o):(i&&t.parent||o)._insertItem(e,this,!0,!0),i&&t!==w.NO_INSERT&&r.filter(this,t,{internal:!0,insert:!0,project:!0,parent:!0}),i},_serialize:function(t,e){function n(n){for(var a in n){var o=s[a];r.equals(o,"leading"===a?1.2*n.fontSize:n[a])||(i[a]=r.serialize(o,t,"data"!==a,e))}}var i={},s=this;return n(this._serializeFields),this instanceof x||n(this._style._defaults),[this._class,i]},_changed:function(t){var n=this._symbol,i=this._parent||n,r=this._project;8&t&&(this._bounds=this._position=this._decomposed=this._globalMatrix=e),i&&40&t&&w._clearBoundsCache(i),2&t&&w._clearBoundsCache(this),r&&r._changed(t,this),n&&n._changed(t)},set:function(t){return t&&this._set(t),this},getId:function(){return this._id},getName:function(){return this._name},setName:function(t){if(this._name&&this._removeNamed(),t===+t+"")throw new Error("Names consisting only of numbers are not supported.");var n=this._getOwner();if(t&&n){var i=n._children,r=n._namedChildren;(r[t]=r[t]||[]).push(this),t in i||(i[t]=this)}this._name=t||e,this._changed(128)},getStyle:function(){return this._style},setStyle:function(t){this.getStyle().set(t)}},r.each(["locked","visible","blendMode","opacity","guide"],function(t){var e=r.capitalize(t),t="_"+t;this["get"+e]=function(){return this[t]},this["set"+e]=function(e){e!=this[t]&&(this[t]=e,this._changed("_locked"===t?128:129))}},{}),{beans:!0,getSelection:function(){return this._selection},setSelection:function(t){if(t!==this._selection){this._selection=t;var e=this._project;e&&(e._updateSelection(this),this._changed(129))}},changeSelection:function(t,e){var n=this._selection;this.setSelection(e?n|t:n&~t)},isSelected:function(){if(this._selectChildren)for(var t=this._children,e=0,n=t.length;e<n;e++)if(t[e].isSelected())return!0;return!!(1&this._selection)},setSelected:function(t){if(this._selectChildren)for(var e=this._children,n=0,i=e.length;n<i;n++)e[n].setSelected(t);this.changeSelection(1,t)},isFullySelected:function(){var t=this._children,e=!!(1&this._selection);if(t&&e){for(var n=0,i=t.length;n<i;n++)if(!t[n].isFullySelected())return!1;return!0}return e},setFullySelected:function(t){var e=this._children;if(e)for(var n=0,i=e.length;n<i;n++)e[n].setFullySelected(t);this.changeSelection(1,t)},isClipMask:function(){return this._clipMask},setClipMask:function(t){this._clipMask!=(t=!!t)&&(this._clipMask=t,t&&(this.setFillColor(null),this.setStrokeColor(null)),this._changed(129),this._parent&&this._parent._changed(1024))},getData:function(){return this._data||(this._data={}),this._data},setData:function(t){this._data=t},getPosition:function(t){var e=this._position,n=t?c:f;if(!e){var i=this._pivot;e=this._position=i?this._matrix._transformPoint(i):this.getBounds().getCenter(!0)}return new n(e.x,e.y,this,"setPosition")},setPosition:function(){this.translate(c.read(arguments).subtract(this.getPosition(!0)))},getPivot:function(t){var e=this._pivot;if(e){var n=t?c:f;e=new n(e.x,e.y,this,"setPivot")}return e},setPivot:function(){this._pivot=c.read(arguments,0,{clone:!0,readNull:!0}),this._position=e}},r.each({getStrokeBounds:{stroke:!0},getHandleBounds:{handle:!0},getInternalBounds:{internal:!0}},function(t,e){this[e]=function(e){return this.getBounds(e,t)}},{beans:!0,getBounds:function(t,e){var n=e||t instanceof p,i=r.set({},n?e:t,this._boundsOptions);i.stroke&&!this.getStrokeScaling()||(i.cacheItem=this);var s=this._getCachedBounds(n&&t,i);return 0===arguments.length?new v(s.x,s.y,s.width,s.height,this,"setBounds"):s},setBounds:function(){var t=g.read(arguments),e=this.getBounds(),n=this._matrix,i=new p,r=t.getCenter();i.translate(r),t.width==e.width&&t.height==e.height||(n.isInvertible()||(n.initialize(n._backup||(new p).translate(n.getTranslation())),e=this.getBounds()),i.scale(0!==e.width?t.width/e.width:0,0!==e.height?t.height/e.height:0)),r=e.getCenter(),i.translate(-r.x,-r.y),this.transform(i)},_getBounds:function(t,e){var n=this._children;return n&&0!==n.length?(w._updateBoundsCache(this,e.cacheItem),w._getBounds(n,t,e)):new g},_getCachedBounds:function(t,e){t=t&&t._orNullIfIdentity();var n=e.internal,i=e.cacheItem,r=n?null:this._matrix._orNullIfIdentity(),s=i&&(!t||t.equals(r))&&[e.stroke?1:0,e.handle?1:0,n?1:0].join("");if(w._updateBoundsCache(this._parent||this._symbol,i),s&&this._bounds&&s in this._bounds)return this._bounds[s].rect.clone();var a=this._getBounds(t||r,e);if(s){this._bounds||(this._bounds={});this._bounds[s]={rect:a.clone(),internal:e.internal}}return a},_getStrokeMatrix:function(t,e){var n=this.getStrokeScaling()?null:e&&e.internal?this:this._parent||this._symbol&&this._symbol._item,i=n?n.getViewMatrix().invert():t;return i&&i._shiftless()},statics:{_updateBoundsCache:function(t,e){if(t&&e){var n=e._id,i=t._boundsCache=t._boundsCache||{ids:{},list:[]};i.ids[n]||(i.list.push(e),i.ids[n]=e)}},_clearBoundsCache:function(t){var n=t._boundsCache;if(n){t._bounds=t._position=t._boundsCache=e;for(var i=0,r=n.list,s=r.length;i<s;i++){var a=r[i];a!==t&&(a._bounds=a._position=e,a._boundsCache&&w._clearBoundsCache(a))}}},_getBounds:function(t,e,n){var i=1/0,r=-i,s=i,a=r;n=n||{};for(var o=0,h=t.length;o<h;o++){var u=t[o];if(u._visible&&!u.isEmpty()){var l=u._getCachedBounds(e&&e.appended(u._matrix),n);i=Math.min(l.x,i),s=Math.min(l.y,s),r=Math.max(l.x+l.width,r),a=Math.max(l.y+l.height,a)}}return isFinite(i)?new g(i,s,r-i,a-s):new g}}}),{beans:!0,_decompose:function(){return this._decomposed||(this._decomposed=this._matrix.decompose())},getRotation:function(){var t=this._decompose();return t&&t.rotation},setRotation:function(t){var e=this.getRotation();null!=e&&null!=t&&this.rotate(t-e)},getScaling:function(t){var e=this._decompose(),n=e&&e.scaling,i=t?c:f;return n&&new i(n.x,n.y,this,"setScaling")},setScaling:function(){var t=this.getScaling(),e=c.read(arguments,0,{clone:!0,readNull:!0});t&&e&&this.scale(e.x/t.x,e.y/t.y)},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},getGlobalMatrix:function(t){var e=this._globalMatrix,n=this._project._updateVersion;if(e&&e._updateVersion!==n&&(e=null),!e){e=this._globalMatrix=this._matrix.clone();var i=this._parent;i&&e.prepend(i.getGlobalMatrix(!0)),e._updateVersion=n}return t?e:e.clone()},getViewMatrix:function(){return this.getGlobalMatrix().prepend(this.getView()._matrix)},getApplyMatrix:function(){return this._applyMatrix},setApplyMatrix:function(t){(this._applyMatrix=this._canApplyMatrix&&!!t)&&this.transform(null,!0)},getTransformContent:"#getApplyMatrix",setTransformContent:"#setApplyMatrix"},{getProject:function(){return this._project},_setProject:function(t,e){if(this._project!==t){this._project&&this._installEvents(!1),this._project=t;for(var n=this._children,i=0,r=n&&n.length;i<r;i++)n[i]._setProject(t);e=!0}e&&this._installEvents(!0)},getView:function(){return this._project._view},_installEvents:function lt(t){lt.base.call(this,t);for(var e=this._children,n=0,i=e&&e.length;n<i;n++)e[n]._installEvents(t)},getLayer:function(){for(var t=this;t=t._parent;)if(t instanceof b)return t;return null},getParent:function(){return this._parent},setParent:function(t){return t.addChild(this)},_getOwner:"#getParent",getChildren:function(){return this._children},setChildren:function(t,e){this.removeChildren(),this.addChildren(t,e)},getFirstChild:function(){return this._children&&this._children[0]||null},getLastChild:function(){return this._children&&this._children[this._children.length-1]||null},getNextSibling:function(){var t=this._getOwner();return t&&t._children[this._index+1]||null},getPreviousSibling:function(){var t=this._getOwner();return t&&t._children[this._index-1]||null},getIndex:function(){return this._index},equals:function(t){return t===this||t&&this._class===t._class&&this._style.equals(t._style)&&this._matrix.equals(t._matrix)&&this._locked===t._locked&&this._visible===t._visible&&this._blendMode===t._blendMode&&this._opacity===t._opacity&&this._clipMask===t._clipMask&&this._guide===t._guide&&this._equals(t)||!1},_equals:function(t){return r.equals(this._children,t._children)},clone:function(t){var n=new this.constructor(w.NO_INSERT),i=this._children,s=r.pick(t?t.insert:e,t===e||t===!0),a=r.pick(t?t.deep:e,!0);i&&n.copyAttributes(this),i&&!a||n.copyContent(this),i||n.copyAttributes(this),s&&n.insertAbove(this);var o=this._name,h=this._parent;if(o&&h){for(var i=h._children,u=o,l=1;i[o];)o=u+" "+l++;o!==u&&n.setName(o)}return n},copyContent:function(t){for(var e=t._children,n=0,i=e&&e.length;n<i;n++)this.addChild(e[n].clone(!1),!0)},copyAttributes:function(t,e){this.setStyle(t._style);for(var n=["_locked","_visible","_blendMode","_opacity","_clipMask","_guide"],i=0,s=n.length;i<s;i++){var a=n[i];t.hasOwnProperty(a)&&(this[a]=t[a])}e||this._matrix.initialize(t._matrix),this.setApplyMatrix(t._applyMatrix),this.setPivot(t._pivot),this.setSelection(t._selection);var o=t._data,h=t._name;this._data=o?r.clone(o):null,h&&this.setName(h)},rasterize:function(t,n){var i=this.getStrokeBounds(),s=(t||this.getView().getResolution())/72,a=i.getTopLeft().floor(),o=i.getBottomRight().ceil(),h=new d(o.subtract(a)),u=new S(w.NO_INSERT);if(!h.isZero()){var l=tt.getCanvas(h.multiply(s)),c=l.getContext("2d"),f=(new p).scale(s).translate(a.negate());c.save(),f.applyToContext(c),this.draw(c,new r({matrices:[f]})),c.restore(),u.setCanvas(l)}return u.transform((new p).translate(a.add(h.divide(2))).scale(1/s)),(n===e||n)&&u.insertAbove(this),u},contains:function(){return!!this._contains(this._matrix._inverseTransform(c.read(arguments)))},_contains:function(t){var e=this._children;if(e){for(var n=e.length-1;n>=0;n--)if(e[n].contains(t))return!0;return!1}return t.isInside(this.getInternalBounds())},isInside:function(){return g.read(arguments).contains(this.getBounds())},_asPathItem:function(){return new E.Rectangle({rectangle:this.getInternalBounds(),matrix:this._matrix,insert:!1})},intersects:function(t,e){return t instanceof w&&this._asPathItem().getIntersections(t._asPathItem(),null,e,!0).length>0}},new function(){function t(){return this._hitTest(c.read(arguments),P.getOptions(arguments))}function e(){var t=c.read(arguments),e=P.getOptions(arguments),n=e.match,i=[];return e=r.set({},e,{match:function(t){n&&!n(t)||i.push(t)}}),this._hitTest(t,e),i}function n(t,e,n,i){var r=this._children;if(r)for(var s=r.length-1;s>=0;s--){var a=r[s],o=a!==i&&a._hitTest(t,e,n);if(o)return o}return null}return y.inject({hitTest:t,hitTestAll:e,_hitTest:n}),{hitTest:t,hitTestAll:e,_hitTestChildren:n}},{_hitTest:function(t,e,n){function i(t){return!g||t&&g(t)?t:null}function s(e,n){var i=c["get"+n]();if(t.subtract(i).divide(l).length<=1)return new P(e,v,{name:r.hyphenate(n),point:i})}if(this._locked||!this._visible||this._guide&&!e.guides||this.isEmpty())return null;var a=this._matrix,o=n?n.appended(a):this.getGlobalMatrix().prepend(this.getView()._matrix),h=this.getStrokeScaling()?null:o.inverted()._shiftless(),u=Math.max(e.tolerance,1e-6),l=e._tolerancePadding=new d(E._getStrokePadding(u,h));if(t=a._inverseTransform(t),!t||!this._children&&!this.getBounds({internal:!0,stroke:!0,handle:!0}).expand(l.multiply(2))._containsPoint(t))return null;var c,f,_=!(e.guides&&!this._guide||e.selected&&!this.isSelected()||e.type&&e.type!==r.hyphenate(this._class)||e["class"]&&!(this instanceof e["class"])),g=e.match,v=this;if(_&&(e.center||e.bounds)&&this._parent){if(c=this.getInternalBounds(),e.center&&(f=s("center","Center")),!f&&e.bounds)for(var p=["TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],m=0;m<8&&!f;m++)f=s("bounds",p[m]);f=i(f)}return f||(f=this._hitTestChildren(t,e,o)||_&&i(this._hitTestSelf(t,e,o,h))||null),f&&f.point&&(f.point=a.transform(f.point)),f},_hitTestSelf:function(t,e){if(e.fill&&this.hasFill()&&this._contains(t))return new P("fill",this)},matches:function(t,e){function n(t,e){for(var i in t)if(t.hasOwnProperty(i)){var s=t[i],a=e[i];if(r.isPlainObject(s)&&r.isPlainObject(a)){if(!n(s,a))return!1}else if(!r.equals(s,a))return!1}return!0}var i=typeof t;if("object"===i){for(var s in t)if(t.hasOwnProperty(s)&&!this.matches(s,t[s]))return!1;return!0}if("function"===i)return t(this);if("match"===t)return e(this);var a=/^(empty|editable)$/.test(t)?this["is"+r.capitalize(t)]():"type"===t?r.hyphenate(this._class):this[t];if("class"===t){if("function"==typeof e)return this instanceof e;a=this._class}if("function"==typeof e)return!!e(a);if(e){if(e.test)return e.test(a);if(r.isPlainObject(e))return n(e,a)}return r.equals(a,e)},getItems:function(t){return w._getItems(this,t,this._matrix)},getItem:function(t){return w._getItems(this,t,this._matrix,null,!0)[0]||null},statics:{_getItems:function ct(t,e,n,i,s){if(!i){var a="object"==typeof e&&e,o=a&&a.overlapping,h=a&&a.inside,u=o||h,l=u&&g.read([u]);i={items:[],recursive:a&&a.recursive!==!1,inside:!!h,overlapping:!!o,rect:l,path:o&&new E.Rectangle({rectangle:l,insert:!1})},a&&(e=r.filter({},e,{recursive:!0,inside:!0,overlapping:!0}))}var c=t._children,f=i.items,l=i.rect;n=l&&(n||new p);for(var d=0,_=c&&c.length;d<_;d++){var v=c[d],m=n&&n.appended(v._matrix),y=!0;if(l){var u=v.getBounds(m);if(!l.intersects(u))continue;l.contains(u)||i.overlapping&&(u.contains(l)||i.path.intersects(v,m))||(y=!1)}if(y&&v.matches(e)&&(f.push(v),s))break;if(i.recursive!==!1&&ct(v,e,m,i,s),s&&f.length>0)break}return f}}},{importJSON:function(t){var e=r.importJSON(t,this);return e!==this?this.addChild(e):e},addChild:function(t,n){return this.insertChild(e,t,n)},insertChild:function(t,e,n){var i=e?this.insertChildren(t,[e],n):null;return i&&i[0]},addChildren:function(t,e){return this.insertChildren(this._children.length,t,e)},insertChildren:function(t,e,n,i){var s=this._children;if(s&&e&&e.length>0){e=Array.prototype.slice.apply(e);for(var a=e.length-1;a>=0;a--){var o=e[a];o&&(!i||o instanceof i)?o._remove(!1,!0):e.splice(a,1)}r.splice(s,e,t,0);for(var h=this._project,u=h._changes,a=0,l=e.length;a<l;a++){var o=e[a],c=o._name;o._parent=this,o._setProject(h,!0),c&&o.setName(c),u&&this._changed(5)}this._changed(11)}else e=null;return e},_insertItem:"#insertChild",_insertAt:function(t,e,n){var i=this;if(i!==t){var r=t&&t._getOwner();r?(i._remove(!1,!0),r._insertItem(t._index+e,i,n)):i=null}return i},insertAbove:function(t,e){return this._insertAt(t,1,e)},insertBelow:function(t,e){return this._insertAt(t,0,e)},sendToBack:function(){var t=this._getOwner();return t?t._insertItem(0,this):null},bringToFront:function(){var t=this._getOwner();return t?t._insertItem(e,this):null},appendTop:"#addChild",appendBottom:function(t){return this.insertChild(0,t)},moveAbove:"#insertAbove",moveBelow:"#insertBelow",copyTo:function(t){return t._insertItem(e,this.clone(!1))},reduce:function(t){var e=this._children;if(e&&1===e.length){var n=e[0].reduce(t);return this._parent?(n.insertAbove(this),this.remove()):n.remove(),n}return this},_removeNamed:function(){var t=this._getOwner();if(t){var e=t._children,n=t._namedChildren,i=this._name,r=n[i],s=r?r.indexOf(this):-1;s!==-1&&(e[i]==this&&delete e[i],r.splice(s,1),r.length?e[i]=r[0]:delete n[i])}},_remove:function(t,e){var n=this._getOwner(),i=this._project,s=this._index;return!!n&&(null!=s&&(i._activeLayer===this&&(i._activeLayer=this.getNextSibling()||this.getPreviousSibling()),r.splice(n._children,null,s,1)),this._name&&this._removeNamed(),this._installEvents(!1),t&&i._changes&&this._changed(5),e&&n._changed(11,this),this._parent=null,!0)},remove:function(){return this._remove(!0,!0)},replaceWith:function(t){var e=t&&t.insertBelow(this);return e&&this.remove(),e},removeChildren:function(t,e){if(!this._children)return null;t=t||0,e=r.pick(e,this._children.length);for(var n=r.splice(this._children,null,t,e-t),i=n.length-1;i>=0;i--)n[i]._remove(!0,!1);return n.length>0&&this._changed(11),n},clear:"#removeChildren",reverseChildren:function(){if(this._children){this._children.reverse();for(var t=0,e=this._children.length;t<e;t++)this._children[t]._index=t;this._changed(11)}},isEmpty:function(){return!this._children||0===this._children.length},isEditable:function(){for(var t=this;t;){if(!t._visible||t._locked)return!1;t=t._parent}return!0},hasFill:function(){return this.getStyle().hasFill()},hasStroke:function(){return this.getStyle().hasStroke()},hasShadow:function(){return this.getStyle().hasShadow()},_getOrder:function(t){function e(t){var e=[];do e.unshift(t);while(t=t._parent);return e}for(var n=e(this),i=e(t),r=0,s=Math.min(n.length,i.length);r<s;r++)if(n[r]!=i[r])return n[r]._index<i[r]._index?1:-1;return 0},hasChildren:function(){return this._children&&this._children.length>0},isInserted:function(){return!!this._parent&&this._parent.isInserted()},isAbove:function(t){return this._getOrder(t)===-1},isBelow:function(t){return 1===this._getOrder(t)},isParent:function(t){return this._parent===t},isChild:function(t){return t&&t._parent===this},isDescendant:function(t){for(var e=this;e=e._parent;)if(e===t)return!0;return!1},isAncestor:function(t){return!!t&&t.isDescendant(this)},isSibling:function(t){return this._parent===t._parent},isGroupedWith:function(t){for(var e=this._parent;e;){if(e._parent&&/^(Group|Layer|CompoundPath)$/.test(e._class)&&t.isDescendant(e))return!0;e=e._parent}return!1}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var n=(e?r:c).read(arguments),i=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](n,i||this.getPosition(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t,e,n,i){t&&t.isIdentity()&&(t=null);var r=this._matrix,s=(e||this._applyMatrix)&&(!r.isIdentity()||t||e&&n&&this._children);if(!t&&!s)return this;if(t&&(!t.isInvertible()&&r.isInvertible()&&(r._backup=r.getValues()),r.prepend(t)),s=s&&this._transformContent(r,n,i)){var a=this._pivot,o=this._style,h=o.getFillColor(!0),u=o.getStrokeColor(!0);a&&r._transformPoint(a,a,!0),h&&h.transform(r),u&&u.transform(r),r.reset(!0),i&&this._canApplyMatrix&&(this._applyMatrix=!0)}var l=this._bounds,c=this._position;this._changed(9);var f=l&&t&&t.decompose();if(f&&!f.shearing&&f.rotation%90===0){for(var d in l){var _=l[d];if(s||!_.internal){var g=_.rect;t._transformBounds(g,g)}}var v=this._boundsGetter,g=l[v&&v.getBounds||v||"getBounds"];g&&(this._position=g.getCenter(!0)),this._bounds=l}else t&&c&&(this._position=t._transformPoint(c,c));return this},_transformContent:function(t,e,n){var i=this._children;if(i){for(var r=0,s=i.length;r<s;r++)i[r].transform(t,!0,e,n);return!0}},globalToLocal:function(){return this.getGlobalMatrix(!0)._inverseTransform(c.read(arguments))},localToGlobal:function(){return this.getGlobalMatrix(!0)._transformPoint(c.read(arguments))},parentToLocal:function(){return this._matrix._inverseTransform(c.read(arguments))},localToParent:function(){return this._matrix._transformPoint(c.read(arguments))},fitBounds:function(t,e){t=g.read(arguments);var n=this.getBounds(),i=n.height/n.width,r=t.height/t.width,s=(e?i>r:i<r)?t.width/n.width:t.height/n.height,a=new g(new c,new d(n.width*s,n.height*s));a.setCenter(t.getCenter()),this.setBounds(a)}}),{_setStyles:function(t,e,n){var i=this._style;if(i.hasFill()&&(t.fillStyle=i.getFillColor().toCanvasStyle(t)),i.hasStroke()){t.strokeStyle=i.getStrokeColor().toCanvasStyle(t),t.lineWidth=i.getStrokeWidth();var r=i.getStrokeJoin(),s=i.getStrokeCap(),a=i.getMiterLimit();if(r&&(t.lineJoin=r),s&&(t.lineCap=s),a&&(t.miterLimit=a),paper.support.nativeDash){var o=i.getDashArray(),h=i.getDashOffset();o&&o.length&&("setLineDash"in t?(t.setLineDash(o),t.lineDashOffset=h):(t.mozDash=o,t.mozDashOffset=h))}}if(i.hasShadow()){var u=e.pixelRatio||1,l=n._shiftless().prepend((new p).scale(u,u)),f=l.transform(new c(i.getShadowBlur(),0)),d=l.transform(this.getShadowOffset());t.shadowColor=i.getShadowColor().toCanvasStyle(t),t.shadowBlur=f.getLength(),t.shadowOffsetX=d.x,t.shadowOffsetY=d.y}},draw:function(t,e,n){var i=this._updateVersion=this._project._updateVersion;if(this._visible&&0!==this._opacity){var r=e.matrices,s=e.viewMatrix,a=this._matrix,o=r[r.length-1].appended(a);if(o.isInvertible()){s=s?s.appended(o):o,r.push(o),e.updateMatrix&&(o._updateVersion=i,this._globalMatrix=o);var h,u,l,c=this._blendMode,f=this._opacity,d="normal"===c,_=et.nativeModes[c],g=d&&1===f||e.dontStart||e.clip||(_||d&&f<1)&&this._canComposite(),v=e.pixelRatio||1;if(!g){var p=this.getStrokeBounds(s);if(!p.width||!p.height)return;l=e.offset,u=e.offset=p.getTopLeft().floor(),h=t,t=tt.getContext(p.getSize().ceil().add(1).multiply(v)),1!==v&&t.scale(v,v)}t.save();var m=n?n.appended(a):this._canScaleStroke&&!this.getStrokeScaling(!0)&&s,y=!g&&e.clipItem,w=!m||y;if(g?(t.globalAlpha=f,_&&(t.globalCompositeOperation=c)):w&&t.translate(-u.x,-u.y),w&&(g?a:s).applyToContext(t),y&&e.clipItem.draw(t,e.extend({clip:!0})),m){t.setTransform(v,0,0,v,0,0);var x=e.offset;x&&t.translate(-x.x,-x.y)}this._draw(t,e,s,m),t.restore(),r.pop(),e.clip&&!e.dontFinish&&t.clip(),g||(et.process(c,t,h,f,u.subtract(l).multiply(v)),tt.release(t),e.offset=l)}}},_isUpdated:function(t){var e=this._parent;if(e instanceof L)return e._isUpdated(t);var n=this._updateVersion===t;return!n&&e&&e._visible&&e._isUpdated(t)&&(this._updateVersion=t,n=!0),n},_drawSelection:function(t,e,n,i,r){var s=this._selection,a=1&s,o=2&s||a&&this._selectBounds,h=4&s;if(this._drawSelected||(a=!1),
+(a||o||h)&&this._isUpdated(r)){var u,l=this.getSelectedColor(!0)||(u=this.getLayer())&&u.getSelectedColor(!0),c=e.appended(this.getGlobalMatrix(!0)),f=n/2;if(t.strokeStyle=t.fillStyle=l?l.toCanvasStyle(t):"#009dec",a&&this._drawSelected(t,c,i),h){var d=this.getPosition(!0),_=d.x,g=d.y;t.beginPath(),t.arc(_,g,f,0,2*Math.PI,!0),t.stroke();for(var v=[[0,-1],[1,0],[0,1],[-1,0]],p=f,m=n+1,y=0;y<4;y++){var w=v[y],x=w[0],b=w[1];t.moveTo(_+x*p,g+b*p),t.lineTo(_+x*m,g+b*m),t.stroke()}}if(o){var C=c._transformCorners(this.getInternalBounds());t.beginPath();for(var y=0;y<8;y++)t[0===y?"moveTo":"lineTo"](C[y],C[++y]);t.closePath(),t.stroke();for(var y=0;y<8;y++)t.fillRect(C[y]-f,C[++y]-f,n,n)}}},_canComposite:function(){return!1}},r.each(["down","drag","up","move"],function(t){this["removeOn"+r.capitalize(t)]=function(){var e={};return e[t]=!0,this.removeOn(e)}},{removeOn:function(t){for(var e in t)if(t[e]){var n="mouse"+e,i=this._project,r=i._removeSets=i._removeSets||{};r[n]=r[n]||{},r[n][this._id]=this}return this}})),x=w.extend({_class:"Group",_selectBounds:!1,_selectChildren:!0,_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||this.addChildren(Array.isArray(t)?t:arguments)},_changed:function ft(t){ft.base.call(this,t),1026&t&&(this._clipItem=e)},_getClipItem:function(){var t=this._clipItem;if(t===e){t=null;for(var n=this._children,i=0,r=n.length;i<r;i++)if(n[i]._clipMask){t=n[i];break}this._clipItem=t}return t},isClipped:function(){return!!this._getClipItem()},setClipped:function(t){var e=this.getFirstChild();e&&e.setClipMask(t)},_getBounds:function dt(t,e){var n=this._getClipItem();return n?n._getCachedBounds(t&&t.appended(n._matrix),r.set({},e,{stroke:!1})):dt.base.call(this,t,e)},_hitTestChildren:function _t(t,e,n){var i=this._getClipItem();return(!i||i.contains(t))&&_t.base.call(this,t,e,n,i)},_draw:function(t,e){var n=e.clip,i=!n&&this._getClipItem();e=e.extend({clipItem:i,clip:!1}),n?(t.beginPath(),e.dontStart=e.dontFinish=!0):i&&i.draw(t,e.extend({clip:!0}));for(var r=this._children,s=0,a=r.length;s<a;s++){var o=r[s];o!==i&&o.draw(t,e)}}}),b=x.extend({_class:"Layer",initialize:function(){x.apply(this,arguments)},_getOwner:function(){return this._parent||null!=this._index&&this._project},isInserted:function gt(){return this._parent?gt.base.call(this):null!=this._index},activate:function(){this._project._activeLayer=this},_hitTestSelf:function(){}}),C=w.extend({_class:"Shape",_applyMatrix:!1,_canApplyMatrix:!1,_canScaleStroke:!0,_serializeFields:{type:null,size:null,radius:null},initialize:function(t){this._initialize(t)},_equals:function(t){return this._type===t._type&&this._size.equals(t._size)&&r.equals(this._radius,t._radius)},copyContent:function(t){this.setType(t._type),this.setSize(t._size),this.setRadius(t._radius)},getType:function(){return this._type},setType:function(t){this._type=t},getShape:"#getType",setShape:"#setType",getSize:function(){var t=this._size;return new _(t.width,t.height,this,"setSize")},setSize:function(){var t=d.read(arguments);if(this._size){if(!this._size.equals(t)){var e=this._type,n=t.width,i=t.height;if("rectangle"===e){var r=d.min(this._radius,t.divide(2));this._radius.set(r.width,r.height)}else"circle"===e?(n=i=(n+i)/2,this._radius=n/2):"ellipse"===e&&this._radius.set(n/2,i/2);this._size.set(n,i),this._changed(9)}}else this._size=t.clone()},getRadius:function(){var t=this._radius;return"circle"===this._type?t:new _(t.width,t.height,this,"setRadius")},setRadius:function(t){var e=this._type;if("circle"===e){if(t===this._radius)return;var n=2*t;this._radius=t,this._size.set(n,n)}else if(t=d.read(arguments),this._radius){if(this._radius.equals(t))return;if(this._radius.set(t.width,t.height),"rectangle"===e){var n=d.max(this._size,t.multiply(2));this._size.set(n.width,n.height)}else"ellipse"===e&&this._size.set(2*t.width,2*t.height)}else this._radius=t.clone();this._changed(9)},isEmpty:function(){return!1},toPath:function(t){var n=new(E[r.capitalize(this._type)])({center:new c,size:this._size,radius:this._radius,insert:!1});return n.copyAttributes(this),paper.settings.applyMatrix&&n.setApplyMatrix(!0),(t===e||t)&&n.insertAbove(this),n},toShape:"#clone",_draw:function(t,e,n,i){var r=this._style,s=r.hasFill(),a=r.hasStroke(),o=e.dontFinish||e.clip,h=!i;if(s||a||o){var u=this._type,l=this._radius,c="circle"===u;if(e.dontStart||t.beginPath(),h&&c)t.arc(0,0,l,0,2*Math.PI,!0);else{var f=c?l:l.width,d=c?l:l.height,_=this._size,g=_.width,v=_.height;if(h&&"rectangle"===u&&0===f&&0===d)t.rect(-g/2,-v/2,g,v);else{var p=g/2,m=v/2,y=.44771525016920644,w=f*y,x=d*y,b=[-p,-m+d,-p,-m+x,-p+w,-m,-p+f,-m,p-f,-m,p-w,-m,p,-m+x,p,-m+d,p,m-d,p,m-x,p-w,m,p-f,m,-p+f,m,-p+w,m,-p,m-x,-p,m-d];i&&i.transform(b,b,32),t.moveTo(b[0],b[1]),t.bezierCurveTo(b[2],b[3],b[4],b[5],b[6],b[7]),p!==f&&t.lineTo(b[8],b[9]),t.bezierCurveTo(b[10],b[11],b[12],b[13],b[14],b[15]),m!==d&&t.lineTo(b[16],b[17]),t.bezierCurveTo(b[18],b[19],b[20],b[21],b[22],b[23]),p!==f&&t.lineTo(b[24],b[25]),t.bezierCurveTo(b[26],b[27],b[28],b[29],b[30],b[31])}}t.closePath()}o||!s&&!a||(this._setStyles(t,e,n),s&&(t.fill(r.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),a&&t.stroke())},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_getBounds:function(t,e){var n=new g(this._size).setCenter(0,0),i=this._style,r=e.stroke&&i.hasStroke()&&i.getStrokeWidth();return t&&(n=t._transformBounds(n)),r?n.expand(E._getStrokePadding(r,this._getStrokeMatrix(t,e))):n}},new function(){function t(t,e,n){var i=t._radius;if(!i.isZero())for(var r=t._size.divide(2),s=0;s<4;s++){var a=new c(1&s?1:-1,s>1?1:-1),o=a.multiply(r),h=o.subtract(a.multiply(i)),u=new g(o,h);if((n?u.expand(n):u).contains(e))return h}}function e(t,e,n,i){var r=t.divide(e);return(!i||r.quadrant===i)&&r.subtract(r.normalize()).multiply(e).divide(n).length<=1}return{_contains:function n(e){if("rectangle"===this._type){var i=t(this,e);return i?e.subtract(i).divide(this._radius).getLength()<=1:n.base.call(this,e)}return e.divide(this.size).getLength()<=.5},_hitTestSelf:function i(n,r,s,a){var o=!1,h=this._style,u=r.stroke&&h.hasStroke(),l=r.fill&&h.hasFill();if(u||l){var c=this._type,f=this._radius,d=u?h.getStrokeWidth()/2:0,_=r._tolerancePadding.add(E._getStrokePadding(d,!h.getStrokeScaling()&&a));if("rectangle"===c){var v=_.multiply(2),p=t(this,n,v);if(p)o=e(n.subtract(p),f,_,p.getQuadrant());else{var m=new g(this._size).setCenter(0,0),y=m.expand(v),w=m.expand(v.negate());o=y._containsPoint(n)&&!w._containsPoint(n)}}else o=e(n,f,_)}return o?new P(u?"stroke":"fill",this):i.base.apply(this,arguments)}}},{statics:new function(){function t(t,e,n,i,s){var a=new C(r.getNamed(s));return a._type=t,a._size=n,a._radius=i,a.translate(e)}return{Circle:function(){var e=c.readNamed(arguments,"center"),n=r.readNamed(arguments,"radius");return t("circle",e,new d(2*n),n,arguments)},Rectangle:function(){var e=g.readNamed(arguments,"rectangle"),n=d.min(d.readNamed(arguments,"radius"),e.getSize(!0).divide(2));return t("rectangle",e.getCenter(!0),e.getSize(!0),n,arguments)},Ellipse:function(){var e=C._readEllipse(arguments),n=e.radius;return t("ellipse",e.center,n.multiply(2),n,arguments)},_readEllipse:function(t){var e,n;if(r.hasNamed(t,"radius"))e=c.readNamed(t,"center"),n=d.readNamed(t,"radius");else{var i=g.readNamed(t,"rectangle");e=i.getCenter(!0),n=i.getSize(!0).divide(2)}return{center:e,radius:n}}}}}),S=w.extend({_class:"Raster",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!1,handle:!1},_serializeFields:{crossOrigin:null,source:null},initialize:function(t,n){if(!this._initialize(t,n!==e&&c.read(arguments,1))){var r="string"==typeof t?i.getElementById(t):t;r?this.setImage(r):this.setSource(t)}this._size||(this._size=new d,this._loaded=!1)},_equals:function(t){return this.getSource()===t.getSource()},copyContent:function(t){var e=t._image,n=t._canvas;if(e)this._setImage(e);else if(n){var i=tt.getCanvas(t._size);i.getContext("2d").drawImage(n,0,0),this._setImage(i)}this._crossOrigin=t._crossOrigin},getSize:function(){var t=this._size;return new _(t?t.width:0,t?t.height:0,this,"setSize")},setSize:function(){var t=d.read(arguments);if(!t.equals(this._size))if(t.width>0&&t.height>0){var e=this.getElement();this._setImage(tt.getCanvas(t)),e&&this.getContext(!0).drawImage(e,0,0,t.width,t.height)}else this._canvas&&tt.release(this._canvas),this._size=t.clone()},getWidth:function(){return this._size?this._size.width:0},setWidth:function(t){this.setSize(t,this.getHeight())},getHeight:function(){return this._size?this._size.height:0},setHeight:function(t){this.setSize(this.getWidth(),t)},getLoaded:function(){return this._loaded},isEmpty:function(){var t=this._size;return!t||0===t.width&&0===t.height},getResolution:function(){var t=this._matrix,e=new c(0,0).transform(t),n=new c(1,0).transform(t).subtract(e),i=new c(0,1).transform(t).subtract(e);return new d(72/n.getLength(),72/i.getLength())},getPpi:"#getResolution",getImage:function(){return this._image},setImage:function(t){function e(t){var e=n.getView(),i=t&&t.type||"load";e&&n.responds(i)&&(paper=e._scope,n.emit(i,new G(t)))}var n=this;this._setImage(t),this._loaded?setTimeout(e,0):t&&U.add(t,{load:function(i){n._setImage(t),e(i)},error:e})},_setImage:function(t){this._canvas&&tt.release(this._canvas),t&&t.getContext?(this._image=null,this._canvas=t,this._loaded=!0):(this._image=t,this._canvas=null,this._loaded=!!(t&&t.src&&t.complete)),this._size=new d(t?t.naturalWidth||t.width:0,t?t.naturalHeight||t.height:0),this._context=null,this._changed(521)},getCanvas:function(){if(!this._canvas){var t=tt.getContext(this._size);try{this._image&&t.drawImage(this._image,0,0),this._canvas=t.canvas}catch(e){tt.release(t)}}return this._canvas},setCanvas:"#setImage",getContext:function(t){return this._context||(this._context=this.getCanvas().getContext("2d")),t&&(this._image=null,this._changed(513)),this._context},setContext:function(t){this._context=t},getSource:function(){var t=this._image;return t&&t.src||this.toDataURL()},setSource:function(t){var e=new n.Image,i=this._crossOrigin;i&&(e.crossOrigin=i),e.src=t,this.setImage(e)},getCrossOrigin:function(){var t=this._image;return t&&t.crossOrigin||this._crossOrigin||""},setCrossOrigin:function(t){this._crossOrigin=t;var e=this._image;e&&(e.crossOrigin=t)},getElement:function(){return this._canvas||this._loaded&&this._image}},{beans:!1,getSubCanvas:function(){var t=g.read(arguments),e=tt.getContext(t.getSize());return e.drawImage(this.getCanvas(),t.x,t.y,t.width,t.height,0,0,t.width,t.height),e.canvas},getSubRaster:function(){var t=g.read(arguments),e=new S(w.NO_INSERT);return e._setImage(this.getSubCanvas(t)),e.translate(t.getCenter().subtract(this.getSize().divide(2))),e._matrix.prepend(this._matrix),e.insertAbove(this),e},toDataURL:function(){var t=this._image,e=t&&t.src;if(/^data:/.test(e))return e;var n=this.getCanvas();return n?n.toDataURL.apply(n,arguments):null},drawImage:function(t){var e=c.read(arguments,1);this.getContext(!0).drawImage(t,e.x,e.y)},getAverageColor:function(t){var e,n;if(t?t instanceof O?(n=t,e=t.getBounds()):"object"==typeof t&&("width"in t?e=new g(t):"x"in t&&(e=new g(t.x-.5,t.y-.5,1,1))):e=this.getBounds(),!e)return null;var i=32,s=Math.min(e.width,i),a=Math.min(e.height,i),o=S._sampleContext;o?o.clearRect(0,0,i+1,i+1):o=S._sampleContext=tt.getContext(new d(i)),o.save();var h=(new p).scale(s/e.width,a/e.height).translate(-e.x,-e.y);h.applyToContext(o),n&&n.draw(o,new r({clip:!0,matrices:[h]})),this._matrix.applyToContext(o);var u=this.getElement(),l=this._size;u&&o.drawImage(u,-l.width/2,-l.height/2),o.restore();for(var c=o.getImageData(.5,.5,Math.ceil(s),Math.ceil(a)).data,f=[0,0,0],_=0,v=0,m=c.length;v<m;v+=4){var y=c[v+3];_+=y,y/=255,f[0]+=c[v]*y,f[1]+=c[v+1]*y,f[2]+=c[v+2]*y}for(var v=0;v<3;v++)f[v]/=_;return _?D.read(f):null},getPixel:function(){var t=c.read(arguments),e=this.getContext().getImageData(t.x,t.y,1,1).data;return new D("rgb",[e[0]/255,e[1]/255,e[2]/255],e[3]/255)},setPixel:function(){var t=c.read(arguments),e=D.read(arguments),n=e._convert("rgb"),i=e._alpha,r=this.getContext(!0),s=r.createImageData(1,1),a=s.data;a[0]=255*n[0],a[1]=255*n[1],a[2]=255*n[2],a[3]=null!=i?255*i:255,r.putImageData(s,t.x,t.y)},createImageData:function(){var t=d.read(arguments);return this.getContext().createImageData(t.width,t.height)},getImageData:function(){var t=g.read(arguments);return t.isEmpty()&&(t=new g(this._size)),this.getContext().getImageData(t.x,t.y,t.width,t.height)},setImageData:function(t){var e=c.read(arguments,1);this.getContext(!0).putImageData(t,e.x,e.y)},_getBounds:function(t,e){var n=new g(this._size).setCenter(0,0);return t?t._transformBounds(n):n},_hitTestSelf:function(t){if(this._contains(t)){var e=this;return new P("pixel",e,{offset:t.add(e._size.divide(2)).round(),color:{get:function(){return e.getPixel(this.offset)}}})}},_draw:function(t){var e=this.getElement();e&&(t.globalAlpha=this._opacity,t.drawImage(e,-this._size.width/2,-this._size.height/2))},_canComposite:function(){return!0}}),k=w.extend({_class:"SymbolItem",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!0},_serializeFields:{symbol:null},initialize:function(t,n){this._initialize(t,n!==e&&c.read(arguments,1))||this.setDefinition(t instanceof I?t:new I(t))},_equals:function(t){return this._definition===t._definition},copyContent:function(t){this.setDefinition(t._definition)},getDefinition:function(){return this._definition},setDefinition:function(t){this._definition=t,this._changed(9)},getSymbol:"#getDefinition",setSymbol:"#setDefinition",isEmpty:function(){return this._definition._item.isEmpty()},_getBounds:function(t,e){var n=this._definition._item;return n._getCachedBounds(n._matrix.prepended(t),e)},_hitTestSelf:function(t,e,n,i){var r=this._definition._item._hitTest(t,e,n);return r&&(r.item=this),r},_draw:function(t,e){this._definition._item.draw(t,e)}}),I=r.extend({_class:"SymbolDefinition",initialize:function(t,e){this._id=l.get(),this.project=paper.project,t&&this.setItem(t,e)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._class,this._item],t,!1,e)})},_changed:function(t){8&t&&w._clearBoundsCache(this),1&t&&this.project._changed(t)},getItem:function(){return this._item},setItem:function(t,e){t._symbol&&(t=t.clone()),this._item&&(this._item._symbol=null),this._item=t,t.remove(),t.setSelected(!1),e||t.setPosition(new c),t._symbol=this,this._changed(9)},getDefinition:"#getItem",setDefinition:"#setItem",place:function(t){return new k(this,t)},clone:function(){return new I(this._item.clone(!1))},equals:function(t){return t===this||t&&this._item.equals(t._item)||!1}}),P=r.extend({_class:"HitResult",initialize:function(t,e,n){this.type=t,this.item=e,n&&(n.enumerable=!0,this.inject(n))},statics:{getOptions:function(t){var e=t&&r.read(t);return r.set({type:null,tolerance:paper.settings.hitTolerance,fill:!e,stroke:!e,segments:!e,handles:!1,ends:!1,center:!1,bounds:!1,guides:!1,selected:!1},e)}}}),M=r.extend({_class:"Segment",beans:!0,_selection:0,initialize:function(t,n,i,r,s,a){var o,h,u,l,c=arguments.length;0===c||(1===c?t&&"point"in t?(o=t.point,h=t.handleIn,u=t.handleOut,l=t.selection):o=t:null==t||"object"==typeof t?(o=t,h=n,u=i,l=r):(o=t!==e?[t,n]:null,h=i!==e?[i,r]:null,u=s!==e?[s,a]:null)),new A(o,this,"_point"),new A(h,this,"_handleIn"),new A(u,this,"_handleOut"),l&&this.setSelection(l)},_serialize:function(t,e){var n=this._point,i=this._selection,s=i||this.hasHandles()?[n,this._handleIn,this._handleOut]:n;return i&&s.push(i),r.serialize(s,t,!0,e)},_changed:function(t){var e=this._path;if(e){var n,i=e._curves,r=this._index;i&&(t&&t!==this._point&&t!==this._handleIn||!(n=r>0?i[r-1]:e._closed?i[i.length-1]:null)||n._changed(),t&&t!==this._point&&t!==this._handleOut||!(n=i[r])||n._changed()),e._changed(25)}},getPoint:function(){return this._point},setPoint:function(){var t=c.read(arguments);this._point.set(t.x,t.y)},getHandleIn:function(){return this._handleIn},setHandleIn:function(){var t=c.read(arguments);this._handleIn.set(t.x,t.y)},getHandleOut:function(){return this._handleOut},setHandleOut:function(){var t=c.read(arguments);this._handleOut.set(t.x,t.y)},hasHandles:function(){return!this._handleIn.isZero()||!this._handleOut.isZero()},clearHandles:function(){this._handleIn.set(0,0),this._handleOut.set(0,0)},getSelection:function(){return this._selection},setSelection:function(t){var e=this._selection,n=this._path;this._selection=t=t||0,n&&t!==e&&(n._updateSelection(this,e,t),n._changed(129))},changeSelection:function(t,e){var n=this._selection;this.setSelection(e?n|t:n&~t)},isSelected:function(){return!!(7&this._selection)},setSelected:function(t){this.changeSelection(7,t)},getIndex:function(){return this._index!==e?this._index:null},getPath:function(){return this._path||null},getCurve:function(){var t=this._path,e=this._index;return t?(e>0&&!t._closed&&e===t._segments.length-1&&e--,t.getCurves()[e]||null):null},getLocation:function(){var t=this.getCurve();return t?new z(t,this===t._segment1?0:1):null},getNext:function(){var t=this._path&&this._path._segments;return t&&(t[this._index+1]||this._path._closed&&t[0])||null},smooth:function(t,n,i){var r=t||{},s=r.type,a=r.factor,o=this.getPrevious(),h=this.getNext(),u=(o||this)._point,l=this._point,f=(h||this)._point,d=u.getDistance(l),_=l.getDistance(f);if(s&&"catmull-rom"!==s){if("geometric"!==s)throw new Error("Smoothing method '"+s+"' not supported.");if(o&&h){var g=u.subtract(f),v=a===e?.4:a,p=v*d/(d+_);n||this.setHandleIn(g.multiply(p)),i||this.setHandleOut(g.multiply(p-v))}}else{var m=a===e?.5:a,y=Math.pow(d,m),w=y*y,x=Math.pow(_,m),b=x*x;if(!n&&o){var C=2*b+3*x*y+w,S=3*x*(x+y);this.setHandleIn(0!==S?new c((b*u._x+C*l._x-w*f._x)/S-l._x,(b*u._y+C*l._y-w*f._y)/S-l._y):new c)}if(!i&&h){var C=2*w+3*y*x+b,S=3*y*(y+x);this.setHandleOut(0!==S?new c((w*f._x+C*l._x-b*u._x)/S-l._x,(w*f._y+C*l._y-b*u._y)/S-l._y):new c)}}},getPrevious:function(){var t=this._path&&this._path._segments;return t&&(t[this._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._index},isLast:function(){var t=this._path;return t&&this._index===t._segments.length-1||!1},reverse:function(){var t=this._handleIn,e=this._handleOut,n=t._x,i=t._y;t.set(e._x,e._y),e.set(n,i)},reversed:function(){return new M(this._point,this._handleOut,this._handleIn)},remove:function(){return!!this._path&&!!this._path.removeSegment(this._index)},clone:function(){return new M(this._point,this._handleIn,this._handleOut)},equals:function(t){return t===this||t&&this._class===t._class&&this._point.equals(t._point)&&this._handleIn.equals(t._handleIn)&&this._handleOut.equals(t._handleOut)||!1},toString:function(){var t=["point: "+this._point];return this._handleIn.isZero()||t.push("handleIn: "+this._handleIn),this._handleOut.isZero()||t.push("handleOut: "+this._handleOut),"{ "+t.join(", ")+" }"},transform:function(t){this._transformCoordinates(t,new Array(6),!0),this._changed()},interpolate:function(t,e,n){var i=1-n,r=n,s=t._point,a=e._point,o=t._handleIn,h=e._handleIn,u=e._handleOut,l=t._handleOut;this._point.set(i*s._x+r*a._x,i*s._y+r*a._y,!0),this._handleIn.set(i*o._x+r*h._x,i*o._y+r*h._y,!0),this._handleOut.set(i*l._x+r*u._x,i*l._y+r*u._y,!0),this._changed()},_transformCoordinates:function(t,e,n){var i=this._point,r=n&&this._handleIn.isZero()?null:this._handleIn,s=n&&this._handleOut.isZero()?null:this._handleOut,a=i._x,o=i._y,h=2;return e[0]=a,e[1]=o,r&&(e[h++]=r._x+a,e[h++]=r._y+o),s&&(e[h++]=s._x+a,e[h++]=s._y+o),t&&(t._transformCoordinates(e,e,h/2),a=e[0],o=e[1],n?(i._x=a,i._y=o,h=2,r&&(r._x=e[h++]-a,r._y=e[h++]-o),s&&(s._x=e[h++]-a,s._y=e[h++]-o)):(r||(e[h++]=a,e[h++]=o),s||(e[h++]=a,e[h++]=o))),e}}),A=c.extend({initialize:function(t,n,i){var r,s,a;if(t)if((r=t[0])!==e)s=t[1];else{var o=t;(r=o.x)===e&&(o=c.read(arguments),r=o.x),s=o.y,a=o.selected}else r=s=0;this._x=r,this._y=s,this._owner=n,n[i]=this,a&&this.setSelected(!0)},set:function(t,e){return this._x=t,this._y=e,this._owner._changed(this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner._changed(this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner._changed(this)},isZero:function(){return u.isZero(this._x)&&u.isZero(this._y)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){var t=this._owner;return this===t._point?1:this===t._handleIn?2:this===t._handleOut?4:0}}),T=r.extend({_class:"Curve",initialize:function(t,e,n,i,r,s,a,o){var h,u,l,c,f,d,_=arguments.length;3===_?(this._path=t,h=e,u=n):0===_?(h=new M,u=new M):1===_?"segment1"in t?(h=new M(t.segment1),u=new M(t.segment2)):"point1"in t?(l=t.point1,f=t.handle1,d=t.handle2,c=t.point2):Array.isArray(t)&&(l=[t[0],t[1]],c=[t[6],t[7]],f=[t[2]-t[0],t[3]-t[1]],d=[t[4]-t[6],t[5]-t[7]]):2===_?(h=new M(t),u=new M(e)):4===_?(l=t,f=e,d=n,c=i):8===_&&(l=[t,e],c=[a,o],f=[n-t,i-e],d=[r-a,s-o]),this._segment1=h||new M(l,null,f),this._segment2=u||new M(c,d,null)},_serialize:function(t,e){return r.serialize(this.hasHandles()?[this.getPoint1(),this.getHandle1(),this.getHandle2(),this.getPoint2()]:[this.getPoint1(),this.getPoint2()],t,!0,e)},_changed:function(){this._length=this._bounds=e},clone:function(){return new T(this._segment1,this._segment2)},toString:function(){var t=["point1: "+this._segment1._point];return this._segment1._handleOut.isZero()||t.push("handle1: "+this._segment1._handleOut),this._segment2._handleIn.isZero()||t.push("handle2: "+this._segment2._handleIn),t.push("point2: "+this._segment2._point),"{ "+t.join(", ")+" }"},remove:function(){var t=!1;if(this._path){var e=this._segment2,n=e._handleOut;t=e.remove(),t&&this._segment1._handleOut.set(n.x,n.y)}return t},getPoint1:function(){return this._segment1._point},setPoint1:function(){var t=c.read(arguments);this._segment1._point.set(t.x,t.y)},getPoint2:function(){return this._segment2._point},setPoint2:function(){var t=c.read(arguments);this._segment2._point.set(t.x,t.y)},getHandle1:function(){return this._segment1._handleOut},setHandle1:function(){var t=c.read(arguments);this._segment1._handleOut.set(t.x,t.y)},getHandle2:function(){return this._segment2._handleIn},setHandle2:function(){var t=c.read(arguments);this._segment2._handleIn.set(t.x,t.y)},getSegment1:function(){return this._segment1},getSegment2:function(){return this._segment2},getPath:function(){return this._path},getIndex:function(){return this._segment1._index},getNext:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index+1]||this._path._closed&&t[0])||null},getPrevious:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._segment1._index},isLast:function(){var t=this._path;return t&&this._segment1._index===t._curves.length-1||!1},isSelected:function(){return this.getPoint1().isSelected()&&this.getHandle2().isSelected()&&this.getHandle2().isSelected()&&this.getPoint2().isSelected()},setSelected:function(t){this.getPoint1().setSelected(t),this.getHandle1().setSelected(t),this.getHandle2().setSelected(t),this.getPoint2().setSelected(t)},getValues:function(t){return T.getValues(this._segment1,this._segment2,t)},getPoints:function(){for(var t=this.getValues(),e=[],n=0;n<8;n+=2)e.push(new c(t[n],t[n+1]));return e},getLength:function(){return null==this._length&&(this._length=T.getLength(this.getValues(),0,1)),this._length},getArea:function(){return T.getArea(this.getValues())},getLine:function(){return new m(this._segment1._point,this._segment2._point)},getPart:function(t,e){return new T(T.getPart(this.getValues(),t,e))},getPartLength:function(t,e){return T.getLength(this.getValues(),t,e)},getIntersections:function(t){return T._getIntersections(this.getValues(),t&&t!==this?t.getValues():null,this,t,[],{})},divideAt:function(t){return this.divideAtTime(t&&t.curve===this?t.time:t)},divideAtTime:function(t,e){var n=4e-7,i=1-n,r=null;if(t>=n&&t<=i){var s=T.subdivide(this.getValues(),t),a=s[0],o=s[1],h=e||this.hasHandles(),u=this._segment1,l=this._segment2,f=this._path;h&&(u._handleOut.set(a[2]-a[0],a[3]-a[1]),l._handleIn.set(o[4]-o[6],o[5]-o[7]));var d=a[6],_=a[7],g=new M(new c(d,_),h&&new c(a[4]-d,a[5]-_),h&&new c(o[2]-d,o[3]-_));f?(f.insert(u._index+1,g),r=this.getNext()):(this._segment2=g,this._changed(),r=new T(g,l))}return r},splitAt:function(t){return this._path?this._path.splitAt(t):null},splitAtTime:function(t){return this.splitAt(this.getLocationAtTime(t))},divide:function(t,n){return this.divideAtTime(t===e?.5:n?t:this.getTimeAt(t))},split:function(t,n){return this.splitAtTime(t===e?.5:n?t:this.getTimeAt(t))},reversed:function(){return new T(this._segment2.reversed(),this._segment1.reversed())},clearHandles:function(){this._segment1._handleOut.set(0,0),this._segment2._handleIn.set(0,0)},statics:{getValues:function(t,e,n){var i=t._point,r=t._handleOut,s=e._handleIn,a=e._point,o=[i._x,i._y,i._x+r._x,i._y+r._y,a._x+s._x,a._y+s._y,a._x,a._y];return n&&n._transformCoordinates(o,o,4),o},subdivide:function(t,n){var i=t[0],r=t[1],s=t[2],a=t[3],o=t[4],h=t[5],u=t[6],l=t[7];n===e&&(n=.5);var c=1-n,f=c*i+n*s,d=c*r+n*a,_=c*s+n*o,g=c*a+n*h,v=c*o+n*u,p=c*h+n*l,m=c*f+n*_,y=c*d+n*g,w=c*_+n*v,x=c*g+n*p,b=c*m+n*w,C=c*y+n*x;return[[i,r,f,d,m,y,b,C],[b,C,w,x,v,p,u,l]]},solveCubic:function(t,e,n,i,r,s){var a=t[e],o=t[e+2],h=t[e+4],l=t[e+6],c=0;if(!(a<n&&l<n&&o<n&&h<n||a>n&&l>n&&o>n&&h>n)){var f=3*(o-a),d=3*(h-o)-f,_=l-a-f-d;c=u.solveCubic(_,d,f,a-n,i,r,s)}return c},getTimeOf:function(t,e){var n=new c(t[0],t[1]),i=new c(t[6],t[7]),r=1e-12,s=e.isClose(n,r)?0:e.isClose(i,r)?1:null;if(null!==s)return s;for(var a=[e.x,e.y],o=[],h=2e-7,u=0;u<2;u++)for(var l=T.solveCubic(t,u,a[u],o,0,1),f=0;f<l;f++)if(s=o[f],e.isClose(T.getPoint(t,s),h))return s;return e.isClose(n,h)?0:e.isClose(i,h)?1:null},getNearestTime:function(t,e){function n(n){if(n>=0&&n<=1){var i=e.getDistance(T.getPoint(t,n),!0);if(i<d)return d=i,_=n,!0}}if(T.isStraight(t)){var i=t[0],r=t[1],s=t[6],a=t[7],o=s-i,h=a-r,u=o*o+h*h;if(0===u)return 0;var l=((e.x-i)*o+(e.y-r)*h)/u;return l<1e-12?0:l>.999999999999?1:T.getTimeOf(t,new c(i+l*o,r+l*h))}for(var f=100,d=1/0,_=0,g=0;g<=f;g++)n(g/f);for(var v=1/(2*f);v>4e-7;)n(_-v)||n(_+v)||(v/=2);return _},getPart:function(t,e,n){var i=e>n;if(i){var r=e;e=n,n=r}return e>0&&(t=T.subdivide(t,e)[1]),n<1&&(t=T.subdivide(t,(n-e)/(1-e))[0]),i?[t[6],t[7],t[4],t[5],t[2],t[3],t[0],t[1]]:t},isFlatEnough:function(t,e){var n=t[0],i=t[1],r=t[2],s=t[3],a=t[4],o=t[5],h=t[6],u=t[7],l=3*r-2*n-h,c=3*s-2*i-u,f=3*a-2*h-n,d=3*o-2*u-i;return Math.max(l*l,f*f)+Math.max(c*c,d*d)<=16*e*e},getArea:function(t){var e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7];return 3*((h-n)*(i+s)-(o-e)*(r+a)+r*(e-s)-i*(n-a)+h*(s+e/3)-o*(a+n/3))/20},getBounds:function(t){for(var e=t.slice(0,2),n=e.slice(),i=[0,0],r=0;r<2;r++)T._addBounds(t[r],t[r+2],t[r+4],t[r+6],r,0,e,n,i);return new g(e[0],e[1],n[0]-e[0],n[1]-e[1])},_addBounds:function(t,e,n,i,r,s,a,o,h){function l(t,e){var n=t-e,i=t+e;n<a[r]&&(a[r]=n),i>o[r]&&(o[r]=i)}s/=2;var c=a[r]-s,f=o[r]+s;if(t<c||e<c||n<c||i<c||t>f||e>f||n>f||i>f)if(e<t!=e<i&&n<t!=n<i)l(t,s),l(i,s);else{var d=3*(e-n)-t+i,_=2*(t+n)-4*e,g=e-t,v=u.solveQuadratic(d,_,g,h),p=4e-7,m=1-p;l(i,0);for(var y=0;y<v;y++){var w=h[y],x=1-w;p<w&&w<m&&l(x*x*x*t+3*x*x*w*e+3*x*w*w*n+w*w*w*i,s)}}}}},r.each(["getBounds","getStrokeBounds","getHandleBounds"],function(t){this[t]=function(){this._bounds||(this._bounds={});var e=this._bounds[t];return e||(e=this._bounds[t]=E[t]([this._segment1,this._segment2],!1,this._path)),e.clone()}},{}),r.each({isStraight:function(t,e,n){if(e.isZero()&&n.isZero())return!0;var i=t.getVector(),r=2e-7;if(i.isZero())return!1;if(t.getDistance(e)<r&&t.getDistance(n)<r){var s=i.dot(i),a=i.dot(e)/s,o=i.dot(n)/s;return a>=0&&a<=1&&o<=0&&o>=-1}return!1},isLinear:function(t,e,n){var i=t.getVector().divide(3);return e.equals(i)&&n.negate().equals(i)}},function(t,e){this[e]=function(){var e=this._segment1,n=this._segment2;return t(new m(e._point,n._point),e._handleOut,n._handleIn)},this.statics[e]=function(e){var n=e[0],i=e[1],r=e[6],s=e[7];return t(new m(n,i,r,s),new c(e[2]-n,e[3]-i),new c(e[4]-r,e[5]-s))}},{statics:{},hasHandles:function(){return!this._segment1._handleOut.isZero()||!this._segment2._handleIn.isZero()},isCollinear:function(t){return t&&this.isStraight()&&t.isStraight()&&this.getLine().isCollinear(t.getLine())},isHorizontal:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).y)<1e-7},isVertical:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).x)<1e-7}}),{beans:!1,getLocationAt:function(t,e){return this.getLocationAtTime(e?t:this.getTimeAt(t))},getLocationAtTime:function(t){return null!=t&&t>=0&&t<=1?new z(this,t):null},getTimeAt:function(t,e){return T.getTimeAt(this.getValues(),t,e)},getParameterAt:"#getTimeAt",getOffsetAtTime:function(t){return this.getPartLength(0,t)},getLocationOf:function(){return this.getLocationAtTime(this.getTimeOf(c.read(arguments)))},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getTimeOf:function(){return T.getTimeOf(this.getValues(),c.read(arguments))},getParameterOf:"#getTimeOf",getNearestLocation:function(){var t=c.read(arguments),e=this.getValues(),n=T.getNearestTime(e,t),i=T.getPoint(e,n);return new z(this,n,i,null,t.getDistance(i))},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t}},new function(){var t=["getPoint","getTangent","getNormal","getWeightedTangent","getWeightedNormal","getCurvature"];return r.each(t,function(t){this[t+"At"]=function(e,n){var i=this.getValues();return T[t](i,n?e:T.getTimeAt(i,e))},this[t+"AtTime"]=function(e){return T[t](this.getValues(),e)}},{statics:{_evaluateMethods:t}})},new function(){function t(t){var e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7],u=9*(i-s)+3*(o-e),l=6*(e+s)-12*i,c=3*(i-e),f=9*(r-a)+3*(h-n),d=6*(n+a)-12*r,_=3*(r-n);return function(t){var e=(u*t+l)*t+c,n=(f*t+d)*t+_;return Math.sqrt(e*e+n*n)}}function n(t,e){return Math.max(2,Math.min(16,Math.ceil(32*Math.abs(e-t))))}function i(t,e,n,i){if(null==e||e<0||e>1)return null;var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],f=t[6],d=t[7],_=u.isZero;_(a-r)&&_(o-s)&&(a=r,o=s),_(h-f)&&_(l-d)&&(h=f,l=d);var g,v,p=3*(a-r),m=3*(h-a)-p,y=f-r-p-m,w=3*(o-s),x=3*(l-o)-w,b=d-s-w-x;if(0===n)g=0===e?r:1===e?f:((y*e+m)*e+p)*e+r,v=0===e?s:1===e?d:((b*e+x)*e+w)*e+s;else{var C=4e-7,S=1-C;if(e<C?(g=p,v=w):e>S?(g=3*(f-h),v=3*(d-l)):(g=(3*y*e+2*m)*e+p,v=(3*b*e+2*x)*e+w),i){0===g&&0===v&&(e<C||e>S)&&(g=h-a,v=l-o);var k=Math.sqrt(g*g+v*v);k&&(g/=k,v/=k)}if(3===n){var I=6*y*e+2*m,P=6*b*e+2*x,M=Math.pow(g*g+v*v,1.5);g=0!==M?(g*P-v*I)/M:0,v=0}}return 2===n?new c(v,(-g)):new c(g,v)}return{statics:{getLength:function(i,r,s,a){if(r===e&&(r=0),s===e&&(s=1),T.isStraight(i)){var o=i;s<1&&(o=T.subdivide(o,s)[0],r/=s),r>0&&(o=T.subdivide(o,r)[1]);var h=o[6]-o[0],l=o[7]-o[1];return Math.sqrt(h*h+l*l)}return u.integrate(a||t(i),r,s,n(r,s))},getTimeAt:function(i,r,s){function a(t){return p+=u.integrate(d,s,t,n(s,t)),s=t,p-r}if(s===e&&(s=r<0?1:0),0===r)return s;var o=Math.abs,h=1e-12,l=r>0,c=l?s:0,f=l?1:s,d=t(i),_=T.getLength(i,c,f,d),g=o(r)-_;if(o(g)<h)return l?f:c;if(g>h)return null;var v=r/_,p=0;return u.findRoot(a,d,s+v,c,f,32,1e-12)},getPoint:function(t,e){return i(t,e,0,!1)},getTangent:function(t,e){return i(t,e,1,!0)},getWeightedTangent:function(t,e){return i(t,e,1,!1)},getNormal:function(t,e){return i(t,e,2,!0)},getWeightedNormal:function(t,e){return i(t,e,2,!1)},getCurvature:function(t,e){return i(t,e,3,!1).x}}}},new function(){function t(t,e,n,i,r,s,a,o,h,u,l){var c=!l&&e.excludeStart,f=!l&&e.excludeEnd,d=4e-7,_=1-d;if(null==r&&(r=T.getTimeOf(n,s)),null!==r&&r>=(c?d:0)&&r<=(f?_:1)&&(null==h&&(h=T.getTimeOf(a,u)),null!==h&&h>=(f?d:0)&&h<=(c?_:1))){var g=e.renormalize;
+if(g){var v=g(r,h);r=v[0],h=v[1]}var p=new z(i,r,s||T.getPoint(n,r),l),m=new z(o,h,u||T.getPoint(a,h),l),y=p.getPath()===m.getPath()&&p.getIndex()>m.getIndex(),w=y?m:p,x=e.include;p._intersection=m,m._intersection=p,x&&!x(w)||z.insert(t,w,!0)}}function e(r,s,a,o,h,u,l,c,f,d,_,g,v){if(++g>=48||++v>4096)return v;var p,y,w=s[0],x=s[1],b=s[6],C=s[7],S=m.getSignedDistance,k=S(w,x,b,C,s[2],s[3]),I=S(w,x,b,C,s[4],s[5]),P=k*I>0?.75:4/9,M=P*Math.min(0,k,I),A=P*Math.max(0,k,I),z=S(w,x,b,C,r[0],r[1]),O=S(w,x,b,C,r[2],r[3]),E=S(w,x,b,C,r[4],r[5]),L=S(w,x,b,C,r[6],r[7]),N=n(z,O,E,L),B=N[0],j=N[1];if(0===k&&0===I&&0===z&&0===O&&0===E&&0===L||null==(p=i(B,j,M,A))||null==(y=i(B.reverse(),j.reverse(),M,A)))return v;var F=l+(c-l)*p,D=l+(c-l)*y;if(Math.max(d-f,D-F)<1e-9){var R=(F+D)/2,q=(f+d)/2;r=a.getValues(),s=o.getValues(),t(h,u,_?s:r,_?o:a,_?q:R,null,_?r:s,_?a:o,_?R:q,null)}else if(r=T.getPart(r,p,y),y-p>.8)if(D-F>d-f){var V=T.subdivide(r,.5),R=(F+D)/2;v=e(s,V[0],o,a,h,u,f,d,F,R,!_,g,v),v=e(s,V[1],o,a,h,u,f,d,R,D,!_,g,v)}else{var V=T.subdivide(s,.5),q=(f+d)/2;v=e(V[0],r,o,a,h,u,f,q,F,D,!_,g,v),v=e(V[1],r,o,a,h,u,q,d,F,D,!_,g,v)}else v=e(s,r,o,a,h,u,f,d,F,D,!_,g,v);return v}function n(t,e,n,i){var r,s=[0,t],a=[1/3,e],o=[2/3,n],h=[1,i],u=e-(2*t+i)/3,l=n-(t+2*i)/3;if(u*l<0)r=[[s,a,h],[s,o,h]];else{var c=u/l;r=[c>=2?[s,a,h]:c<=.5?[s,o,h]:[s,a,o,h],[s,h]]}return(u||l)<0?r.reverse():r}function i(t,e,n,i){return t[0][1]<n?r(t,!0,n):e[0][1]>i?r(e,!1,i):t[0][0]}function r(t,e,n){for(var i=t[0][0],r=t[0][1],s=1,a=t.length;s<a;s++){var o=t[s][0],h=t[s][1];if(e?h>=n:h<=n)return h===n?o:i+(n-r)*(o-i)/(h-r);i=o,r=h}return null}function s(e,n,i,r,s,a){for(var o=T.isStraight(e),h=o?n:e,l=o?e:n,c=l[0],f=l[1],d=l[6],_=l[7],g=d-c,v=_-f,p=Math.atan2(-v,g),m=Math.sin(p),y=Math.cos(p),w=[],x=0;x<8;x+=2){var b=h[x]-c,C=h[x+1]-f;w.push(b*y-C*m,b*m+C*y)}for(var S=[],k=T.solveCubic(w,1,0,S,0,1),x=0;x<k;x++){var I=S[x],P=T.getPoint(h,I),M=T.getTimeOf(l,P);if(null!==M){var A=T.getPoint(l,M),z=o?M:I,O=o?I:M;(!a.excludeEnd||O>u.CURVETIME_EPSILON)&&t(s,a,e,i,z,o?A:P,n,r,O,o?P:A)}}}function a(e,n,i,r,s,a){var o=m.intersect(e[0],e[1],e[6],e[7],n[0],n[1],n[6],n[7]);o&&t(s,a,e,i,null,o,n,r,null,o)}return{statics:{_getIntersections:function(n,i,r,o,h,u){if(!i)return T._getSelfIntersection(n,r,h,u);var l=2e-7,f=n[0],d=n[1],_=n[6],g=n[7],v=i[0],p=i[1],m=i[6],y=i[7],w=(3*n[2]+f)/4,x=(3*n[3]+d)/4,b=(3*n[4]+_)/4,C=(3*n[5]+g)/4,S=(3*i[2]+v)/4,k=(3*i[3]+p)/4,I=(3*i[4]+m)/4,P=(3*i[5]+y)/4,M=Math.min,A=Math.max;if(!(A(f,w,b,_)+l>M(v,S,I,m)&&M(f,w,b,_)-l<A(v,S,I,m)&&A(d,x,C,g)+l>M(p,k,P,y)&&M(d,x,C,g)-l<A(p,k,P,y)))return h;var z=T.getOverlaps(n,i);if(z){for(var O=0;O<2;O++){var E=z[O];t(h,u,n,r,E[0],null,i,o,E[1],null,!0)}return h}var L=T.isStraight(n),N=T.isStraight(i),B=L&&N,j=h.length;if((B?a:L||N?s:e)(n,i,r,o,h,u,0,1,0,1,0,0,0),B&&h.length>j)return h;var F=new c(f,d),D=new c(_,g),R=new c(v,p),q=new c(m,y);return F.isClose(R,l)&&t(h,u,n,r,0,F,i,o,0,R),!u.excludeStart&&F.isClose(q,l)&&t(h,u,n,r,0,F,i,o,1,q),!u.excludeEnd&&D.isClose(R,l)&&t(h,u,n,r,1,D,i,o,0,R),D.isClose(q,l)&&t(h,u,n,r,1,D,i,o,1,q),h},_getSelfIntersection:function(t,e,n,i){var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],f=t[6],d=t[7],_=new m(r,s,f,d,(!1)),g=_.getSide(new c(a,o),!0),v=_.getSide(new c(h,l),!0);if(g===v){var p=(r-h)*(o-d)+(a-f)*(l-s);if(p*g>0)return n}var y=f-3*h+3*a-r,w=h-2*a+r,x=a-r,b=d-3*l+3*o-s,C=l-2*o+s,S=o-s,k=b*x-y*S,I=b*w-y*C,P=C*x-w*S;if(k*k-4*I*P<0){var M,A=[],z=u.solveCubic(y*y+b*b,3*(y*w+b*C),2*(w*w+C*C)+y*x+b*S,w*x+C*S,A,0,1);if(z>0){for(var O=0,E=0;O<z;O++){var L=Math.abs(e.getCurvatureAtTime(A[O]));L>E&&(E=L,M=A[O])}var N=T.subdivide(t,M);i.excludeEnd=!0,i.renormalize=function(t,e){return[t*M,e*(1-M)+M]},T._getIntersections(N[0],N[1],e,e,n,i)}}return n},getOverlaps:function(t,e){function n(t){var e=t[6]-t[0],n=t[7]-t[1];return e*e+n*n}var i=Math.abs,r=4e-7,s=2e-7,a=T.isStraight(t),o=T.isStraight(e),h=a&&o,u=n(t)<n(e),l=u?e:t,f=u?t:e,d=new m(l[0],l[1],l[6],l[7]);if(d.getDistance(new c(f[0],f[1]))<s&&d.getDistance(new c(f[6],f[7]))<s)!h&&d.getDistance(new c(l[2],l[3]))<s&&d.getDistance(new c(l[4],l[5]))<s&&d.getDistance(new c(f[2],f[3]))<s&&d.getDistance(new c(f[4],f[5]))<s&&(a=o=h=!0);else if(h)return null;if(a^o)return null;for(var _=[t,e],g=[],v=0,p=0;v<2&&g.length<2;v+=0===p?0:1,p=1^p){var y=T.getTimeOf(_[1^v],new c(_[v][0===p?0:6],_[v][0===p?1:7]));if(null!=y){var w=0===v?[p,y]:[y,p];(0===g.length||i(w[0]-g[0][0])>r&&i(w[1]-g[0][1])>r)&&g.push(w)}if(1===v&&0===g.length)break}if(2!==g.length)g=null;else if(!h){var x=T.getPart(t,g[0][0],g[1][0]),b=T.getPart(e,g[0][1],g[1][1]);(i(b[2]-x[2])>s||i(b[3]-x[3])>s||i(b[4]-x[4])>s||i(b[5]-x[5])>s)&&(g=null)}return g}}}}),z=r.extend({_class:"CurveLocation",beans:!0,initialize:function(t,e,n,i,r){if(e>.9999996){var s=t.getNext();s&&(e=0,t=s)}this._setCurve(t),this._time=e,this._point=n||t.getPointAtTime(e),this._overlap=i,this._distance=r,this._intersection=this._next=this._previous=null},_setCurve:function(t){var e=t._path;this._path=e,this._version=e?e._version:0,this._curve=t,this._segment=null,this._segment1=t._segment1,this._segment2=t._segment2},_setSegment:function(t){this._setCurve(t.getCurve()),this._segment=t,this._time=t===this._segment1?0:1,this._point=t._point.clone()},getSegment:function(){var t=this.getCurve(),e=this._segment;if(!e){var n=this.getTime();0===n?e=t._segment1:1===n?e=t._segment2:null!=n&&(e=t.getPartLength(0,n)<t.getPartLength(n,1)?t._segment1:t._segment2),this._segment=e}return e},getCurve:function(){function t(t){var e=t&&t.getCurve();if(e&&null!=(n._time=e.getTimeOf(n._point)))return n._setCurve(e),n._segment=t,e}var e=this._path,n=this;return e&&e._version!==this._version&&(this._time=this._curve=this._offset=null),this._curve||t(this._segment)||t(this._segment1)||t(this._segment2.getPrevious())},getPath:function(){var t=this.getCurve();return t&&t._path},getIndex:function(){var t=this.getCurve();return t&&t.getIndex()},getTime:function(){var t=this.getCurve(),e=this._time;return t&&null==e?this._time=t.getTimeOf(this._point):e},getParameter:"#getTime",getPoint:function(){return this._point},getOffset:function(){var t=this._offset;if(null==t){t=0;var e=this.getPath(),n=this.getIndex();if(e&&null!=n)for(var i=e.getCurves(),r=0;r<n;r++)t+=i[r].getLength();this._offset=t+=this.getCurveOffset()}return t},getCurveOffset:function(){var t=this.getCurve(),e=this.getTime();return null!=e&&t&&t.getPartLength(0,e)},getIntersection:function(){return this._intersection},getDistance:function(){return this._distance},divide:function(){var t=this.getCurve(),e=null;return t&&(e=t.divideAtTime(this.getTime()),e&&this._setSegment(e._segment1)),e},split:function(){var t=this.getCurve();return t?t.splitAtTime(this.getTime()):null},equals:function(t,e){var n=this===t,i=2e-7;if(!n&&t instanceof z&&this.getPath()===t.getPath()&&this.getPoint().isClose(t.getPoint(),i)){var r=this.getCurve(),s=t.getCurve(),a=Math.abs,o=a((r.isLast()&&s.isFirst()?-1:r.getIndex())+this.getTime()-((s.isLast()&&r.isFirst()?-1:s.getIndex())+t.getTime()));n=(o<4e-7||(o=a(this.getOffset()-t.getOffset()))<i||a(this.getPath().getLength()-o)<i)&&(e||!this._intersection&&!t._intersection||this._intersection&&this._intersection.equals(t._intersection,!0))}return n},toString:function(){var t=[],e=this.getPoint(),n=h.instance;e&&t.push("point: "+e);var i=this.getIndex();null!=i&&t.push("index: "+i);var r=this.getTime();return null!=r&&t.push("time: "+n.number(r)),null!=this._distance&&t.push("distance: "+n.number(this._distance)),"{ "+t.join(", ")+" }"},isTouching:function(){var t=this._intersection;if(t&&this.getTangent().isCollinear(t.getTangent())){var e=this.getCurve(),n=t.getCurve();return!(e.isStraight()&&n.isStraight()&&e.getLine().intersect(n.getLine()))}return!1},isCrossing:function(){function t(t,e,n){return e<n?t>e&&t<n:t>e||t<n}var e=this._intersection;if(!e)return!1;var n=this.getTime(),i=e.getTime(),r=4e-7,s=1-r,a=n>r&&n<s,o=i>r&&i<s;if(a&&o)return!this.isTouching();var h=this.getCurve(),u=n<=r?h.getPrevious():h,l=e.getCurve(),c=i<=r?l.getPrevious():l;if(n>=s&&(h=h.getNext()),i>=s&&(l=l.getNext()),!(u&&h&&c&&l))return!1;var f=[];a||f.push(u.getLength(),h.getLength()),o||f.push(c.getLength(),l.getLength());var d=this.getPoint(),_=Math.min.apply(Math,f)/64,g=a?h.getTangentAtTime(n):h.getPointAt(_).subtract(d),v=a?g.negate():u.getPointAt(-_).subtract(d),p=o?l.getTangentAtTime(i):l.getPointAt(_).subtract(d),m=o?p.negate():c.getPointAt(-_).subtract(d),y=v.getAngle(),w=g.getAngle(),x=m.getAngle(),b=p.getAngle();return!!(a?t(y,x,b)^t(w,x,b)&&t(y,b,x)^t(w,b,x):t(x,y,w)^t(b,y,w)&&t(x,w,y)^t(b,w,y))},hasOverlap:function(){return!!this._overlap}},r.each(T._evaluateMethods,function(t){var e=t+"At";this[t]=function(){var t=this.getCurve(),n=this.getTime();return null!=n&&t&&t[e](n,!0)}},{preserve:!0}),new function(){function t(t,e,n){function i(n,i){for(var s=n+i;s>=-1&&s<=r;s+=i){var a=t[(s%r+r)%r];if(!e.getPoint().isClose(a.getPoint(),2e-7))break;if(e.equals(a))return a}return null}for(var r=t.length,s=0,a=r-1;s<=a;){var o,h=s+a>>>1,u=t[h];if(n&&(o=e.equals(u)?u:i(h,-1)||i(h,1)))return e._overlap&&(o._overlap=o._intersection._overlap=!0),o;var l=e.getPath(),c=u.getPath(),f=l===c?e.getIndex()+e.getTime()-(u.getIndex()+u.getTime()):l._id-c._id;f<0?a=h-1:s=h+1}return t.splice(s,0,e),e}return{statics:{insert:t,expand:function(e){for(var n=e.slice(),i=e.length-1;i>=0;i--)t(n,e[i]._intersection,!1);return n}}}}),O=w.extend({_class:"PathItem",_selectBounds:!1,_canScaleStroke:!0,initialize:function(){},statics:{create:function(t){var e=(t&&t.match(/m/gi)||[]).length>1||/z\s*\S+/i.test(t)?L:E;return new e(t)}},_asPathItem:function(){return this},setPathData:function(t){function e(t,e){var n=+i[t];return o&&(n+=h[e]),n}function n(t){return new c(e(t,"x"),e(t+1,"y"))}var i,r,s,a=t&&t.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/gi),o=!1,h=new c,u=new c;this.clear();for(var l=0,f=a&&a.length;l<f;l++){var _=a[l],g=_[0],v=g.toLowerCase();i=_.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);var p=i&&i.length;switch(o=g===v,"z"!==r||/[mz]/.test(v)||this.moveTo(h=u),v){case"m":case"l":for(var m="m"===v,y=0;y<p;y+=2)this[0===y&&m?"moveTo":"lineTo"](h=n(y));s=h,m&&(u=h);break;case"h":case"v":for(var w="h"===v?"x":"y",y=0;y<p;y++)h[w]=e(y,w),this.lineTo(h);s=h;break;case"c":for(var y=0;y<p;y+=6)this.cubicCurveTo(n(y),s=n(y+2),h=n(y+4));break;case"s":for(var y=0;y<p;y+=4)this.cubicCurveTo(/[cs]/.test(r)?h.multiply(2).subtract(s):h,s=n(y),h=n(y+2)),r=v;break;case"q":for(var y=0;y<p;y+=4)this.quadraticCurveTo(s=n(y),h=n(y+2));break;case"t":for(var y=0;y<p;y+=2)this.quadraticCurveTo(s=/[qt]/.test(r)?h.multiply(2).subtract(s):h,h=n(y)),r=v;break;case"a":for(var y=0;y<p;y+=7)this.arcTo(h=n(y+5),new d((+i[y]),(+i[y+1])),+i[y+2],+i[y+4],+i[y+3]);break;case"z":this.closePath(1e-12)}r=v}},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_contains:function(t){var e=t.isInside(this.getBounds({internal:!0,handle:!0}))&&this._getWinding(t);return!!("evenodd"===this.getFillRule()?1&e:e)},getIntersections:function(t,e,n,i){var r=this===t||!t,s=this._matrix._orNullIfIdentity(),a=r?s:(n||t._matrix)._orNullIfIdentity();if(!r&&!this.getBounds(s).touches(t.getBounds(a)))return[];for(var o,t,h=this.getCurves(),u=r?h:t.getCurves(),l=h.length,c=r?l:u.length,f=[],d=[],_=0;_<c;_++)f[_]=u[_].getValues(a);for(var _=0;_<l;_++){var g=h[_],v=r?f[_]:g.getValues(s),p=g.getPath();p!==t&&(t=p,o=[],d.push(o)),r&&T._getSelfIntersection(v,g,o,{include:e,excludeStart:1===l&&g.getPoint1().equals(g.getPoint2())});for(var m=r?_+1:0;m<c;m++){if(i&&o.length)return o;var y=u[m];T._getIntersections(v,f[m],g,y,o,{include:e,excludeStart:r&&g.getPrevious()===y,excludeEnd:r&&g.getNext()===y})}}o=[];for(var _=0,w=d.length;_<w;_++)o.push.apply(o,d[_]);return o},getCrossings:function(t){return this.getIntersections(t,function(t){return t._overlap||t.isCrossing()})},getNearestLocation:function(){for(var t=c.read(arguments),e=this.getCurves(),n=1/0,i=null,r=0,s=e.length;r<s;r++){var a=e[r].getNearestLocation(t);a._distance<n&&(n=a._distance,i=a)}return i},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t},interpolate:function(t,e,n){var i=!this._children,r=i?"_segments":"_children",s=t[r],a=e[r],o=this[r];if(!s||!a||s.length!==a.length)throw new Error("Invalid operands in interpolate() call: "+t+", "+e);var h=o.length,u=a.length;if(h<u)for(var l=i?M:E,c=h;c<u;c++)this.add(new l);else h>u&&this[i?"removeSegments":"removeChildren"](u,h);for(var c=0;c<u;c++)o[c].interpolate(s[c],a[c],n);i&&(this.setClosed(t._closed),this._changed(9))}}),E=O.extend({_class:"Path",_serializeFields:{segments:[],closed:!1},initialize:function(t){this._closed=!1,this._segments=[],this._version=0;var n=Array.isArray(t)?"object"==typeof t[0]?t:arguments:!t||t.size!==e||t.x===e&&t.point===e?null:arguments;n&&n.length>0?this.setSegments(n):(this._curves=e,this._segmentSelection=0,n||"string"!=typeof t||(this.setPathData(t),t=null)),this._initialize(!n&&t)},_equals:function(t){return this._closed===t._closed&&r.equals(this._segments,t._segments)},copyContent:function(t){this.setSegments(t._segments),this._closed=t._closed;var n=t._clockwise;n!==e&&(this._clockwise=n)},_changed:function vt(t){if(vt.base.call(this,t),8&t){if(this._length=this._area=this._clockwise=this._monoCurves=e,16&t)this._version++;else if(this._curves)for(var n=0,i=this._curves.length;n<i;n++)this._curves[n]._changed()}else 32&t&&(this._bounds=e)},getStyle:function(){var t=this._parent;return(t instanceof L?t:this)._style},getSegments:function(){return this._segments},setSegments:function(t){var n=this.isFullySelected();this._segments.length=0,this._segmentSelection=0,this._curves=e,t&&t.length>0&&this._add(M.readAll(t)),n&&this.setFullySelected(!0)},getFirstSegment:function(){return this._segments[0]},getLastSegment:function(){return this._segments[this._segments.length-1]},getCurves:function(){var t=this._curves,e=this._segments;if(!t){var n=this._countCurves();t=this._curves=new Array(n);for(var i=0;i<n;i++)t[i]=new T(this,e[i],e[i+1]||e[0])}return t},getFirstCurve:function(){return this.getCurves()[0]},getLastCurve:function(){var t=this.getCurves();return t[t.length-1]},isClosed:function(){return this._closed},setClosed:function(t){if(this._closed!=(t=!!t)){if(this._closed=t,this._curves){var e=this._curves.length=this._countCurves();t&&(this._curves[e-1]=new T(this,this._segments[e-1],this._segments[0]))}this._changed(25)}}},{beans:!0,getPathData:function(t,e){function n(e,n){e._transformCoordinates(t,g),i=g[0],r=g[1],v?(p.push("M"+_.pair(i,r)),v=!1):(o=g[2],u=g[3],o===i&&u===r&&l===s&&c===a?n||p.push("l"+_.pair(i-s,r-a)):p.push("c"+_.pair(l-s,c-a)+" "+_.pair(o-s,u-a)+" "+_.pair(i-s,r-a))),s=i,a=r,l=g[4],c=g[5]}var i,r,s,a,o,u,l,c,f=this._segments,d=f.length,_=new h(e),g=new Array(6),v=!0,p=[];if(0===d)return"";for(var m=0;m<d;m++)n(f[m]);return this._closed&&d>0&&(n(f[0],!0),p.push("z")),p.join("")},isEmpty:function(){return 0===this._segments.length},_transformContent:function(t){for(var e=this._segments,n=new Array(6),i=0,r=e.length;i<r;i++)e[i]._transformCoordinates(t,n,!0);return!0},_add:function(t,e){for(var n=this._segments,i=this._curves,r=t.length,s=null==e,e=s?n.length:e,a=0;a<r;a++){var o=t[a];o._path&&(o=t[a]=o.clone()),o._path=this,o._index=e+a,o._selection&&this._updateSelection(o,0,o._selection)}if(s)n.push.apply(n,t);else{n.splice.apply(n,[e,0].concat(t));for(var a=e+r,h=n.length;a<h;a++)n[a]._index=a}if(i){var u=this._countCurves(),l=e>0&&e+r-1===u?e-1:e,c=l,f=Math.min(l+r,u);t._curves&&(i.splice.apply(i,[l,0].concat(t._curves)),c+=t._curves.length);for(var a=c;a<f;a++)i.splice(a,0,new T(this,null,null));this._adjustCurves(l,f)}return this._changed(25),t},_adjustCurves:function(t,e){for(var n,i=this._segments,r=this._curves,s=t;s<e;s++)n=r[s],n._path=this,n._segment1=i[s],n._segment2=i[s+1]||i[0],n._changed();(n=r[this._closed&&0===t?i.length-1:t-1])&&(n._segment2=i[t]||i[0],n._changed()),(n=r[e])&&(n._segment1=i[e],n._changed())},_countCurves:function(){var t=this._segments.length;return!this._closed&&t>0?t-1:t},add:function(t){return arguments.length>1&&"number"!=typeof t?this._add(M.readAll(arguments)):this._add([M.read(arguments)])[0]},insert:function(t,e){return arguments.length>2&&"number"!=typeof e?this._add(M.readAll(arguments,1),t):this._add([M.read(arguments,1)],t)[0]},addSegment:function(){return this._add([M.read(arguments)])[0]},insertSegment:function(t){return this._add([M.read(arguments,1)],t)[0]},addSegments:function(t){return this._add(M.readAll(t))},insertSegments:function(t,e){return this._add(M.readAll(e),t)},removeSegment:function(t){return this.removeSegments(t,t+1)[0]||null},removeSegments:function(t,e,n){t=t||0,e=r.pick(e,this._segments.length);var i=this._segments,s=this._curves,a=i.length,o=i.splice(t,e-t),h=o.length;if(!h)return o;for(var u=0;u<h;u++){var l=o[u];l._selection&&this._updateSelection(l,l._selection,0),l._index=l._path=null}for(var u=t,c=i.length;u<c;u++)i[u]._index=u;if(s){for(var f=t>0&&e===a+(this._closed?1:0)?t-1:t,s=s.splice(f,h),u=s.length-1;u>=0;u--)s[u]._path=null;n&&(o._curves=s.slice(1)),this._adjustCurves(f,f)}return this._changed(25),o},clear:"#removeSegments",hasHandles:function(){for(var t=this._segments,e=0,n=t.length;e<n;e++)if(t[e].hasHandles())return!0;return!1},clearHandles:function(){for(var t=this._segments,e=0,n=t.length;e<n;e++)t[e].clearHandles()},getLength:function(){if(null==this._length){for(var t=this.getCurves(),e=0,n=0,i=t.length;n<i;n++)e+=t[n].getLength();this._length=e}return this._length},getArea:function(t){var n=t===e,i=this._area;if(!n||null==i){var r=this._segments,s=r.length,a=n?this._closed:t,o=s-1;i=0;for(var h=0,u=a?s:o;h<u;h++)i+=T.getArea(T.getValues(r[h],r[h<o?h+1:0]));n&&(this._area=i)}return i},isClockwise:function(){return this._clockwise!==e?this._clockwise:this.getArea()>=0},setClockwise:function(t){this.isClockwise()!=(t=!!t)&&this.reverse(),this._clockwise=t},isFullySelected:function(){var t=this._segments.length;return this.isSelected()&&t>0&&this._segmentSelection===7*t},setFullySelected:function(t){t&&this._selectSegments(!0),this.setSelected(t)},setSelection:function pt(t){1&t||this._selectSegments(!1),pt.base.call(this,t)},_selectSegments:function(t){var e=this._segments,n=e.length,i=t?7:0;this._segmentSelection=i*n;for(var r=0;r<n;r++)e[r]._selection=i},_updateSelection:function(t,e,n){t._selection=n;var i=this._segmentSelection+=n-e;i>0&&this.setSelected(!0)},splitAt:function(t){var e="number"==typeof t?this.getLocationAt(t):t,n=e&&e.index,i=e&&e.time,r=4e-7,s=1-r;i>=s&&(n++,i=0);var a=this.getCurves();if(n>=0&&n<a.length){i>=r&&a[n++].divideAtTime(i);var o,h=this.removeSegments(n,this._segments.length,!0);return this._closed?(this.setClosed(!1),o=this):(o=new E(w.NO_INSERT),o.insertAbove(this,!0),o.copyAttributes(this)),o._add(h,0),this.addSegment(h[0]),o}return null},split:function(t,n){var i,r=n===e?t:(i=this.getCurves()[t])&&i.getLocationAtTime(n);return null!=r?this.splitAt(r):null},join:function(t,e){var n=e||0;if(t&&t!==this){var i=t._segments,r=this.getLastSegment(),s=t.getLastSegment();if(!s)return this;r&&r._point.isClose(s._point,n)&&t.reverse();var a=t.getFirstSegment();if(r&&r._point.isClose(a._point,n))r.setHandleOut(a._handleOut),this._add(i.slice(1));else{var o=this.getFirstSegment();o&&o._point.isClose(a._point,n)&&t.reverse(),s=t.getLastSegment(),o&&o._point.isClose(s._point,n)?(o.setHandleIn(s._handleIn),this._add(i.slice(0,i.length-1),0)):this._add(i.slice())}t._closed&&this._add([i[0]]),t.remove()}var h=this.getFirstSegment(),u=this.getLastSegment();return h!==u&&h._point.isClose(u._point,n)&&(h.setHandleIn(u._handleIn),u.remove(),this.setClosed(!0)),this},reduce:function(t){for(var e=this.getCurves(),n=t&&t.simplify,i=n?2e-7:0,r=e.length-1;r>=0;r--){var s=e[r];!s.hasHandles()&&(s.getLength()<i||n&&s.isCollinear(s.getNext()))&&s.remove()}return this},reverse:function(){this._segments.reverse();for(var t=0,n=this._segments.length;t<n;t++){var i=this._segments[t],r=i._handleIn;i._handleIn=i._handleOut,i._handleOut=r,i._index=t}this._curves=null,this._clockwise!==e&&(this._clockwise=!this._clockwise),this._changed(9)},flatten:function(t){for(var e=new N(this,t||.25,256,(!0)),n=e.parts,i=n.length,r=[],s=0;s<i;s++)r.push(new M(n[s].curve.slice(0,2)));!this._closed&&i>0&&r.push(new M(n[i-1].curve.slice(6))),this.setSegments(r)},simplify:function(t){var e=new B(this).fit(t||2.5);return e&&this.setSegments(e),!!e},smooth:function(t){function n(t,e){var n=t&&t.index;if(null!=n){var r=t.path;if(r&&r!==i)throw new Error(t._class+" "+n+" of "+r+" is not part of "+i);e&&t instanceof T&&n++}else n="number"==typeof t?t:e;return Math.min(n<0&&h?n%o:n<0?n+o:n,o-1)}var i=this,r=t||{},s=r.type||"asymmetric",a=this._segments,o=a.length,h=this._closed,u=h&&r.from===e&&r.to===e,l=n(r.from,0),c=n(r.to,o-1);if(l>c)if(h)l-=o;else{var f=l;l=c,c=f}if(/^(?:asymmetric|continuous)$/.test(s)){var d="asymmetric"===s,_=Math.min,g=c-l+1,v=g-1,p=u?_(g,4):1,m=p,y=p,w=[];if(h||(m=_(1,l),y=_(1,o-c-1)),v+=m+y,v<=1)return;for(var x=0,b=l-m;x<=v;x++,b++)w[x]=a[(b<0?b+o:b)%o]._point;for(var C=w[0]._x+2*w[1]._x,S=w[0]._y+2*w[1]._y,k=2,I=v-1,P=[C],M=[S],A=[k],z=[],O=[],x=1;x<v;x++){var E=x<I,L=E?1:d?1:2,N=E?4:d?2:7,B=E?4:d?3:8,j=E?2:d?0:1,F=L/k;k=A[x]=N-F,C=P[x]=B*w[x]._x+j*w[x+1]._x-F*C,S=M[x]=B*w[x]._y+j*w[x+1]._y-F*S}z[I]=P[I]/A[I],O[I]=M[I]/A[I];for(var x=v-2;x>=0;x--)z[x]=(P[x]-z[x+1])/A[x],O[x]=(M[x]-O[x+1])/A[x];z[v]=(3*w[v]._x-z[I])/2,O[v]=(3*w[v]._y-O[I])/2;for(var x=m,D=v-y,b=l;x<=D;x++,b++){var R=a[b<0?b+o:b],q=R._point,V=z[x]-q._x,H=O[x]-q._y;(u||x<D)&&R.setHandleOut(V,H),(u||x>m)&&R.setHandleIn(-V,-H)}}else for(var x=l;x<=c;x++)a[x<0?x+o:x].smooth(r,!u&&x===l,!u&&x===c)},toShape:function(t){function n(t,e){var n=c[t],i=n.getNext(),r=c[e],s=r.getNext();return n._handleOut.isZero()&&i._handleIn.isZero()&&r._handleOut.isZero()&&s._handleIn.isZero()&&i._point.subtract(n._point).isCollinear(s._point.subtract(r._point))}function i(t){var e=c[t],n=e.getPrevious(),i=e.getNext();return n._handleOut.isZero()&&e._handleIn.isZero()&&e._handleOut.isZero()&&i._handleIn.isZero()&&e._point.subtract(n._point).isOrthogonal(i._point.subtract(e._point))}function r(t){var e=c[t],n=e.getNext(),i=e._handleOut,r=n._handleIn,s=.5522847498307936;if(i.isOrthogonal(r)){var a=e._point,o=n._point,h=new m(a,i,(!0)).intersect(new m(o,r,(!0)),!0);return h&&u.isZero(i.getLength()/h.subtract(a).getLength()-s)&&u.isZero(r.getLength()/h.subtract(o).getLength()-s)}return!1}function s(t,e){return c[t]._point.getDistance(c[e]._point)}if(!this._closed)return null;var a,o,h,l,c=this._segments;if(!this.hasHandles()&&4===c.length&&n(0,2)&&n(1,3)&&i(1)?(a=C.Rectangle,o=new d(s(0,3),s(0,1)),l=c[1]._point.add(c[2]._point).divide(2)):8===c.length&&r(0)&&r(2)&&r(4)&&r(6)&&n(1,5)&&n(3,7)?(a=C.Rectangle,o=new d(s(1,6),s(0,3)),h=o.subtract(new d(s(0,7),s(1,2))).divide(2),l=c[3]._point.add(c[4]._point).divide(2)):4===c.length&&r(0)&&r(1)&&r(2)&&r(3)&&(u.isZero(s(0,2)-s(1,3))?(a=C.Circle,h=s(0,2)/2):(a=C.Ellipse,h=new d(s(2,0)/2,s(3,1)/2)),l=c[1]._point),a){var f=this.getPosition(!0),_=new a({center:f,size:o,radius:h,insert:!1});return _.copyAttributes(this,!0),_._matrix.prepend(this._matrix),_.rotate(l.subtract(f).getAngle()+90),(t===e||t)&&_.insertAbove(this),_}return null},toPath:"#clone",_hitTestSelf:function(t,e,n,i){function r(e,n){return t.subtract(e).divide(n).length<=1}function s(t,n,i){if(!e.selected||n.isSelected()){var s=t._point;if(n!==s&&(n=n.add(s)),r(n,x))return new P(i,g,{segment:t,point:n})}}function a(t,n){return(n||e.segments)&&s(t,t._point,"segment")||!n&&e.handles&&(s(t,t._handleIn,"handle-in")||s(t,t._handleOut,"handle-out"))}function o(t){f.add(t)}function h(e){if(("round"!==u||"round"!==l)&&(f=new E({internal:!0,closed:!0}),y||e._index>0&&e._index<m-1?"round"!==u&&(e._handleIn.isZero()||e._handleOut.isZero())&&E._addBevelJoin(e,u,k,c,null,i,o,!0):"round"!==l&&E._addSquareCap(e,l,k,null,i,o,!0),!f.isEmpty())){var n;return f.contains(t)||(n=f.getNearestLocation(t))&&r(n.getPoint(),w)}return r(e._point,x)}var u,l,c,f,d,_,g=this,v=this.getStyle(),p=this._segments,m=p.length,y=this._closed,w=e._tolerancePadding,x=w,b=e.stroke&&v.hasStroke(),C=e.fill&&v.hasFill(),S=e.curves,k=b?v.getStrokeWidth()/2:C&&e.tolerance>0||S?0:null;if(null!==k&&(k>0?(u=v.getStrokeJoin(),l=v.getStrokeCap(),c=k*v.getMiterLimit(),x=x.add(E._getStrokePadding(k,i))):u=l="round"),!e.ends||e.segments||y){if(e.segments||e.handles)for(var I=0;I<m;I++)if(_=a(p[I]))return _}else if(_=a(p[0],!0)||a(p[m-1],!0))return _;if(null!==k){if(d=this.getNearestLocation(t)){var M=d.getTime();0===M||1===M&&m>1?h(d.getSegment())||(d=null):r(d.getPoint(),x)||(d=null)}if(!d&&"miter"===u&&m>1)for(var I=0;I<m;I++){var A=p[I];if(t.getDistance(A._point)<=c&&h(A)){d=A.getLocation();break}}}return!d&&C&&this._contains(t)||d&&!b&&!S?new P("fill",this):d?new P(b?"stroke":"curve",this,{location:d,point:d.getPoint()}):null}},r.each(T._evaluateMethods,function(t){this[t+"At"]=function(e){var n=this.getLocationAt(e);return n&&n[t]()}},{beans:!1,getLocationOf:function(){for(var t=c.read(arguments),e=this.getCurves(),n=0,i=e.length;n<i;n++){var r=e[n].getLocationOf(t);if(r)return r}return null},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getLocationAt:function(t){for(var e=this.getCurves(),n=0,i=0,r=e.length;i<r;i++){var s=n,a=e[i];if(n+=a.getLength(),n>t)return a.getLocationAt(t-s)}return e.length>0&&t<=this.getLength()?new z(e[e.length-1],1):null}}),new function(){function t(t,e,n,i){function r(e){var n=h[e],i=h[e+1];s==n&&a==i||(t.beginPath(),t.moveTo(s,a),t.lineTo(n,i),t.stroke(),t.beginPath(),t.arc(n,i,o,0,2*Math.PI,!0),t.fill())}for(var s,a,o=i/2,h=new Array(6),u=0,l=e.length;u<l;u++){var c=e[u],f=c._selection;if(c._transformCoordinates(n,h),s=h[0],a=h[1],2&f&&r(2),4&f&&r(4),t.fillRect(s-o,a-o,i,i),!(1&f)){var d=t.fillStyle;t.fillStyle="#ffffff",t.fillRect(s-o+1,a-o+1,i-2,i-2),t.fillStyle=d}}}function e(t,e,n){function i(e){if(n)e._transformCoordinates(n,_),r=_[0],s=_[1];else{var i=e._point;r=i._x,s=i._y}if(g)t.moveTo(r,s),g=!1;else{if(n)h=_[2],u=_[3];else{var f=e._handleIn;h=r+f._x,u=s+f._y}h===r&&u===s&&l===a&&c===o?t.lineTo(r,s):t.bezierCurveTo(l,c,h,u,r,s)}if(a=r,o=s,n)l=_[4],c=_[5];else{var f=e._handleOut;l=a+f._x,c=o+f._y}}for(var r,s,a,o,h,u,l,c,f=e._segments,d=f.length,_=new Array(6),g=!0,v=0;v<d;v++)i(f[v]);e._closed&&d>0&&i(f[0])}return{_draw:function(t,n,i,r){function s(t){return c[(t%f+f)%f]}var a=n.dontStart,o=n.dontFinish||n.clip,h=this.getStyle(),u=h.hasFill(),l=h.hasStroke(),c=h.getDashArray(),f=!paper.support.nativeDash&&l&&c&&c.length;if(a||t.beginPath(),(u||l&&!f||o)&&(e(t,this,r),this._closed&&t.closePath()),!o&&(u||l)&&(this._setStyles(t,n,i),u&&(t.fill(h.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),l)){if(f){a||t.beginPath();var d,_=new N(this,.25,32,(!1),r),g=_.length,v=-h.getDashOffset(),p=0;for(v%=g;v>0;)v-=s(p--)+s(p--);for(;v<g;)d=v+s(p++),(v>0||d>0)&&_.drawPart(t,Math.max(v,0),Math.max(d,0)),v=d+s(p++)}t.stroke()}},_drawSelected:function(n,i){n.beginPath(),e(n,this,i),n.stroke(),t(n,this._segments,i,paper.settings.handleSize)}}},new function(){function t(t){var e=t._segments;if(0===e.length)throw new Error("Use a moveTo() command first");return e[e.length-1]}return{moveTo:function(){var t=this._segments;1===t.length&&this.removeSegment(0),t.length||this._add([new M(c.read(arguments))])},moveBy:function(){throw new Error("moveBy() is unsupported on Path items.")},lineTo:function(){this._add([new M(c.read(arguments))])},cubicCurveTo:function(){var e=c.read(arguments),n=c.read(arguments),i=c.read(arguments),r=t(this);r.setHandleOut(e.subtract(r._point)),this._add([new M(i,n.subtract(i))])},quadraticCurveTo:function(){var e=c.read(arguments),n=c.read(arguments),i=t(this)._point;this.cubicCurveTo(e.add(i.subtract(e).multiply(1/3)),e.add(n.subtract(e).multiply(1/3)),n)},curveTo:function(){var e=c.read(arguments),n=c.read(arguments),i=r.pick(r.read(arguments),.5),s=1-i,a=t(this)._point,o=e.subtract(a.multiply(s*s)).subtract(n.multiply(i*i)).divide(2*i*s);if(o.isNaN())throw new Error("Cannot put a curve through points with parameter = "+i);this.quadraticCurveTo(o,n)},arcTo:function(){var e,n,i,s,a,o=t(this),h=o._point,l=c.read(arguments),f=r.peek(arguments),_=r.pick(f,!0);if("boolean"==typeof _)var g=h.add(l).divide(2),e=g.add(g.subtract(h).rotate(_?-90:90));else if(r.remain(arguments)<=2)e=l,l=c.read(arguments);else{var v=d.read(arguments),y=u.isZero;if(y(v.width)||y(v.height))return this.lineTo(l);var w=r.read(arguments),_=!!r.read(arguments),x=!!r.read(arguments),g=h.add(l).divide(2),b=h.subtract(g).rotate(-w),C=b.x,S=b.y,k=Math.abs,I=k(v.width),P=k(v.height),A=I*I,T=P*P,z=C*C,O=S*S,E=Math.sqrt(z/A+O/T);if(E>1&&(I*=E,P*=E,A=I*I,T=P*P),E=(A*T-A*O-T*z)/(A*O+T*z),k(E)<1e-12&&(E=0),E<0)throw new Error("Cannot create an arc with the given arguments");n=new c(I*S/P,-P*C/I).multiply((x===_?-1:1)*Math.sqrt(E)).rotate(w).add(g),a=(new p).translate(n).rotate(w).scale(I,P),s=a._inverseTransform(h),i=s.getDirectedAngle(a._inverseTransform(l)),!_&&i>0?i-=360:_&&i<0&&(i+=360)}if(e){var L=new m(h.add(e).divide(2),e.subtract(h).rotate(90),(!0)),N=new m(e.add(l).divide(2),l.subtract(e).rotate(90),(!0)),B=new m(h,l),j=B.getSide(e);if(n=L.intersect(N,!0),!n){if(!j)return this.lineTo(l);throw new Error("Cannot create an arc with the given arguments")}s=h.subtract(n),i=s.getDirectedAngle(l.subtract(n));var F=B.getSide(n);0===F?i=j*Math.abs(i):j===F&&(i+=i<0?360:-360)}for(var D=Math.abs(i),R=D>=360?4:Math.ceil(D/90),q=i/R,V=q*Math.PI/360,H=4/3*Math.sin(V)/(1+Math.cos(V)),U=[],Z=0;Z<=R;Z++){var b=l,W=null;if(Z<R&&(W=s.rotate(90).multiply(H),a?(b=a._transformPoint(s),W=a._transformPoint(s.add(W)).subtract(b)):b=n.add(s)),0===Z)o.setHandleOut(W);else{var G=s.rotate(-90).multiply(H);a&&(G=a._transformPoint(s.add(G)).subtract(b)),U.push(new M(b,G,W))}s=s.rotate(q)}this._add(U)},lineBy:function(){var e=c.read(arguments),n=t(this)._point;this.lineTo(n.add(e))},curveBy:function(){var e=c.read(arguments),n=c.read(arguments),i=r.read(arguments),s=t(this)._point;this.curveTo(s.add(e),s.add(n),i)},cubicCurveBy:function(){var e=c.read(arguments),n=c.read(arguments),i=c.read(arguments),r=t(this)._point;this.cubicCurveTo(r.add(e),r.add(n),r.add(i))},quadraticCurveBy:function(){var e=c.read(arguments),n=c.read(arguments),i=t(this)._point;this.quadraticCurveTo(i.add(e),i.add(n))},arcBy:function(){var e=t(this)._point,n=e.add(c.read(arguments)),i=r.pick(r.peek(arguments),!0);"boolean"==typeof i?this.arcTo(n,i):this.arcTo(n,e.add(c.read(arguments)))},closePath:function(t){this.setClosed(!0),this.join(this,t)}}},{_getBounds:function(t,e){var n=e.handle?"getHandleBounds":e.stroke?"getStrokeBounds":"getBounds";return E[n](this._segments,this._closed,this,t,e)},statics:{getBounds:function(t,e,n,i,r,s){function a(t){t._transformCoordinates(i,h);for(var e=0;e<2;e++)T._addBounds(u[e],u[e+4],h[e+2],h[e],e,s?s[e]:0,l,c,f);var n=u;u=h,h=n}var o=t[0];if(!o)return new g;for(var h=new Array(6),u=o._transformCoordinates(i,new Array(6)),l=u.slice(0,2),c=l.slice(),f=new Array(2),d=1,_=t.length;d<_;d++)a(t[d]);return e&&a(o),new g(l[0],l[1],c[0]-l[0],c[1]-l[1])},getStrokeBounds:function(t,e,n,i,r){function s(t){v=v.include(t)}function a(t){v=v.unite(x.setCenter(t._point.transform(i)))}function o(t,e){var n=t._handleIn,r=t._handleOut;"round"===e||!n.isZero()&&!r.isZero()&&n.isCollinear(r)?a(t):E._addBevelJoin(t,e,p,w,i,f,s)}function h(t,e){"round"===e?a(t):E._addSquareCap(t,e,p,i,f,s)}var u=n.getStyle(),l=u.hasStroke(),c=u.getStrokeWidth(),f=l&&n._getStrokeMatrix(i,r),_=l&&E._getStrokePadding(c,f),v=E.getBounds(t,e,n,i,r,_);if(!l)return v;for(var p=c/2,m=u.getStrokeJoin(),y=u.getStrokeCap(),w=p*u.getMiterLimit(),x=new g(new d(_)),b=t.length-(e?0:1),C=1;C<b;C++)o(t[C],m);return e?o(t[0],m):b>0&&(h(t[0],y),h(t[t.length-1],y)),v},_getStrokePadding:function(t,e){
+if(!e)return[t,t];var n=new c(t,0).transform(e),i=new c(0,t).transform(e),r=n.getAngleInRadians(),s=n.getLength(),a=i.getLength(),o=Math.sin(r),h=Math.cos(r),u=Math.tan(r),l=Math.atan2(a*u,s),f=Math.atan2(a,u*s);return[Math.abs(s*Math.cos(l)*h+a*Math.sin(l)*o),Math.abs(a*Math.sin(f)*h+s*Math.cos(f)*o)]},_addBevelJoin:function(t,e,n,i,r,s,a,o){var h=t.getCurve(),u=h.getPrevious(),l=h.getPointAtTime(0),f=u.getNormalAtTime(1),d=h.getNormalAtTime(0),_=f.getDirectedAngle(d)<0?-n:n;if(f.setLength(_),d.setLength(_),r&&r._transformPoint(l,l),s&&(s._transformPoint(f,f),s._transformPoint(d,d)),o&&(a(l),a(l.add(f))),"miter"===e){var g=new m(l.add(f),new c((-f.y),f.x),(!0)).intersect(new m(l.add(d),new c((-d.y),d.x),(!0)),!0);if(g&&l.getDistance(g)<=i&&(a(g),!o))return}o||a(l.add(f)),a(l.add(d))},_addSquareCap:function(t,e,n,i,r,s,a){var o=t._point,h=t.getLocation(),u=h.getNormal().multiply(n);i&&i._transformPoint(o,o),r&&r._transformPoint(u,u),a&&(s(o.subtract(u)),s(o.add(u))),"square"===e&&(o=o.add(u.rotate(0===h.getTime()?-90:90))),s(o.add(u)),s(o.subtract(u))},getHandleBounds:function(t,e,n,i,r){var s,a,o=n.getStyle(),h=r.stroke&&o.hasStroke();if(h){var u=n._getStrokeMatrix(i,r),l=o.getStrokeWidth()/2,c=l;"miter"===o.getStrokeJoin()&&(c=l*o.getMiterLimit()),"square"===o.getStrokeCap()&&(c=Math.max(c,l*Math.sqrt(2))),s=E._getStrokePadding(l,u),a=E._getStrokePadding(c,u)}for(var f=new Array(6),d=1/0,_=-d,v=d,p=_,m=0,y=t.length;m<y;m++){var w=t[m];w._transformCoordinates(i,f);for(var x=0;x<6;x+=2){var b=0===x?a:s,C=b?b[0]:0,S=b?b[1]:0,k=f[x],I=f[x+1],P=k-C,M=k+C,A=I-S,T=I+S;P<d&&(d=P),M>_&&(_=M),A<v&&(v=A),T>p&&(p=T)}}return new g(d,v,_-d,p-v)}}});E.inject({statics:new function(){function t(t,e,n){var i=r.getNamed(n),s=new E(i&&i.insert===!1&&w.NO_INSERT);return s._add(t),s._closed=e,s.set(i)}function e(e,n,r){for(var s=new Array(4),a=0;a<4;a++){var o=i[a];s[a]=new M(o._point.multiply(n).add(e),o._handleIn.multiply(n),o._handleOut.multiply(n))}return t(s,!0,r)}var n=.5522847498307936,i=[new M([-1,0],[0,n],[0,-n]),new M([0,-1],[-n,0],[n,0]),new M([1,0],[0,-n],[0,n]),new M([0,1],[n,0],[-n,0])];return{Line:function(){return t([new M(c.readNamed(arguments,"from")),new M(c.readNamed(arguments,"to"))],!1,arguments)},Circle:function(){var t=c.readNamed(arguments,"center"),n=r.readNamed(arguments,"radius");return e(t,new d(n),arguments)},Rectangle:function(){var e,i=g.readNamed(arguments,"rectangle"),r=d.readNamed(arguments,"radius",0,{readNull:!0}),s=i.getBottomLeft(!0),a=i.getTopLeft(!0),o=i.getTopRight(!0),h=i.getBottomRight(!0);if(!r||r.isZero())e=[new M(s),new M(a),new M(o),new M(h)];else{r=d.min(r,i.getSize(!0).divide(2));var u=r.width,l=r.height,c=u*n,f=l*n;e=[new M(s.add(u,0),null,[-c,0]),new M(s.subtract(0,l),[0,f]),new M(a.add(0,l),null,[0,-f]),new M(a.add(u,0),[-c,0],null),new M(o.subtract(u,0),null,[c,0]),new M(o.add(0,l),[0,-f],null),new M(h.subtract(0,l),null,[0,f]),new M(h.subtract(u,0),[c,0])]}return t(e,!0,arguments)},RoundRectangle:"#Rectangle",Ellipse:function(){var t=C._readEllipse(arguments);return e(t.center,t.radius,arguments)},Oval:"#Ellipse",Arc:function(){var t=c.readNamed(arguments,"from"),e=c.readNamed(arguments,"through"),n=c.readNamed(arguments,"to"),i=r.getNamed(arguments),s=new E(i&&i.insert===!1&&w.NO_INSERT);return s.moveTo(t),s.arcTo(e,n),s.set(i)},RegularPolygon:function(){for(var e=c.readNamed(arguments,"center"),n=r.readNamed(arguments,"sides"),i=r.readNamed(arguments,"radius"),s=360/n,a=n%3===0,o=new c(0,a?-i:i),h=a?-1:.5,u=new Array(n),l=0;l<n;l++)u[l]=new M(e.add(o.rotate((l+h)*s)));return t(u,!0,arguments)},Star:function(){for(var e=c.readNamed(arguments,"center"),n=2*r.readNamed(arguments,"points"),i=r.readNamed(arguments,"radius1"),s=r.readNamed(arguments,"radius2"),a=360/n,o=new c(0,(-1)),h=new Array(n),u=0;u<n;u++)h[u]=new M(e.add(o.rotate(a*u).multiply(u%2?s:i)));return t(h,!0,arguments)}}}});var L=O.extend({_class:"CompoundPath",_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||("string"==typeof t?this.setPathData(t):this.addChildren(Array.isArray(t)?t:arguments))},insertChildren:function mt(t,n,i){for(var r=n.length-1;r>=0;r--){var s=n[r];s instanceof L&&(n=n.slice(),n.splice.apply(n,[r,1].concat(s.removeChildren())),s.remove())}n=mt.base.call(this,t,n,i,E);for(var r=0,a=!i&&n&&n.length;r<a;r++){var s=n[r];s._clockwise===e&&s.setClockwise(0===s._index)}return n},reduce:function yt(t){for(var e=this._children,n=e.length-1;n>=0;n--){var i=e[n].reduce(t);i.isEmpty()&&i.remove()}if(0===e.length){var i=new E(w.NO_INSERT);return i.copyAttributes(this),i.insertAbove(this),this.remove(),i}return yt.base.call(this)},isClockwise:function(){var t=this.getFirstChild();return t&&t.isClockwise()},setClockwise:function(t){this.isClockwise()^!!t&&this.reverse()},getFirstSegment:function(){var t=this.getFirstChild();return t&&t.getFirstSegment()},getLastSegment:function(){var t=this.getLastChild();return t&&t.getLastSegment()},getCurves:function(){for(var t=this._children,e=[],n=0,i=t.length;n<i;n++)e.push.apply(e,t[n].getCurves());return e},getFirstCurve:function(){var t=this.getFirstChild();return t&&t.getFirstCurve()},getLastCurve:function(){var t=this.getLastChild();return t&&t.getFirstCurve()},getArea:function(){for(var t=this._children,e=0,n=0,i=t.length;n<i;n++)e+=t[n].getArea();return e}},{beans:!0,getPathData:function(t,e){for(var n=this._children,i=[],r=0,s=n.length;r<s;r++){var a=n[r],o=a._matrix;i.push(a.getPathData(t&&!o.isIdentity()?t.appended(o):t,e))}return i.join(" ")}},{_hitTestChildren:function wt(t,e,n){return wt.base.call(this,t,e["class"]===E||"path"===e.type?e:r.set({},e,{fill:!1}),n)},_draw:function(t,e,n,i){var r=this._children;if(0!==r.length){e=e.extend({dontStart:!0,dontFinish:!0}),t.beginPath();for(var s=0,a=r.length;s<a;s++)r[s].draw(t,e,i);if(!e.clip){this._setStyles(t,e,n);var o=this._style;o.hasFill()&&(t.fill(o.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),o.hasStroke()&&t.stroke()}}},_drawSelected:function(t,e,n){for(var i=this._children,r=0,s=i.length;r<s;r++){var a=i[r],o=a._matrix;n[a._id]||a._drawSelected(t,o.isIdentity()?e:e.appended(o))}}},new function(){function t(t,e){var n=t._children;if(e&&0===n.length)throw new Error("Use a moveTo() command first");return n[n.length-1]}return r.each(["lineTo","cubicCurveTo","quadraticCurveTo","curveTo","arcTo","lineBy","cubicCurveBy","quadraticCurveBy","curveBy","arcBy"],function(e){this[e]=function(){var n=t(this,!0);n[e].apply(n,arguments)}},{moveTo:function(){var e=t(this),n=e&&e.isEmpty()?e:new E(w.NO_INSERT);n!==e&&this.addChild(n),n.moveTo.apply(n,arguments)},moveBy:function(){var e=t(this,!0),n=e&&e.getLastSegment(),i=c.read(arguments);this.moveTo(n?i.add(n._point):i)},closePath:function(e){t(this,!0).closePath(e)}})},r.each(["reverse","flatten","simplify","smooth"],function(t){this[t]=function(e){for(var n,i=this._children,r=0,s=i.length;r<s;r++)n=i[r][t](e)||n;return n}},{}));O.inject(new function(){function t(t,e){var n=t.clone(!1).reduce({simplify:!0}).transform(null,!0,!0);return e?n.resolveCrossings():n}function e(t,e,n,i,r){var s=new t(w.NO_INSERT);return s.addChildren(e,!0),n&&(s=s.reduce({simplify:!0})),s.insertAbove(r&&i.isSibling(r)&&i.getIndex()<r.getIndex()?r:i),s.copyAttributes(i,!0),s}function n(n,r,s){function o(t){for(var e=0,n=t.length;e<n;e++){var i=t[e];g.push.apply(g,i._segments),v.push.apply(v,i._getMonoCurves()),i._overlapsOnly=i._validOverlapsOnly=!0}}var u=f[s];if(u[s]=!0,!n._children&&!n._closed)return i(n,r,u);var c=t(n,!0),d=r&&n!==r&&t(r,!0);d&&(u.subtract||u.exclude)^(d.isClockwise()^c.isClockwise())&&d.reverse();var _=a(z.expand(c.getCrossings(d))),g=[],v=[];o(c._children||[c]),d&&o(d._children||[d]);for(var p=0,m=_.length;p<m;p++)h(_[p]._segment,c,d,v,u);for(var p=0,m=g.length;p<m;p++){var y=g[p],w=y._intersection;if(null==y._winding&&h(y,c,d,v,u),!w||!w._overlap){var x=y._path;x._overlapsOnly=!1,u[y._winding]&&(x._validOverlapsOnly=!1)}}return e(L,l(g,u),!0,n,r)}function i(n,i,r){function s(t){if(o.contains(t.getPointAt(t.getLength()/2))^u)return l.unshift(t),!0}if(!i||!i._children&&!i._closed||!r.subtract&&!r.intersect)return null;for(var a=t(n,!1),o=t(i,!1),h=a.getCrossings(o),u=r.subtract,l=[],c=h.length-1;c>=0;c--){var f=h[c].split();f&&(s(f)&&f.getFirstSegment().setHandleIn(0,0),a.getLastSegment().setHandleOut(0,0))}return s(a),e(x,l,!1,n,i)}function s(t,e){for(var n=t;n;){if(n===e)return;n=n._previous}for(;t._next&&t._next!==e;)t=t._next;if(!t._next){for(;e._previous;)e=e._previous;t._next=e,e._previous=t}}function a(t,e){for(var n,i,r=e&&[],a=4e-7,o=1-a,h=!1,u=[],l=t.length-1;l>=0;l--){var c=t[l];if(e){if(!e(c))continue;r.unshift(c)}var f,d=c._curve,_=c._time,g=_;if(d!==n?h=!d.hasHandles():i>=a&&i<=o&&(_/=i),_<a)f=d._segment1;else if(_>o)f=d._segment2;else{var v=d.divideAtTime(_,!0);h&&u.push(d,v),f=v._segment1}c._setSegment(f);var p=f._intersection,m=c._intersection;if(p){s(p,m);for(var y=p;y;)s(y._intersection,p),y=y._next}else f._intersection=m;n=d,i=g}for(var l=0,w=u.length;l<w;l++)u[l].clearHandles();return r||t}function o(t,e,n){var i=2e-7,r=t.x,s=t.y,a=0,h=0,u=e.length,l=[],f=Math.abs;if(n){for(var d=-(1/0),_=1/0,g=s-i,v=s+i,p=0;p<u;p++)for(var m=e[p].values,y=T.solveCubic(m,0,r,l,0,1),w=y-1;w>=0;w--){var x=T.getPoint(m,l[w]).y;x<g&&x>d?d=x:x>v&&x<_&&(_=x)}d=(d+s)/2,_=(_+s)/2,d>-(1/0)&&(a=o(new c(r,d),e).winding),_<1/0&&(h=o(new c(r,_),e).winding)}else{for(var b,C,S=r-i,k=r+i,I=0,P=0,M=!1,p=0;p<u;p++){var A=e[p],z=A.winding,m=A.values,O=m[1],E=m[7];if(A.last&&(b=A.last.winding,C=A.last.values[6],M=!1),s>=O&&s<=E||s>=E&&s<=O)if(z){var L=s===O?m[0]:s===E?m[6]:1===T.solveCubic(m,1,s,l,0,1)?T.getPoint(m,l[0]).x:null;null!=L&&(L>=S&&L<=k?M=!0:s===O&&z===b||s===O&&(r-L)*(r-C)<0||(L<S?a+=z:L>k&&(h+=z))),b=z,C=m[6]}else(r-m[0])*(r-m[6])<=0&&(M=!0);M&&(p>=u-1||e[p+1].last)&&(I+=1,P-=1)}0===a&&0===h&&(a=I,h=P)}return{winding:Math.max(f(a),f(h)),contour:!a^!h}}function h(t,e,n,i,r){var s,a=[],h=t,u=0;do{var l=t.getCurve(),c=l.getLength();a.push({segment:t,curve:l,length:c}),u+=c,t=t.getNext()}while(t&&!t._intersection&&t!==h);for(var c=u/2,f=0,d=a.length;f<d;f++){var _=a[f],g=_.length;if(c<=g){var l=_.curve,v=l._path,p=v._parent,m=l.getTimeAt(c),y=l.getPointAtTime(m),w=Math.abs(l.getTangentAtTime(m).y)<1e-7;p instanceof L&&(v=p),s=r.subtract&&n&&(v===e&&n._getWinding(y,w)||v===n&&!e._getWinding(y,w))?{winding:0}:o(y,i,w);break}c-=g}for(var f=a.length-1;f>=0;f--){var x=a[f].segment;x._winding=s.winding,x._contour=s.contour}}function l(t,e){function n(t,n){return!(!t||t._visited||!(!e||e[t._winding]||!n&&e.unite&&t._contour))}function i(t){return t===a||t===o}function s(t,r){if(!t._next)return t;for(;t;){var s=t._segment,a=s.getNext(),o=a&&a._intersection;if(s!==r&&(i(s)||i(a)||!s._visited&&!a._visited&&(!e||n(s)&&(n(a)||o&&n(o._segment)))))return t;t=t._next}return null}for(var a,o,h=[],l=0,c=t.length;l<c;l++){var f,d=null,_=!1,g=t[l],v=g._intersection;if(!g._visited&&g._path._overlapsOnly){var p=g._path,m=v._segment._path,y=p._segments,x=m._segments;if(r.equals(y,x)){(e.unite||e.intersect)&&p.getArea()&&h.push(p.clone(!1));for(var b=0,C=y.length;b<C;b++)y[b]._visited=x[b]._visited=!0}}if(n(g,!0)&&(g._path._validOverlapsOnly||!v||!v._overlap)){for(a=o=null;;){v=v&&s(v,g)||v;var S=v&&v._segment;if(i(g)?_=!0:S&&(i(S)?(_=!0,g=S):n(S,n(g,!0))&&(e&&(e.intersect||e.subtract)&&(g._visited=!0),g=S)),_||g._visited){g._visited=!0;break}if(g._path._validOverlapsOnly&&!n(g))break;d||(d=new E(w.NO_INSERT),a=g,o=S);var k=g.getNext();d.add(new M(g._point,f,k&&g._handleOut)),g._visited=!0,g=k||g._path.getFirstSegment(),f=k&&k._handleIn,v=g._intersection}if(_)d.firstSegment.setHandleIn(f),d.setClosed(!0);else if(d){var I=d.getArea(!0);Math.abs(I)>=2e-7&&console.error("Boolean operation resulted in open path","segments =",d._segments.length,"length =",d.getLength(),"area=",I),d=null}d&&(d._segments.length>8||!u.isZero(d.getArea()))&&(h.push(d),d=null)}}return h}var f={unite:{1:!0},intersect:{2:!0},subtract:{1:!0},exclude:{1:!0}};return{_getWinding:function(t,e){return o(t,this._getMonoCurves(),e).winding},unite:function(t){return n(this,t,"unite")},intersect:function(t){return n(this,t,"intersect")},subtract:function(t){return n(this,t,"subtract")},exclude:function(t){return n(this,t,"exclude")},divide:function(t){return e(x,[this.subtract(t),this.intersect(t)],!0,this,t)},resolveCrossings:function(){function t(t){var e=t&&t._intersection;return e&&e._overlap}var e=this._children,n=e||[this],i=!1,s=!1,o=this.getIntersections(null,function(t){return t._overlap&&(i=!0)||t.isCrossing()&&(s=!0)});if(o=z.expand(o),i)for(var h=a(o,function(t){return t._overlap}),u=h.length-1;u>=0;u--){var c=h[u]._segment,f=c.getPrevious(),d=c.getNext();if(c._path&&t(f)&&t(d)){c.remove(),f._handleOut.set(0,0),d._handleIn.set(0,0);var _=f.getCurve();_.isStraight()&&0===_.getLength()&&f.remove()}}s&&(a(o,i&&function(t){var e=t.getCurve(),n=t._intersection._curve,i=t._segment;return!!(e&&n&&e._path&&n._path)||void(i&&(i._intersection=null))}),n=l(r.each(n,function(t){this.push.apply(this,t._segments)},[])));var g,v=n.length;if(v>1){n=n.slice().sort(function(t,e){return e.getBounds().getArea()-t.getBounds().getArea()});for(var p=n[0],m=[p],y={},x="nonzero"===this.getFillRule(),b=x&&r.each(n,function(t){this.push(t.isClockwise()?1:-1)},[]),u=1;u<v;u++){for(var C=n[u],S=C.getInteriorPoint(),k=!1,I=null,P=!1,M=u-1;M>=0&&!I;M--)if(n[M].contains(S)){if(x&&!k&&(b[u]+=b[M],b[u]&&b[M])){P=y[u]=!0;break}k=!0,I=!y[M]&&n[M]}P||(C.setClockwise(I?!I.isClockwise():p.isClockwise()),m.push(C))}n=m,v=m.length}return v>1&&e?(n!==e&&this.setChildren(n,!0),g=this):1!==v||e||(n[0]!==this&&this.setSegments(n[0].removeSegments()),g=this),g||(g=new L(w.NO_INSERT),g.addChildren(n,!0),g=g.reduce(),g.copyAttributes(this),this.replaceWith(g)),g}}}),E.inject({_getMonoCurves:function(){function t(t){var e=t[1],r=t[7],s=Math.abs((e-r)/(t[0]-t[6]))<2e-7?0:e>r?-1:1,a={values:t,winding:s};i.push(a),s&&(n=a)}function e(e){if(0!==T.getLength(e)){var n=e[1],i=e[3],r=e[5],s=e[7];if(T.isStraight(e)||n>=i==i>=r&&i>=r==r>=s)t(e);else{var a=3*(i-r)-n+s,o=2*(n+r)-4*i,h=i-n,l=4e-7,c=1-l,f=[],d=u.solveQuadratic(a,o,h,f,l,c);if(d<1)t(e);else{f.sort();var _=f[0],g=T.subdivide(e,_);t(g[0]),d>1&&(_=(f[1]-_)/(1-_),g=T.subdivide(g[1],_),t(g[0])),t(g[1])}}}}var n,i=this._monoCurves;if(!i){i=this._monoCurves=[];for(var r=this.getCurves(),s=this._segments,a=0,o=r.length;a<o;a++)e(r[a].getValues());if(!this._closed&&s.length>1){var h=s[s.length-1]._point,l=s[0]._point,c=h._x,f=h._y,d=l._x,_=l._y;e([c,f,c,f,d,_,d,_])}i.length>0&&(i[0].last=n)}return i},getInteriorPoint:function(){var t=this.getBounds(),e=t.getCenter(!0);if(!this.contains(e)){for(var n=this._getMonoCurves(),i=[],r=e.y,s=[],a=0,o=n.length;a<o;a++){var h=n[a].values;if(1===n[a].winding&&r>h[1]&&r<=h[7]||r>=h[7]&&r<h[1])for(var u=T.solveCubic(h,1,r,i,0,1),l=u-1;l>=0;l--)s.push(T.getPoint(h,i[l]).x)}s.sort(function(t,e){return t-e}),e.x=(s[0]+s[1])/2}return e}}),L.inject({_getMonoCurves:function(){for(var t=this._children,e=[],n=0,i=t.length;n<i;n++)e.push.apply(e,t[n]._getMonoCurves());return e}});var N=r.extend({_class:"PathIterator",initialize:function(t,e,n,i,r){function s(t,e){var n=T.getValues(t,e,r);h.push(n),a(n,t._index,0,1)}function a(t,n,r,s){if(!(s-r>c)||i&&T.isStraight(t)||T.isFlatEnough(t,e||.25)){var o=t[6]-t[0],h=t[7]-t[1],f=Math.sqrt(o*o+h*h);f>0&&(l+=f,u.push({offset:l,curve:t,index:n,time:s}))}else{var d=T.subdivide(t,.5),_=(r+s)/2;a(d[0],n,r,_),a(d[1],n,_,s)}}for(var o,h=[],u=[],l=0,c=1/(n||32),f=t._segments,d=f[0],_=1,g=f.length;_<g;_++)o=f[_],s(d,o),d=o;t._closed&&s(o,f[0]),this.curves=h,this.parts=u,this.length=l,this.index=0},_get:function(t){for(var e,n=this.index;e=n,!(0===n||this.parts[--n].offset<t););for(var i=this.parts.length;e<i;e++){var r=this.parts[e];if(r.offset>=t){this.index=e;var s=this.parts[e-1],a=s&&s.index===r.index?s.time:0,o=s?s.offset:0;return{index:r.index,time:a+(r.time-a)*(t-o)/(r.offset-o)}}}var r=this.parts[this.parts.length-1];return{index:r.index,time:1}},drawPart:function(t,e,n){for(var i=this._get(e),r=this._get(n),s=i.index,a=r.index;s<=a;s++){var o=T.getPart(this.curves[s],s===i.index?i.time:0,s===r.index?r.time:1);s===i.index&&t.moveTo(o[0],o[1]),t.bezierCurveTo.apply(t,o.slice(2))}}},r.each(T._evaluateMethods,function(t){this[t+"At"]=function(e){var n=this._get(e);return T[t](this.curves[n.index],n.time)}},{})),B=r.extend({initialize:function(t){for(var e,n=this.points=[],i=t._segments,r=t._closed,s=0,a=i.length;s<a;s++){var o=i[s].point;e&&e.equals(o)||n.push(e=o.clone())}r&&(n.unshift(n[n.length-1]),n.push(n[1])),this.closed=r},fit:function(t){var e=this.points,n=e.length,i=null;return n>0&&(i=[new M(e[0])],n>1&&(this.fitCubic(i,t,0,n-1,e[1].subtract(e[0]),e[n-2].subtract(e[n-1])),this.closed&&(i.shift(),i.pop()))),i},fitCubic:function(t,e,n,i,r,s){var a=this.points;if(i-n===1){var o=a[n],h=a[i],u=o.getDistance(h)/3;return void this.addCurve(t,[o,o.add(r.normalize(u)),h.add(s.normalize(u)),h])}for(var l,c=this.chordLengthParameterize(n,i),f=Math.max(e,e*e),d=!0,_=0;_<=4;_++){var g=this.generateBezier(n,i,c,r,s),v=this.findMaxError(n,i,g,c);if(v.error<e&&d)return void this.addCurve(t,g);if(l=v.index,v.error>=f)break;d=this.reparameterize(n,i,c,g),f=v.error}var p=a[l-1].subtract(a[l+1]);this.fitCubic(t,e,n,l,r,p),this.fitCubic(t,e,l,i,p.negate(),s)},addCurve:function(t,e){var n=t[t.length-1];n.setHandleOut(e[1].subtract(e[0])),t.push(new M(e[3],e[2].subtract(e[3])))},generateBezier:function(t,e,n,i,r){for(var s=1e-12,a=Math.abs,o=this.points,h=o[t],u=o[e],l=[[0,0],[0,0]],c=[0,0],f=0,d=e-t+1;f<d;f++){var _=n[f],g=1-_,v=3*_*g,p=g*g*g,m=v*g,y=v*_,w=_*_*_,x=i.normalize(m),b=r.normalize(y),C=o[t+f].subtract(h.multiply(p+m)).subtract(u.multiply(y+w));l[0][0]+=x.dot(x),l[0][1]+=x.dot(b),l[1][0]=l[0][1],l[1][1]+=b.dot(b),c[0]+=x.dot(C),c[1]+=b.dot(C)}var S,k,I=l[0][0]*l[1][1]-l[1][0]*l[0][1];if(a(I)>s){var P=l[0][0]*c[1]-l[1][0]*c[0],M=c[0]*l[1][1]-c[1]*l[0][1];S=M/I,k=P/I}else{var A=l[0][0]+l[0][1],T=l[1][0]+l[1][1];S=k=a(A)>s?c[0]/A:a(T)>s?c[1]/T:0}var z,O,E=u.getDistance(h),L=s*E;if(S<L||k<L)S=k=E/3;else{var N=u.subtract(h);z=i.normalize(S),O=r.normalize(k),z.dot(N)-O.dot(N)>E*E&&(S=k=E/3,z=O=null)}return[h,h.add(z||i.normalize(S)),u.add(O||r.normalize(k)),u]},reparameterize:function(t,e,n,i){for(var r=t;r<=e;r++)n[r-t]=this.findRoot(i,this.points[r],n[r-t]);for(var r=1,s=n.length;r<s;r++)if(n[r]<=n[r-1])return!1;return!0},findRoot:function(t,e,n){for(var i=[],r=[],s=0;s<=2;s++)i[s]=t[s+1].subtract(t[s]).multiply(3);for(var s=0;s<=1;s++)r[s]=i[s+1].subtract(i[s]).multiply(2);var a=this.evaluate(3,t,n),o=this.evaluate(2,i,n),h=this.evaluate(1,r,n),u=a.subtract(e),l=o.dot(o)+u.dot(h);return Math.abs(l)<1e-6?n:n-u.dot(o)/l},evaluate:function(t,e,n){for(var i=e.slice(),r=1;r<=t;r++)for(var s=0;s<=t-r;s++)i[s]=i[s].multiply(1-n).add(i[s+1].multiply(n));return i[0]},chordLengthParameterize:function(t,e){for(var n=[0],i=t+1;i<=e;i++)n[i-t]=n[i-t-1]+this.points[i].getDistance(this.points[i-1]);for(var i=1,r=e-t;i<=r;i++)n[i]/=n[r];return n},findMaxError:function(t,e,n,i){for(var r=Math.floor((e-t+1)/2),s=0,a=t+1;a<e;a++){var o=this.evaluate(3,n,i[a-t]),h=o.subtract(this.points[a]),u=h.x*h.x+h.y*h.y;u>=s&&(s=u,r=a)}return{error:s,index:r}}}),j=w.extend({_class:"TextItem",_applyMatrix:!1,_canApplyMatrix:!1,_serializeFields:{content:null},_boundsOptions:{stroke:!1,handle:!1},initialize:function(t){this._content="",this._lines=[];var n=t&&r.isPlainObject(t)&&t.x===e&&t.y===e;this._initialize(n&&t,!n&&c.read(arguments))},_equals:function(t){return this._content===t._content},copyContent:function(t){this.setContent(t._content)},getContent:function(){return this._content},setContent:function(t){this._content=""+t,this._lines=this._content.split(/\r\n|\n|\r/gm),this._changed(265)},isEmpty:function(){return!this._content},getCharacterStyle:"#getStyle",setCharacterStyle:"#setStyle",getParagraphStyle:"#getStyle",setParagraphStyle:"#setStyle"}),F=j.extend({_class:"PointText",initialize:function(){j.apply(this,arguments)},getPoint:function(){var t=this._matrix.getTranslation();return new f(t.x,t.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.translate(t.subtract(this._matrix.getTranslation()))},_draw:function(t,e,n){if(this._content){this._setStyles(t,e,n);var i=this._lines,r=this._style,s=r.hasFill(),a=r.hasStroke(),o=r.getLeading(),h=t.shadowColor;t.font=r.getFontStyle(),t.textAlign=r.getJustification();for(var u=0,l=i.length;u<l;u++){t.shadowColor=h;var c=i[u];s&&(t.fillText(c,0,0),t.shadowColor="rgba(0,0,0,0)"),a&&t.strokeText(c,0,0),t.translate(0,o)}}},_getBounds:function(t,e){var n=this._style,i=this._lines,r=i.length,s=n.getJustification(),a=n.getLeading(),o=this.getView().getTextWidth(n.getFontStyle(),i),h=0;"left"!==s&&(h-=o/("center"===s?2:1));var u=new g(h,r?-.75*a:0,o,r*a);return t?t._transformBounds(u,u):u}}),D=r.extend(new function(){function t(t){var i,r=t.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/);if(r){i=[0,0,0];for(var s=0;s<3;s++){var o=r[s+1];i[s]=parseInt(1==o.length?o+o:o,16)/255}}else if(r=t.match(/^rgba?\((.*)\)$/)){i=r[1].split(",");for(var s=0,h=i.length;s<h;s++){var o=+i[s];i[s]=s<3?o/255:o}}else if(n){var u=a[t];if(!u){e||(e=tt.getContext(1,1),e.globalCompositeOperation="copy"),e.fillStyle="rgba(0,0,0,0)",e.fillStyle=t,e.fillRect(0,0,1,1);var l=e.getImageData(0,0,1,1).data;u=a[t]=[l[0]/255,l[1]/255,l[2]/255]}i=u.slice()}else i=[0,0,0];return i}var e,i={gray:["gray"],rgb:["red","green","blue"],hsb:["hue","saturation","brightness"],hsl:["hue","saturation","lightness"],gradient:["gradient","origin","destination","highlight"]},s={},a={},o=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]],u={"rgb-hsb":function(t,e,n){var i=Math.max(t,e,n),r=Math.min(t,e,n),s=i-r,a=0===s?0:60*(i==t?(e-n)/s+(e<n?6:0):i==e?(n-t)/s+2:(t-e)/s+4);return[a,0===i?0:s/i,i]},"hsb-rgb":function(t,e,n){t=(t/60%6+6)%6;var i=Math.floor(t),r=t-i,i=o[i],s=[n,n*(1-e),n*(1-e*r),n*(1-e*(1-r))];return[s[i[0]],s[i[1]],s[i[2]]]},"rgb-hsl":function(t,e,n){var i=Math.max(t,e,n),r=Math.min(t,e,n),s=i-r,a=0===s,o=a?0:60*(i==t?(e-n)/s+(e<n?6:0):i==e?(n-t)/s+2:(t-e)/s+4),h=(i+r)/2,u=a?0:h<.5?s/(i+r):s/(2-i-r);return[o,u,h]},"hsl-rgb":function(t,e,n){if(t=(t/360%1+1)%1,0===e)return[n,n,n];for(var i=[t+1/3,t,t-1/3],r=n<.5?n*(1+e):n+e-n*e,s=2*n-r,a=[],o=0;o<3;o++){var h=i[o];h<0&&(h+=1),h>1&&(h-=1),a[o]=6*h<1?s+6*(r-s)*h:2*h<1?r:3*h<2?s+(r-s)*(2/3-h)*6:s}return a},"rgb-gray":function(t,e,n){return[.2989*t+.587*e+.114*n]},"gray-rgb":function(t){return[t,t,t]},"gray-hsb":function(t){return[0,0,t]},"gray-hsl":function(t){return[0,0,t]},"gradient-rgb":function(){return[]},"rgb-gradient":function(){return[]}};return r.each(i,function(t,e){s[e]=[],r.each(t,function(t,n){var a=r.capitalize(t),o=/^(hue|saturation)$/.test(t),h=s[e][n]="gradient"===t?function(t){var e=this._components[0];return t=R.read(Array.isArray(t)?t:arguments,0,{readNull:!0}),e!==t&&(e&&e._removeOwner(this),t&&t._addOwner(this)),t}:"gradient"===e?function(){return c.read(arguments,0,{readNull:"highlight"===t,clone:!0})}:function(t){return null==t||isNaN(t)?0:t};this["get"+a]=function(){return this._type===e||o&&/^hs[bl]$/.test(this._type)?this._components[n]:this._convert(e)[n]},this["set"+a]=function(t){this._type===e||o&&/^hs[bl]$/.test(this._type)||(this._components=this._convert(e),this._properties=i[e],this._type=e),this._components[n]=h.call(this,t),this._changed()}},this)},{_class:"Color",_readIndex:!0,initialize:function l(e){var n,r,a,o,h=Array.prototype.slice,u=arguments,c=this.__read,f=0;Array.isArray(e)&&(u=e,e=u[0]);var d=null!=e&&typeof e;if("string"===d&&e in i&&(n=e,e=u[1],Array.isArray(e)?(r=e,a=u[2]):(c&&(f=1),u=h.call(u,1),d=typeof e)),!r){if(o="number"===d?u:"object"===d&&null!=e.length?e:null){n||(n=o.length>=3?"rgb":"gray");var _=i[n].length;a=o[_],c&&(f+=o===arguments?_+(null!=a?1:0):1),o.length>_&&(o=h.call(o,0,_))}else if("string"===d)n="rgb",r=t(e),4===r.length&&(a=r[3],r.length--);else if("object"===d)if(e.constructor===l){if(n=e._type,r=e._components.slice(),a=e._alpha,"gradient"===n)for(var g=1,v=r.length;g<v;g++){var p=r[g];p&&(r[g]=p.clone())}}else if(e.constructor===R)n="gradient",o=u;else{n="hue"in e?"lightness"in e?"hsl":"hsb":"gradient"in e||"stops"in e||"radial"in e?"gradient":"gray"in e?"gray":"rgb";var m=i[n],y=s[n];this._components=r=[];for(var g=0,v=m.length;g<v;g++){var w=e[m[g]];null==w&&0===g&&"gradient"===n&&"stops"in e&&(w={stops:e.stops,radial:e.radial}),w=y[g].call(this,w),null!=w&&(r[g]=w)}a=e.alpha}c&&n&&(f=1)}if(this._type=n||"rgb",!r){this._components=r=[];for(var y=s[this._type],g=0,v=y.length;g<v;g++){var w=y[g].call(this,o&&o[g]);null!=w&&(r[g]=w)}}this._components=r,this._properties=i[this._type],this._alpha=a,c&&(this.__read=f)},_set:"#initialize",_serialize:function(t,e){var n=this.getComponents();return r.serialize(/^(gray|rgb)$/.test(this._type)?n:[this._type].concat(n),t,!0,e)},_changed:function(){this._canvasStyle=null,this._owner&&this._owner._changed(65)},_convert:function(t){var e;return this._type===t?this._components.slice():(e=u[this._type+"-"+t])?e.apply(this,this._components):u["rgb-"+t].apply(this,u[this._type+"-rgb"].apply(this,this._components))},convert:function(t){return new D(t,this._convert(t),this._alpha)},getType:function(){return this._type},setType:function(t){this._components=this._convert(t),this._properties=i[t],this._type=t},getComponents:function(){var t=this._components.slice();return null!=this._alpha&&t.push(this._alpha),t},getAlpha:function(){return null!=this._alpha?this._alpha:1},setAlpha:function(t){this._alpha=null==t?null:Math.min(Math.max(t,0),1),this._changed()},hasAlpha:function(){return null!=this._alpha},equals:function(t){var e=r.isPlainValue(t,!0)?D.read(arguments):t;return e===this||e&&this._class===e._class&&this._type===e._type&&this._alpha===e._alpha&&r.equals(this._components,e._components)||!1},toString:function(){for(var t=this._properties,e=[],n="gradient"===this._type,i=h.instance,r=0,s=t.length;r<s;r++){var a=this._components[r];null!=a&&e.push(t[r]+": "+(n?a:i.number(a)))}return null!=this._alpha&&e.push("alpha: "+i.number(this._alpha)),"{ "+e.join(", ")+" }"},toCSS:function(t){function e(t){return Math.round(255*(t<0?0:t>1?1:t))}var n=this._convert("rgb"),i=t||null==this._alpha?1:this._alpha;return n=[e(n[0]),e(n[1]),e(n[2])],i<1&&n.push(i<0?0:i),t?"#"+((1<<24)+(n[0]<<16)+(n[1]<<8)+n[2]).toString(16).slice(1):(4==n.length?"rgba(":"rgb(")+n.join(",")+")"},toCanvasStyle:function(t){if(this._canvasStyle)return this._canvasStyle;if("gradient"!==this._type)return this._canvasStyle=this.toCSS();var e,n=this._components,i=n[0],r=i._stops,s=n[1],a=n[2];if(i._radial){var o=a.getDistance(s),h=n[3];if(h){var u=h.subtract(s);u.getLength()>o&&(h=s.add(u.normalize(o-.1)))}var l=h||s;e=t.createRadialGradient(l.x,l.y,0,s.x,s.y,o)}else e=t.createLinearGradient(s.x,s.y,a.x,a.y);for(var c=0,f=r.length;c<f;c++){var d=r[c];e.addColorStop(d._offset||c/(f-1),d._color.toCanvasStyle())}return this._canvasStyle=e},transform:function(t){if("gradient"===this._type){for(var e=this._components,n=1,i=e.length;n<i;n++){var r=e[n];t._transformPoint(r,r,!0)}this._changed()}},statics:{_types:i,random:function(){var t=Math.random;return new D(t(),t(),t())}}})},new function(){var t={add:function(t,e){return t+e},subtract:function(t,e){return t-e},multiply:function(t,e){return t*e},divide:function(t,e){return t/e}};return r.each(t,function(t,e){this[e]=function(e){e=D.read(arguments);for(var n=this._type,i=this._components,r=e._convert(n),s=0,a=i.length;s<a;s++)r[s]=t(i[s],r[s]);return new D(n,r,null!=this._alpha?t(this._alpha,e.getAlpha()):null)}},{})}),R=r.extend({_class:"Gradient",initialize:function(t,e){this._id=l.get(),t&&this._set(t)&&(t=e=null),this._stops||this.setStops(t||["white","black"]),null==this._radial&&this.setRadial("string"==typeof e&&"radial"===e||e||!1)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._stops,this._radial],t,!0,e)})},_changed:function(){for(var t=0,e=this._owners&&this._owners.length;t<e;t++)this._owners[t]._changed()},_addOwner:function(t){this._owners||(this._owners=[]),this._owners.push(t)},_removeOwner:function(t){var n=this._owners?this._owners.indexOf(t):-1;n!=-1&&(this._owners.splice(n,1),0===this._owners.length&&(this._owners=e))},clone:function(){for(var t=[],e=0,n=this._stops.length;e<n;e++)t[e]=this._stops[e].clone();return new R(t,this._radial)},getStops:function(){return this._stops},setStops:function(t){if(t.length<2)throw new Error("Gradient stop list needs to contain at least two stops.");var n=this._stops;if(n)for(var i=0,r=n.length;i<r;i++)n[i]._owner=e;n=this._stops=q.readAll(t,0,{clone:!0});for(var i=0,r=n.length;i<r;i++)n[i]._owner=this;this._changed()},getRadial:function(){return this._radial},setRadial:function(t){this._radial=t,this._changed()},equals:function(t){if(t===this)return!0;if(t&&this._class===t._class){var e=this._stops,n=t._stops,i=e.length;if(i===n.length){for(var r=0;r<i;r++)if(!e[r].equals(n[r]))return!1;return!0}}return!1}}),q=r.extend({_class:"GradientStop",initialize:function(t,n){var i=t,r=n;"object"==typeof t&&n===e&&(Array.isArray(t)&&"number"!=typeof t[0]?(i=t[0],r=t[1]):("color"in t||"offset"in t||"rampPoint"in t)&&(i=t.color,r=t.offset||t.rampPoint||0)),this.setColor(i),this.setOffset(r)},clone:function(){return new q(this._color.clone(),this._offset)},_serialize:function(t,e){var n=this._color,i=this._offset;return r.serialize(null==i?[n]:[n,i],t,!0,e)},_changed:function(){this._owner&&this._owner._changed(65)},getOffset:function(){return this._offset},setOffset:function(t){this._offset=t,this._changed()},getRampPoint:"#getOffset",setRampPoint:"#setOffset",getColor:function(){return this._color},setColor:function(){var t=D.read(arguments,0,{clone:!0});t&&(t._owner=this),this._color=t,this._changed()},equals:function(t){return t===this||t&&this._class===t._class&&this._color.equals(t._color)&&this._offset==t._offset||!1}}),V=r.extend(new function(){var t={fillColor:null,fillRule:"nonzero",strokeColor:null,strokeWidth:1,strokeCap:"butt",strokeJoin:"miter",strokeScaling:!0,miterLimit:10,dashOffset:0,dashArray:[],shadowColor:null,shadowBlur:0,shadowOffset:new c,selectedColor:null},n=r.set({},t,{fontFamily:"sans-serif",fontWeight:"normal",fontSize:12,leading:null,justification:"left"}),i=r.set({},n,{fillColor:new D}),s={strokeWidth:97,strokeCap:97,strokeJoin:97,strokeScaling:105,miterLimit:97,fontFamily:9,fontWeight:9,fontSize:9,font:9,leading:9,justification:9},a={beans:!0},o={_class:"Style",beans:!0,initialize:function(e,r,s){this._values={},this._owner=r,this._project=r&&r._project||s||paper.project,this._defaults=!r||r instanceof x?n:r instanceof j?i:t,e&&this.set(e)}};return r.each(n,function(t,n){var i=/Color$/.test(n),h="shadowOffset"===n,u=r.capitalize(n),l=s[n],f="set"+u,d="get"+u;o[f]=function(t){var r=this._owner,s=r&&r._children;if(s&&s.length>0&&!(r instanceof L))for(var a=0,o=s.length;a<o;a++)s[a]._style[f](t);else if(n in this._defaults){var h=this._values[n];h!==t&&(i&&(h&&h._owner!==e&&(h._owner=e),t&&t.constructor===D&&(t._owner&&(t=t.clone()),t._owner=r)),this._values[n]=t,r&&r._changed(l||65))}},o[d]=function(t){var s,a=this._owner,o=a&&a._children;if(n in this._defaults&&(!o||0===o.length||t||a instanceof L)){var s=this._values[n];if(s===e)s=this._defaults[n],s&&s.clone&&(s=s.clone());else{var u=i?D:h?c:null;!u||s&&s.constructor===u||(this._values[n]=s=u.read([s],0,{readNull:!0,clone:!0}),s&&i&&(s._owner=a))}}else if(o)for(var l=0,f=o.length;l<f;l++){var _=o[l]._style[d]();if(0===l)s=_;else if(!r.equals(s,_))return e}return s},a[d]=function(t){return this._style[d](t)},a[f]=function(t){this._style[f](t)}}),r.each({Font:"FontFamily",WindingRule:"FillRule"},function(t,e){var n="get"+e,i="set"+e;o[n]=a[n]="#get"+t,o[i]=a[i]="#set"+t}),w.inject(a),o},{set:function(t){var e=t instanceof V,n=e?t._values:t;if(n)for(var i in n)if(i in this._defaults){
+var r=n[i];this[i]=r&&e&&r.clone?r.clone():r}},equals:function(t){return t===this||t&&this._class===t._class&&r.equals(this._values,t._values)||!1},hasFill:function(){var t=this.getFillColor();return!!t&&t.alpha>0},hasStroke:function(){var t=this.getStrokeColor();return!!t&&t.alpha>0&&this.getStrokeWidth()>0},hasShadow:function(){var t=this.getShadowColor();return!!t&&t.alpha>0&&(this.getShadowBlur()>0||!this.getShadowOffset().isZero())},getView:function(){return this._project._view},getFontStyle:function(){var t=this.getFontSize();return this.getFontWeight()+" "+t+(/[a-z]/i.test(t+"")?" ":"px ")+this.getFontFamily()},getFont:"#getFontFamily",setFont:"#setFontFamily",getLeading:function xt(){var t=xt.base.call(this),e=this.getFontSize();return/pt|em|%|px/.test(e)&&(e=this.getView().getPixelSize(e)),null!=t?t:1.2*e}}),H=new function(){function t(t,e,n,i){for(var r=["","webkit","moz","Moz","ms","o"],s=e[0].toUpperCase()+e.substring(1),a=0;a<6;a++){var o=r[a],h=o?o+s:e;if(h in t){if(!n)return t[h];t[h]=i;break}}}return{getStyles:function(t){var e=t&&9!==t.nodeType?t.ownerDocument:t,n=e&&e.defaultView;return n&&n.getComputedStyle(t,"")},getBounds:function(t,e){var n,i=t.ownerDocument,r=i.body,s=i.documentElement;try{n=t.getBoundingClientRect()}catch(a){n={left:0,top:0,width:0,height:0}}var o=n.left-(s.clientLeft||r.clientLeft||0),h=n.top-(s.clientTop||r.clientTop||0);if(!e){var u=i.defaultView;o+=u.pageXOffset||s.scrollLeft||r.scrollLeft,h+=u.pageYOffset||s.scrollTop||r.scrollTop}return new g(o,h,n.width,n.height)},getViewportBounds:function(t){var e=t.ownerDocument,n=e.defaultView,i=e.documentElement;return new g(0,0,n.innerWidth||i.clientWidth,n.innerHeight||i.clientHeight)},getOffset:function(t,e){return H.getBounds(t,e).getPoint()},getSize:function(t){return H.getBounds(t,!0).getSize()},isInvisible:function(t){return H.getSize(t).equals(new d(0,0))},isInView:function(t){return!H.isInvisible(t)&&H.getViewportBounds(t).intersects(H.getBounds(t,!0))},isInserted:function(t){return i.body.contains(t)},getPrefixed:function(e,n){return e&&t(e,n)},setPrefixed:function(e,n,i){if("object"==typeof n)for(var r in n)t(e,r,!0,n[r]);else t(e,n,!0,i)}}},U={add:function(t,e){if(t)for(var n in e)for(var i=e[n],r=n.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.addEventListener(r[s],i,!1)},remove:function(t,e){if(t)for(var n in e)for(var i=e[n],r=n.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.removeEventListener(r[s],i,!1)},getPoint:function(t){var e=t.targetTouches?t.targetTouches.length?t.targetTouches[0]:t.changedTouches[0]:t;return new c(e.pageX||e.clientX+i.documentElement.scrollLeft,e.pageY||e.clientY+i.documentElement.scrollTop)},getTarget:function(t){return t.target||t.srcElement},getRelatedTarget:function(t){return t.relatedTarget||t.toElement},getOffset:function(t,e){return U.getPoint(t).subtract(H.getOffset(e||U.getTarget(t)))}};U.requestAnimationFrame=new function(){function t(){var e=s;s=[];for(var n=0,a=e.length;n<a;n++)e[n]();r=i&&s.length,r&&i(t)}var e,i=H.getPrefixed(n,"requestAnimationFrame"),r=!1,s=[];return function(n){s.push(n),i?r||(i(t),r=!0):e||(e=setInterval(t,1e3/60))}};var Z=r.extend(s,{_class:"View",initialize:function bt(t,e){function r(t){return e[t]||parseInt(e.getAttribute(t),10)}function s(){var t=H.getSize(e);return t.isNaN()||t.isZero()?new d(r("width"),r("height")):t}var o;if(n&&e){this._id=e.getAttribute("id"),null==this._id&&e.setAttribute("id",this._id="view-"+bt._id++),U.add(e,this._viewEvents);var h="none";if(H.setPrefixed(e.style,{userDrag:h,userSelect:h,touchCallout:h,contentZooming:h,tapHighlightColor:"rgba(0,0,0,0)"}),a.hasAttribute(e,"resize")){var u=this;U.add(n,this._windowEvents={resize:function(){u.setViewSize(s())}})}if(o=s(),a.hasAttribute(e,"stats")&&"undefined"!=typeof Stats){this._stats=new Stats;var l=this._stats.domElement,c=l.style,f=H.getOffset(e);c.position="absolute",c.left=f.x+"px",c.top=f.y+"px",i.body.appendChild(l)}}else o=new d(e),e=null;this._project=t,this._scope=t._scope,this._element=e,this._pixelRatio||(this._pixelRatio=n&&n.devicePixelRatio||1),this._setElementSize(o.width,o.height),this._viewSize=o,bt._views.push(this),bt._viewsById[this._id]=this,(this._matrix=new p)._owner=this,this._zoom=1,bt._focused||(bt._focused=this),this._frameItems={},this._frameItemCount=0,this._itemEvents={"native":{},virtual:{}},this._autoUpdate=!paper.agent.node,this._needsUpdate=!1},remove:function(){if(!this._project)return!1;Z._focused===this&&(Z._focused=null),Z._views.splice(Z._views.indexOf(this),1),delete Z._viewsById[this._id];var t=this._project;return t._view===this&&(t._view=null),U.remove(this._element,this._viewEvents),U.remove(n,this._windowEvents),this._element=this._project=null,this.off("frame"),this._animate=!1,this._frameItems={},!0},_events:r.each(w._itemHandlers.concat(["onResize","onKeyDown","onKeyUp"]),function(t){this[t]={}},{onFrame:{install:function(){this.play()},uninstall:function(){this.pause()}}}),_animate:!1,_time:0,_count:0,getAutoUpdate:function(){return this._autoUpdate},setAutoUpdate:function(t){this._autoUpdate=t,t&&this.requestUpdate()},update:function(){},draw:function(){this.update()},requestUpdate:function(){if(!this._requested){var t=this;U.requestAnimationFrame(function(){if(t._requested=!1,t._animate){t.requestUpdate();var e=t._element;H.getPrefixed(i,"hidden")&&"true"!==a.getAttribute(e,"keepalive")||!H.isInView(e)||t._handleFrame()}t._autoUpdate&&t.update()}),this._requested=!0}},play:function(){this._animate=!0,this.requestUpdate()},pause:function(){this._animate=!1},_handleFrame:function(){paper=this._scope;var t=Date.now()/1e3,e=this._last?t-this._last:0;this._last=t,this.emit("frame",new r({delta:e,time:this._time+=e,count:this._count++})),this._stats&&this._stats.update()},_animateItem:function(t,e){var n=this._frameItems;e?(n[t._id]={item:t,time:0,count:0},1===++this._frameItemCount&&this.on("frame",this._handleFrameItems)):(delete n[t._id],0===--this._frameItemCount&&this.off("frame",this._handleFrameItems))},_handleFrameItems:function(t){for(var e in this._frameItems){var n=this._frameItems[e];n.item.emit("frame",new r(t,{time:n.time+=t.delta,count:n.count++}))}},_changed:function(){this._project._changed(2049),this._bounds=null},getElement:function(){return this._element},getPixelRatio:function(){return this._pixelRatio},getResolution:function(){return 72*this._pixelRatio},getViewSize:function(){var t=this._viewSize;return new _(t.width,t.height,this,"setViewSize")},setViewSize:function(){var t=d.read(arguments),e=t.width,n=t.height,i=t.subtract(this._viewSize);i.isZero()||(this._setElementSize(e,n),this._viewSize.set(e,n),this.emit("resize",{size:t,delta:i}),this._changed(),this._autoUpdate&&this.requestUpdate())},_setElementSize:function(t,e){var n=this._element;n&&(n.width!==t&&(n.width=t),n.height!==e&&(n.height=e))},getBounds:function(){return this._bounds||(this._bounds=this._matrix.inverted()._transformBounds(new g(new c,this._viewSize))),this._bounds},getSize:function(){return this.getBounds().getSize()},getCenter:function(){return this.getBounds().getCenter()},setCenter:function(){var t=c.read(arguments);this.translate(this.getCenter().subtract(t))},getZoom:function(){return this._zoom},setZoom:function(t){this.transform((new p).scale(t/this._zoom,this.getCenter())),this._zoom=t},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},isVisible:function(){return H.isInView(this._element)},isInserted:function(){return H.isInserted(this._element)},getPixelSize:function(t){var e,n=this._element;if(n){var r=n.parentNode,s=i.createElement("div");s.style.fontSize=t,r.appendChild(s),e=parseFloat(H.getStyles(s).fontSize),r.removeChild(s)}else e=parseFloat(e);return e},getTextWidth:function(t,e){return 0}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var n=(e?r:c).read(arguments),i=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](n,i||this.getCenter(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t){this._matrix.append(t)},scrollBy:function(){this.translate(c.read(arguments).negate())}}),{projectToView:function(){return this._matrix._transformPoint(c.read(arguments))},viewToProject:function(){return this._matrix._inverseTransform(c.read(arguments))},getEventPoint:function(t){return this.viewToProject(U.getOffset(t,this._element))}},{statics:{_views:[],_viewsById:{},_id:0,create:function(t,e){i&&"string"==typeof e&&(e=i.getElementById(e));var r=n?W:Z;return new r(t,e)}}},new function(){function t(t){var e=U.getTarget(t);return e.getAttribute&&Z._viewsById[e.getAttribute("id")]}function e(){var t=Z._focused;if(!t||!t.isVisible())for(var e=0,n=Z._views.length;e<n;e++)if((t=Z._views[e]).isVisible()){Z._focused=h=t;break}}function r(t,e,n){t._handleMouseEvent("mousemove",e,n)}function s(t,e,n,i,r,s,a){function o(t,n){if(t.responds(n)){if(h||(h=new X(n,i,r,e||t,s?r.subtract(s):null)),t.emit(n,h)&&(I=!0,h.prevented&&(P=!0),h.stopped))return u=!0}else{var a=M[n];if(a)return o(t,a)}}for(var h,u=!1;t&&t!==a&&!o(t,n);)t=t._parent;return u}function a(t,e,n,i,r,a){return t._project.removeOn(n),P=I=!1,b&&s(b,null,n,i,r,a)||e&&e!==b&&!e.isDescendant(b)&&s(e,null,M[n]||n,i,r,a,b)||s(t,b||e||t,n,i,r,a)}if(n){var o,h,u,l,c,f=!1,d=!1,_=n.navigator;_.pointerEnabled||_.msPointerEnabled?(u="pointerdown MSPointerDown",l="pointermove MSPointerMove",c="pointerup pointercancel MSPointerUp MSPointerCancel"):(u="touchstart",l="touchmove",c="touchend touchcancel","ontouchstart"in n&&_.userAgent.match(/mobile|tablet|ip(ad|hone|od)|android|silk/i)||(u+=" mousedown",l+=" mousemove",c+=" mouseup"));var g={},v={mouseout:function(t){var e=Z._focused,n=U.getRelatedTarget(t);if(e&&(!n||"HTML"===n.nodeName)){var i=U.getOffset(t,e._element),s=i.x,a=Math.abs,o=a(s),h=1<<25,u=o-h;i.x=a(u)<o?u*(s<0?-1:1):s,r(e,t,e.viewToProject(i))}},scroll:e};g[u]=function(e){var n=Z._focused=t(e);f||(f=!0,n._handleMouseEvent("mousedown",e))},v[l]=function(n){var i=Z._focused;if(!d){var s=t(n);s?i!==s&&(i&&r(i,n),o||(o=i),i=Z._focused=h=s):h&&h===i&&(o&&!o.isInserted()&&(o=null),i=Z._focused=o,o=null,e())}i&&r(i,n)},v[u]=function(){d=!0},v[c]=function(t){var e=Z._focused;e&&f&&e._handleMouseEvent("mouseup",t),d=f=!1},U.add(i,v),U.add(n,{load:e});var p,m,y,w,x,b,C,S,k,I=!1,P=!1,M={doubleclick:"click",mousedrag:"mousemove"},A=!1,T={mousedown:{mousedown:1,mousedrag:1,click:1,doubleclick:1},mouseup:{mouseup:1,mousedrag:1,click:1,doubleclick:1},mousemove:{mousedrag:1,mousemove:1,mouseenter:1,mouseleave:1}};return{_viewEvents:g,_handleMouseEvent:function(t,e,n){function i(t){return r.virtual[t]||l.responds(t)||u&&u.responds(t)}var r=this._itemEvents,o=r["native"][t],h="mousemove"===t,u=this._scope.tool,l=this;h&&f&&i("mousedrag")&&(t="mousedrag"),n||(n=this.getEventPoint(e));var c=this.getBounds().contains(n),d=o&&c&&l._project.hitTest(n,{tolerance:0,fill:!0,stroke:!0}),_=d&&d.item||null,g=!1,v={};v[t.substr(5)]=!0,o&&_!==x&&(x&&s(x,null,"mouseleave",e,n),_&&s(_,null,"mouseenter",e,n),x=_),A^c&&(s(this,null,c?"mouseenter":"mouseleave",e,n),p=c?this:null,g=!0),!c&&!v.drag||n.equals(y)||(a(this,_,h?t:"mousemove",e,n,y),g=!0),A=c,(v.down&&c||v.up&&m)&&(a(this,_,t,e,n,m),v.down?(k=_===C&&Date.now()-S<300,w=C=_,b=!P&&_,m=n):v.up&&(P||_!==w||(S=Date.now(),a(this,_,k?"doubleclick":"click",e,n,m),k=!1),w=b=null),A=!1,g=!0),y=n,g&&u&&(I=u._handleMouseEvent(t,e,n,v)||I),(I&&!v.move||v.down&&i("mouseup"))&&e.preventDefault()},_handleKeyEvent:function(t,e,n,i){function r(r){r.responds(t)&&(paper=a,r.emit(t,s=s||new $(t,e,n,i)))}var s,a=this._scope,o=a.tool;this.isVisible()&&(r(this),o&&o.responds(t)&&r(o))},_countItemEvent:function(t,e){var n=this._itemEvents,i=n["native"],r=n.virtual;for(var s in T)i[s]=(i[s]||0)+(T[s][t]||0)*e;r[t]=(r[t]||0)+e},statics:{updateFocus:e}}}}),W=Z.extend({_class:"CanvasView",initialize:function(t,e){if(!(e instanceof n.HTMLCanvasElement)){var i=d.read(arguments,1);if(i.isZero())throw new Error("Cannot create CanvasView with the provided argument: "+[].slice.call(arguments,1));e=tt.getCanvas(i)}var r=this._context=e.getContext("2d");if(r.save(),this._pixelRatio=1,!/^off|false$/.test(a.getAttribute(e,"hidpi"))){var s=n.devicePixelRatio||1,o=H.getPrefixed(r,"backingStorePixelRatio")||1;this._pixelRatio=s/o}Z.call(this,t,e),this._needsUpdate=!0},remove:function Ct(){return this._context.restore(),Ct.base.call(this)},_setElementSize:function St(t,e){var n=this._pixelRatio;if(St.base.call(this,t*n,e*n),1!==n){var i=this._element,r=this._context;if(!a.hasAttribute(i,"resize")){var s=i.style;s.width=t+"px",s.height=e+"px"}r.restore(),r.save(),r.scale(n,n)}},getPixelSize:function kt(t){var e,n=paper.agent;if(n&&n.firefox)e=kt.base.call(this,t);else{var i=this._context,r=i.font;i.font=t+" serif",e=parseFloat(i.font),i.font=r}return e},getTextWidth:function(t,e){var n=this._context,i=n.font,r=0;n.font=t;for(var s=0,a=e.length;s<a;s++)r=Math.max(r,n.measureText(e[s]).width);return n.font=i,r},update:function(){if(!this._needsUpdate)return!1;var t=this._project,e=this._context,n=this._viewSize;return e.clearRect(0,0,n.width+1,n.height+1),t&&t.draw(e,this._matrix,this._pixelRatio),this._needsUpdate=!1,!0}}),G=r.extend({_class:"Event",initialize:function(t){this.event=t,this.type=t&&t.type},prevented:!1,stopped:!1,preventDefault:function(){this.prevented=!0,this.event.preventDefault()},stopPropagation:function(){this.stopped=!0,this.event.stopPropagation()},stop:function(){this.stopPropagation(),this.preventDefault()},getTimeStamp:function(){return this.event.timeStamp},getModifiers:function(){return J.modifiers}}),$=G.extend({_class:"KeyEvent",initialize:function(t,e,n,i){this.type=t,this.event=e,this.key=n,this.character=i},toString:function(){return"{ type: '"+this.type+"', key: '"+this.key+"', character: '"+this.character+"', modifiers: "+this.getModifiers()+" }"}}),J=new function(){function t(t){var e=t.key||t.keyIdentifier;return e=/^U\+/.test(e)?String.fromCharCode(parseInt(e.substr(2),16)):/^Arrow[A-Z]/.test(e)?e.substr(5):"Unidentified"===e?String.fromCharCode(t.keyCode):e,o[e]||(e.length>1?r.hyphenate(e):e.toLowerCase())}function e(t,n,i,a){var o,h=Z._focused;if(u[n]=t,t?l[n]=i:delete l[n],n.length>1&&(o=r.camelize(n))in c){c[o]=t;var f=paper&&paper.agent;if("meta"===o&&f&&f.mac)if(t)s={};else{for(var d in s)d in l&&e(!1,d,s[d],a);s=null}}else t&&s&&(s[n]=i);h&&h._handleKeyEvent(t?"keydown":"keyup",a,n,i)}var s,a,o={"\t":"tab"," ":"space","\b":"backspace","\x7f":"delete",Spacebar:"space",Del:"delete",Win:"meta",Esc:"escape"},h={tab:"\t",space:" ",enter:"\r"},u={},l={},c=new r({shift:!1,control:!1,alt:!1,meta:!1,capsLock:!1,space:!1}).inject({option:{get:function(){return this.alt}},command:{get:function(){var t=paper&&paper.agent;return t&&t.mac?this.meta:this.control}}});return U.add(i,{keydown:function(n){var i=t(n),r=paper&&paper.agent;i.length>1||r&&r.chrome&&(n.altKey||r.mac&&n.metaKey||!r.mac&&n.ctrlKey)?e(!0,i,h[i]||(i.length>1?"":i),n):a=i},keypress:function(n){if(a){var i=t(n),r=n.charCode,s=r>=32?String.fromCharCode(r):i.length>1?"":i;i!==a&&(i=s.toLowerCase()),e(!0,i,s,n),a=null}},keyup:function(n){var i=t(n);i in l&&e(!1,i,l[i],n)}}),U.add(n,{blur:function(t){for(var n in l)e(!1,n,l[n],t)}}),{modifiers:c,isDown:function(t){return!!u[t]}}},X=G.extend({_class:"MouseEvent",initialize:function(t,e,n,i,r){this.type=t,this.event=e,this.point=n,this.target=i,this.delta=r},toString:function(){return"{ type: '"+this.type+"', point: "+this.point+", target: "+this.target+(this.delta?", delta: "+this.delta:"")+", modifiers: "+this.getModifiers()+" }"}}),Y=G.extend({_class:"ToolEvent",_item:null,initialize:function(t,e,n){this.tool=t,this.type=e,this.event=n},_choosePoint:function(t,e){return t?t:e?e.clone():null},getPoint:function(){return this._choosePoint(this._point,this.tool._point)},setPoint:function(t){this._point=t},getLastPoint:function(){return this._choosePoint(this._lastPoint,this.tool._lastPoint)},setLastPoint:function(t){this._lastPoint=t},getDownPoint:function(){return this._choosePoint(this._downPoint,this.tool._downPoint)},setDownPoint:function(t){this._downPoint=t},getMiddlePoint:function(){return!this._middlePoint&&this.tool._lastPoint?this.tool._point.add(this.tool._lastPoint).divide(2):this._middlePoint},setMiddlePoint:function(t){this._middlePoint=t},getDelta:function(){return!this._delta&&this.tool._lastPoint?this.tool._point.subtract(this.tool._lastPoint):this._delta},setDelta:function(t){this._delta=t},getCount:function(){return this.tool[/^mouse(down|up)$/.test(this.type)?"_downCount":"_moveCount"]},setCount:function(t){this.tool[/^mouse(down|up)$/.test(this.type)?"downCount":"count"]=t},getItem:function(){if(!this._item){var t=this.tool._scope.project.hitTest(this.getPoint());if(t){for(var e=t.item,n=e._parent;/^(Group|CompoundPath)$/.test(n._class);)e=n,n=n._parent;this._item=e}}return this._item},setItem:function(t){this._item=t},toString:function(){return"{ type: "+this.type+", point: "+this.getPoint()+", count: "+this.getCount()+", modifiers: "+this.getModifiers()+" }"}}),K=o.extend({_class:"Tool",_list:"tools",_reference:"tool",_events:["onMouseDown","onMouseUp","onMouseDrag","onMouseMove","onActivate","onDeactivate","onEditOptions","onKeyDown","onKeyUp"],initialize:function(t){o.call(this),this._moveCount=-1,this._downCount=-1,this._set(t)},getMinDistance:function(){return this._minDistance},setMinDistance:function(t){this._minDistance=t,null!=t&&null!=this._maxDistance&&t>this._maxDistance&&(this._maxDistance=t)},getMaxDistance:function(){return this._maxDistance},setMaxDistance:function(t){this._maxDistance=t,null!=this._minDistance&&null!=t&&t<this._minDistance&&(this._minDistance=t)},getFixedDistance:function(){return this._minDistance==this._maxDistance?this._minDistance:null},setFixedDistance:function(t){this._minDistance=this._maxDistance=t},_handleMouseEvent:function(t,e,n,i){function r(t,e){var r=n,s=a?c._point:c._downPoint||r;if(a){if(c._moveCount&&r.equals(s))return!1;if(s&&(null!=t||null!=e)){var o=r.subtract(s),h=o.getLength();if(h<(t||0))return!1;e&&(r=s.add(o.normalize(Math.min(h,e))))}c._moveCount++}return c._point=r,c._lastPoint=s||r,i.down&&(c._moveCount=-1,c._downPoint=r,c._downCount++),!0}function s(){o&&(l=c.emit(t,new Y(c,t,e))||l)}paper=this._scope,i.drag&&!this.responds(t)&&(t="mousemove");var a=i.move||i.drag,o=this.responds(t),h=this.minDistance,u=this.maxDistance,l=!1,c=this;if(i.down)r(),s();else if(i.up)r(null,u),s();else if(o)for(;r(h,u);)s();return l}}),Q={request:function(t){var e=new n.XMLHttpRequest;return e.open((t.method||"get").toUpperCase(),t.url,r.pick(t.async,!0)),t.mimeType&&e.overrideMimeType(t.mimeType),e.onload=function(){var n=e.status;0===n||200===n?t.onLoad&&t.onLoad.call(e,e.responseText):e.onerror()},e.onerror=function(){var n=e.status,i='Could not load "'+t.url+'" (Status: '+n+")";if(!t.onError)throw new Error(i);t.onError(i,n)},e.send(null)}},tt={canvases:[],getCanvas:function(t,e){if(!n)return null;var r,s=!0;"object"==typeof t&&(e=t.height,t=t.width),this.canvases.length?r=this.canvases.pop():(r=i.createElement("canvas"),s=!1);var a=r.getContext("2d");if(!a)throw new Error("Canvas "+r+" is unable toprovide a 2D context.");return r.width===t&&r.height===e?s&&a.clearRect(0,0,t+1,e+1):(r.width=t,r.height=e),a.save(),r},getContext:function(t,e){var n=this.getCanvas(t,e);return n?n.getContext("2d"):null},release:function(t){var e=t&&t.canvas?t.canvas:t;e&&e.getContext&&(e.getContext("2d").restore(),this.canvases.push(e))}},et=new function(){function t(t,e,n){return.2989*t+.587*e+.114*n}function e(e,n,i,r){var s=r-t(e,n,i);d=e+s,_=n+s,g=i+s;var r=t(d,_,g),a=v(d,_,g),o=p(d,_,g);if(a<0){var h=r-a;d=r+(d-r)*r/h,_=r+(_-r)*r/h,g=r+(g-r)*r/h}if(o>255){var u=255-r,l=o-r;d=r+(d-r)*u/l,_=r+(_-r)*u/l,g=r+(g-r)*u/l}}function n(t,e,n){return p(t,e,n)-v(t,e,n)}function i(t,e,n,i){var r,s=[t,e,n],a=p(t,e,n),o=v(t,e,n);o=o===t?0:o===e?1:2,a=a===t?0:a===e?1:2,r=0===v(o,a)?1===p(o,a)?2:1:0,s[a]>s[o]?(s[r]=(s[r]-s[o])*i/(s[a]-s[o]),s[a]=i):s[r]=s[a]=0,s[o]=0,d=s[0],_=s[1],g=s[2]}var s,a,o,h,u,l,c,f,d,_,g,v=Math.min,p=Math.max,m=Math.abs,y={multiply:function(){d=u*s/255,_=l*a/255,g=c*o/255},screen:function(){d=u+s-u*s/255,_=l+a-l*a/255,g=c+o-c*o/255},overlay:function(){d=u<128?2*u*s/255:255-2*(255-u)*(255-s)/255,_=l<128?2*l*a/255:255-2*(255-l)*(255-a)/255,g=c<128?2*c*o/255:255-2*(255-c)*(255-o)/255},"soft-light":function(){var t=s*u/255;d=t+u*(255-(255-u)*(255-s)/255-t)/255,t=a*l/255,_=t+l*(255-(255-l)*(255-a)/255-t)/255,t=o*c/255,g=t+c*(255-(255-c)*(255-o)/255-t)/255},"hard-light":function(){d=s<128?2*s*u/255:255-2*(255-s)*(255-u)/255,_=a<128?2*a*l/255:255-2*(255-a)*(255-l)/255,g=o<128?2*o*c/255:255-2*(255-o)*(255-c)/255},"color-dodge":function(){d=0===u?0:255===s?255:v(255,255*u/(255-s)),_=0===l?0:255===a?255:v(255,255*l/(255-a)),g=0===c?0:255===o?255:v(255,255*c/(255-o))},"color-burn":function(){d=255===u?255:0===s?0:p(0,255-255*(255-u)/s),_=255===l?255:0===a?0:p(0,255-255*(255-l)/a),g=255===c?255:0===o?0:p(0,255-255*(255-c)/o)},darken:function(){d=u<s?u:s,_=l<a?l:a,g=c<o?c:o},lighten:function(){d=u>s?u:s,_=l>a?l:a,g=c>o?c:o},difference:function(){d=u-s,d<0&&(d=-d),_=l-a,_<0&&(_=-_),g=c-o,g<0&&(g=-g)},exclusion:function(){d=u+s*(255-u-u)/255,_=l+a*(255-l-l)/255,g=c+o*(255-c-c)/255},hue:function(){i(s,a,o,n(u,l,c)),e(d,_,g,t(u,l,c))},saturation:function(){i(u,l,c,n(s,a,o)),e(d,_,g,t(u,l,c))},luminosity:function(){e(u,l,c,t(s,a,o))},color:function(){e(s,a,o,t(u,l,c))},add:function(){d=v(u+s,255),_=v(l+a,255),g=v(c+o,255)},subtract:function(){d=p(u-s,0),_=p(l-a,0),g=p(c-o,0)},average:function(){d=(u+s)/2,_=(l+a)/2,g=(c+o)/2},negation:function(){d=255-m(255-s-u),_=255-m(255-a-l),g=255-m(255-o-c)}},w=this.nativeModes=r.each(["source-over","source-in","source-out","source-atop","destination-over","destination-in","destination-out","destination-atop","lighter","darker","copy","xor"],function(t){this[t]=!0},{}),x=tt.getContext(1,1);x&&(r.each(y,function(t,e){var n="darken"===e,i=!1;x.save();try{x.fillStyle=n?"#300":"#a00",x.fillRect(0,0,1,1),x.globalCompositeOperation=e,x.globalCompositeOperation===e&&(x.fillStyle=n?"#a00":"#300",x.fillRect(0,0,1,1),i=x.getImageData(0,0,1,1).data[0]!==n?170:51)}catch(r){}x.restore(),w[e]=i}),tt.release(x)),this.process=function(t,e,n,i,r){var v=e.canvas,p="normal"===t;if(p||w[t])n.save(),n.setTransform(1,0,0,1,0,0),n.globalAlpha=i,p||(n.globalCompositeOperation=t),n.drawImage(v,r.x,r.y),n.restore();else{var m=y[t];if(!m)return;for(var x=n.getImageData(r.x,r.y,v.width,v.height),b=x.data,C=e.getImageData(0,0,v.width,v.height).data,S=0,k=b.length;S<k;S+=4){s=C[S],u=b[S],a=C[S+1],l=b[S+1],o=C[S+2],c=b[S+2],h=C[S+3],f=b[S+3],m();var I=h*i/255,P=1-I;b[S]=I*d+P*u,b[S+1]=I*_+P*l,b[S+2]=I*g+P*c,b[S+3]=h*i+P*f}n.putImageData(x,r.x,r.y)}}},nt=new function(){function t(t,e,s){return n(i.createElementNS(r,t),e,s)}function e(t,e){var n=o[e],i=n?t.getAttributeNS(n,e):t.getAttribute(e);return"null"===i?null:i}function n(t,e,n){for(var i in e){var r=e[i],s=o[i];"number"==typeof r&&n&&(r=n.number(r)),s?t.setAttributeNS(s,i,r):t.setAttribute(i,r)}return t}var r="http://www.w3.org/2000/svg",s="http://www.w3.org/2000/xmlns",a="http://www.w3.org/1999/xlink",o={href:a,xlink:s,xmlns:s+"/","xmlns:xlink":s+"/"};return{svg:r,xmlns:s,xlink:a,create:t,get:e,set:n}},it=r.each({fillColor:["fill","color"],fillRule:["fill-rule","string"],strokeColor:["stroke","color"],strokeWidth:["stroke-width","number"],strokeCap:["stroke-linecap","string"],strokeJoin:["stroke-linejoin","string"],strokeScaling:["vector-effect","lookup",{"true":"none","false":"non-scaling-stroke"},function(t,e){return!e&&(t instanceof O||t instanceof C||t instanceof j)}],miterLimit:["stroke-miterlimit","number"],dashArray:["stroke-dasharray","array"],dashOffset:["stroke-dashoffset","number"],fontFamily:["font-family","string"],fontWeight:["font-weight","string"],fontSize:["font-size","number"],justification:["text-anchor","lookup",{left:"start",center:"middle",right:"end"}],opacity:["opacity","number"],blendMode:["mix-blend-mode","style"]},function(t,e){var n=r.capitalize(e),i=t[2];this[e]={type:t[1],property:e,attribute:t[0],toSVG:i,fromSVG:i&&r.each(i,function(t,e){this[t]=e},{}),exportFilter:t[3],get:"get"+n,set:"set"+n}},{});return new function(){function t(t,e,n){var i=new r,s=t.getTranslation();if(e){t=t._shiftless();var a=t._inverseTransform(s);i[n?"cx":"x"]=a.x,i[n?"cy":"y"]=a.y,s=null}if(!t.isIdentity()){var o=t.decompose();if(o){var h=[],l=o.rotation,c=o.scaling,f=o.skewing;s&&!s.isZero()&&h.push("translate("+S.point(s)+")"),l&&h.push("rotate("+S.number(l)+")"),u.isZero(c.x-1)&&u.isZero(c.y-1)||h.push("scale("+S.point(c)+")"),f&&f.x&&h.push("skewX("+S.number(f.x)+")"),f&&f.y&&h.push("skewY("+S.number(f.y)+")"),i.transform=h.join(" ")}else i.transform="matrix("+t.getValues().join(",")+")"}return i}function e(e,n){for(var i=t(e._matrix),r=e._children,s=nt.create("g",i,S),a=0,o=r.length;a<o;a++){var h=r[a],u=b(h,n);if(u)if(h.isClipMask()){var l=nt.create("clipPath");l.appendChild(u),m(h,l,"clip"),nt.set(s,{"clip-path":"url(#"+l.id+")"})}else s.appendChild(u)}return s}function i(e,n){var i=t(e._matrix,!0),r=e.getSize(),s=e.getImage();return i.x-=r.width/2,i.y-=r.height/2,i.width=r.width,i.height=r.height,i.href=n.embedImages===!1&&s&&s.src||e.toDataURL(),nt.create("image",i,S)}function s(e,n){var i=n.matchShapes;if(i){var r=e.toShape(!1);if(r)return a(r,n)}var s,o=e._segments,h=o.length,u=t(e._matrix);if(i&&h>=2&&!e.hasHandles())if(h>2){s=e._closed?"polygon":"polyline";for(var l=[],c=0;c<h;c++)l.push(S.point(o[c]._point));u.points=l.join(" ")}else{s="line";var f=o[0]._point,d=o[1]._point;u.set({x1:f.x,y1:f.y,x2:d.x,y2:d.y})}else s="path",u.d=e.getPathData(null,n.precision);return nt.create(s,u,S)}function a(e){var n=e._type,i=e._radius,r=t(e._matrix,!0,"rectangle"!==n);if("rectangle"===n){n="rect";var s=e._size,a=s.width,o=s.height;r.x-=a/2,r.y-=o/2,r.width=a,r.height=o,i.isZero()&&(i=null)}return i&&("circle"===n?r.r=i:(r.rx=i.width,r.ry=i.height)),nt.create(n,r,S)}function o(e,n){var i=t(e._matrix),r=e.getPathData(null,n.precision);return r&&(i.d=r),nt.create("path",i,S)}function c(e,n){var i=t(e._matrix,!0),r=e._definition,s=v(r,"symbol"),a=r._item,o=a.getBounds();return s||(s=nt.create("symbol",{viewBox:S.rectangle(o)}),s.appendChild(b(a,n)),m(r,s,"symbol")),i.href="#"+s.id,i.x+=o.x,i.y+=o.y,i.width=o.width,i.height=o.height,i.overflow="visible",nt.create("use",i,S)}function f(t){var e=v(t,"color");if(!e){var n,i=t.getGradient(),r=i._radial,s=t.getOrigin(),a=t.getDestination();if(r){n={cx:s.x,cy:s.y,r:s.getDistance(a)};var o=t.getHighlight();o&&(n.fx=o.x,n.fy=o.y)}else n={x1:s.x,y1:s.y,x2:a.x,y2:a.y};n.gradientUnits="userSpaceOnUse",e=nt.create((r?"radial":"linear")+"Gradient",n,S);for(var h=i._stops,u=0,l=h.length;u<l;u++){var c=h[u],f=c._color,d=f.getAlpha();n={offset:c._offset||u/(l-1)},f&&(n["stop-color"]=f.toCSS(!0)),d<1&&(n["stop-opacity"]=d),e.appendChild(nt.create("stop",n,S))}m(t,e,"color")}return"url(#"+e.id+")"}function d(e){var n=nt.create("text",t(e._matrix,!0),S);return n.textContent=e._content,n}function _(t,e,n){var i={},s=!n&&t.getParent(),a=[];return null!=t._name&&(i.id=t._name),r.each(it,function(e){var n=e.get,o=e.type,h=t[n]();if(e.exportFilter?e.exportFilter(t,h):!s||!r.equals(s[n](),h)){if("color"===o&&null!=h){var u=h.getAlpha();u<1&&(i[e.attribute+"-opacity"]=u)}"style"===o?a.push(e.attribute+": "+h):i[e.attribute]=null==h?"none":"color"===o?h.gradient?f(h,t):h.toCSS(!0):"array"===o?h.join(","):"lookup"===o?e.toSVG[h]:h}}),a.length&&(i.style=a.join(";")),1===i.opacity&&delete i.opacity,t._visible||(i.visibility="hidden"),nt.set(e,i,S)}function v(t,e){k||(k={ids:{},svgs:{}});var n=t._id||t.__id||(t.__id=l.get("svg"));return t&&k.svgs[e+"-"+n]}function m(t,e,n){k||v();var i=k.ids[n]=(k.ids[n]||0)+1;e.id=n+"-"+i,k.svgs[n+"-"+(t._id||t.__id)]=e}function x(t,e){var i=t,r=null;if(k){i="svg"===t.nodeName.toLowerCase()&&t;for(var s in k.svgs)r||(i||(i=nt.create("svg"),i.appendChild(t)),r=i.insertBefore(nt.create("defs"),i.firstChild)),r.appendChild(k.svgs[s]);k=null}return e.asString?(new n.XMLSerializer).serializeToString(i):i}function b(t,e,n){var i=I[t._class],r=i&&i(t,e);if(r){var s=e.onExport;s&&(r=s(t,r,e)||r);var a=JSON.stringify(t._data);a&&"{}"!==a&&"null"!==a&&r.setAttribute("data-paper-data",a)}return r&&_(t,r,n)}function C(t){return t||(t={}),S=new h(t.precision),t}var S,k,I={Group:e,Layer:e,Raster:i,Path:s,Shape:a,CompoundPath:o,SymbolItem:c,PointText:d};w.inject({exportSVG:function(t){return t=C(t),x(b(this,t,!0),t)}}),y.inject({exportSVG:function(e){e=C(e);var n=this._children,i=this.getView(),s=r.pick(e.bounds,"view"),a=e.matrix||"view"===s&&i._matrix,o=a&&p.read([a]),h="view"===s?new g([0,0],i.getViewSize()):"content"===s?w._getBounds(n,o,{stroke:!0}):g.read([s],0,{readNull:!0}),u={version:"1.1",xmlns:nt.svg,"xmlns:xlink":nt.xlink};h&&(u.width=h.width,u.height=h.height,(h.x||h.y)&&(u.viewBox=S.rectangle(h)));var l=nt.create("svg",u,S),c=l;o&&!o.isIdentity()&&(c=l.appendChild(nt.create("g",t(o),S)));for(var f=0,d=n.length;f<d;f++)c.appendChild(b(n[f],e,!0));return x(l,e)}})},new function(){function t(t,e,n,i,r){var s=nt.get(t,e),a=null==s?i?null:n?"":0:n?s:parseFloat(s);return/%\s*$/.test(s)?a/100*(r?1:A[/x|^width/.test(e)?"width":"height"]):a}function s(e,n,i,r,s){return n=t(e,n||"x",!1,r,s),i=t(e,i||"y",!1,r,s),!r||null!=n&&null!=i?new c(n,i):null}function a(e,n,i,r,s){return n=t(e,n||"width",!1,r,s),i=t(e,i||"height",!1,r,s),!r||null!=n&&null!=i?new d(n,i):null}function o(t,e,n){return"none"===t?null:"number"===e?parseFloat(t):"array"===e?t?t.split(/[\s,]+/g).map(parseFloat):[]:"color"===e?k(t)||t:"lookup"===e?n[t]:t}function h(t,e,n,i){var r=t.childNodes,s="clippath"===e,a="defs"===e,o=new x,h=o._project,u=h._currentStyle,l=[];if(s||a||(o=b(o,t,i),h._currentStyle=o._style.clone()),i)for(var c=t.querySelectorAll("defs"),f=0,d=c.length;f<d;f++)P(c[f],n,!1);for(var f=0,d=r.length;f<d;f++){var _,g=r[f];1!==g.nodeType||/^defs$/i.test(g.nodeName)||!(_=P(g,n,!1))||_ instanceof I||l.push(_)}return o.addChildren(l),s&&(o=b(o.reduce(),t,i)),h._currentStyle=u,(s||a)&&(o.remove(),o=null),o}function u(t,e){for(var n=t.getAttribute("points").match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),i=[],r=0,s=n.length;r<s;r+=2)i.push(new c(parseFloat(n[r]),parseFloat(n[r+1])));var a=new E(i);return"polygon"===e&&a.closePath(),a}function l(t){return O.create(t.getAttribute("d"))}function f(e,n){var i,r=(t(e,"href",!0)||"").substring(1),a="radialgradient"===n;if(r)i=T[r].getGradient(),i._radial^a&&(i=i.clone(),i._radial=a);else{for(var o=e.childNodes,h=[],u=0,l=o.length;u<l;u++){var c=o[u];1===c.nodeType&&h.push(b(new q,c))}i=new R(h,a)}var f,d,_,g="userSpaceOnUse"!==t(e,"gradientUnits",!0);a?(f=s(e,"cx","cy",!1,g),d=f.add(t(e,"r",!1,!1,g),0),_=s(e,"fx","fy",!0,g)):(f=s(e,"x1","y1",!1,g),d=s(e,"x2","y2",!1,g));var v=b(new D(i,f,d,_),e);return v._scaleToBounds=g,null}function _(t,e,n,i){if(t.transform){for(var r=(i.getAttribute(n)||"").split(/\)\s*/g),s=new p,a=0,o=r.length;a<o;a++){var h=r[a];if(!h)break;for(var u=h.split(/\(\s*/),l=u[0],c=u[1].split(/[\s,]+/g),f=0,d=c.length;f<d;f++)c[f]=parseFloat(c[f]);switch(l){case"matrix":s.append(new p(c[0],c[1],c[2],c[3],c[4],c[5]));break;case"rotate":s.rotate(c[0],c[1],c[2]);break;case"translate":s.translate(c[0],c[1]);break;case"scale":s.scale(c);break;case"skewX":s.skew(c[0],0);break;case"skewY":s.skew(0,c[0])}}t.transform(s)}}function v(t,e,n){var i="fill-opacity"===n?"getFillColor":"getStrokeColor",r=t[i]&&t[i]();r&&r.setAlpha(parseFloat(e))}function m(t,n,i){var s=t.attributes[n],a=s&&s.value;if(!a){var o=r.camelize(n);a=t.style[o],a||i.node[o]===i.parent[o]||(a=i.node[o])}return a?"none"===a?null:a:e}function b(t,n,i){var s=n.parentNode,a={node:H.getStyles(n)||{},parent:!i&&!/^defs$/i.test(s.tagName)&&H.getStyles(s)||{}};return r.each(L,function(i,r){var s=m(n,r,a);t=s!==e&&i(t,s,r,n,a)||t;
+}),t}function k(t){var e=t&&t.match(/\((?:["'#]*)([^"')]+)/),i=e&&T[e[1].replace(n.location.href.split("#")[0]+"#","")];return i&&i._scaleToBounds&&(i=i.clone(),i._scaleToBounds=!0),i}function P(t,e,n){var s,o,h,u=t.nodeName.toLowerCase(),l="#document"!==u,c=i.body;n&&l&&(A=a(t,null,null,!0)||paper.getView().getSize(),s=nt.create("svg",{style:"stroke-width: 1px; stroke-miterlimit: 10"}),o=t.parentNode,h=t.nextSibling,s.appendChild(t),c.appendChild(s));var f=paper.settings,d=f.applyMatrix,_=f.insertItems;f.applyMatrix=!1,f.insertItems=!1;var g=z[u],v=g&&g(t,u,e,n)||null;if(f.insertItems=_,f.applyMatrix=d,v){!l||v instanceof x||(v=b(v,t,n));var p=e.onImport,m=l&&t.getAttribute("data-paper-data");p&&(v=p(t,v,e)||v),e.expandShapes&&v instanceof C&&(v.remove(),v=v.toPath()),m&&(v._data=JSON.parse(m))}return s&&(c.removeChild(s),o&&(h?o.insertBefore(t,h):o.appendChild(t))),n&&(T={},v&&r.pick(e.applyMatrix,d)&&v.matrix.apply(!0,!0)),v}function M(t,r,s){function a(i){try{var a="object"==typeof i?i:(new n.DOMParser).parseFromString(i,"image/svg+xml");if(!a.nodeName)throw a=null,new Error("Unsupported SVG source: "+t);paper=h,u=P(a,r,!0),r&&r.insert===!1||s._insertItem(e,u);var l=r.onLoad;l&&l(u,i)}catch(c){o(c)}}function o(t,e){var n=r.onError;if(!n)throw new Error(t);n(t,e)}if(!t)return null;r="function"==typeof r?{onLoad:r}:r||{};var h=paper,u=null;if("string"!=typeof t||/^.*</.test(t)){if("undefined"!=typeof File&&t instanceof File){var l=new FileReader;return l.onload=function(){a(l.result)},l.onerror=function(){o(l.error)},l.readAsText(t)}a(t)}else{var c=i.getElementById(t);c?a(c):Q.request({url:t,async:!0,onLoad:a,onError:o})}return u}var A,T={},z={"#document":function(t,e,n,i){for(var r=t.childNodes,s=0,a=r.length;s<a;s++){var o=r[s];if(1===o.nodeType)return P(o,n,i)}},g:h,svg:h,clippath:h,polygon:u,polyline:u,path:l,lineargradient:f,radialgradient:f,image:function(e){var n=new S(t(e,"href",!0));return n.on("load",function(){var t=a(e);this.setSize(t);var n=this._matrix._transformPoint(s(e).add(t.divide(2)));this.translate(n)}),n},symbol:function(t,e,n,i){return new I(h(t,e,n,i),(!0))},defs:h,use:function(e){var n=(t(e,"href",!0)||"").substring(1),i=T[n],r=s(e);return i?i instanceof I?i.place(r):i.clone().translate(r):null},circle:function(e){return new C.Circle(s(e,"cx","cy"),t(e,"r"))},ellipse:function(t){return new C.Ellipse({center:s(t,"cx","cy"),radius:a(t,"rx","ry")})},rect:function(t){return new C.Rectangle(new g(s(t),a(t)),a(t,"rx","ry"))},line:function(t){return new E.Line(s(t,"x1","y1"),s(t,"x2","y2"))},text:function(t){var e=new F(s(t).add(s(t,"dx","dy")));return e.setContent(t.textContent.trim()||""),e}},L=r.set(r.each(it,function(t){this[t.attribute]=function(e,n){if(e[t.set]&&(e[t.set](o(n,t.type,t.fromSVG)),"color"===t.type)){var i=e[t.get]();if(i){if(i._scaleToBounds){var r=e.getBounds();i.transform((new p).translate(r.getPoint()).scale(r.getSize()))}e instanceof C&&i.transform((new p).translate(e.getPosition(!0).negate()))}}}},{}),{id:function(t,e){T[e]=t,t.setName&&t.setName(e)},"clip-path":function(t,e){var n=k(e);if(n){if(n=n.clone(),n.setClipMask(!0),!(t instanceof x))return new x(n,t);t.insertChild(0,n)}},gradientTransform:_,transform:_,"fill-opacity":v,"stroke-opacity":v,visibility:function(t,e){t.setVisible&&t.setVisible("visible"===e)},display:function(t,e){t.setVisible&&t.setVisible(null!==e)},"stop-color":function(t,e){t.setColor&&t.setColor(e)},"stop-opacity":function(t,e){t._color&&t._color.setAlpha(parseFloat(e))},offset:function(t,e){if(t.setOffset){var n=e.match(/(.*)%$/);t.setOffset(n?n[1]/100:parseFloat(e))}},viewBox:function(t,e,n,i,r){var s,h,u=new g(o(e,"array")),l=a(i,null,null,!0);if(t instanceof x){var c=l?l.divide(u.getSize()):1,h=(new p).scale(c).translate(u.getPoint().negate());s=t}else t instanceof I&&(l&&u.setSize(l),s=t._item);if(s){if("visible"!==m(i,"overflow",r)){var f=new C.Rectangle(u);f.setClipMask(!0),s.addChild(f)}h&&s.transform(h)}}});w.inject({importSVG:function(t,e){return M(t,e,this)}}),y.inject({importSVG:function(t,e){return this.activate(),M(t,e,this)}})},r.exports.PaperScript=function(){function t(t,e,n){var i=p[e];if(t&&t[i]){var r=t[i](n);return"!="===e?!r:r}switch(e){case"+":return t+n;case"-":return t-n;case"*":return t*n;case"/":return t/n;case"%":return t%n;case"==":return t==n;case"!=":return t!=n}}function e(t,e){var n=m[t];if(n&&e&&e[n])return e[n]();switch(t){case"+":return+e;case"-":return-e}}function s(t,e){return v.acorn.parse(t,e)}function o(t,e){function r(t){for(var e=0,n=f.length;e<n;e++){var i=f[e];if(i[0]>=t)break;t+=i[1]}return t}function a(e){return t.substring(r(e.range[0]),r(e.range[1]))}function o(e,n){return t.substring(r(e.range[1]),r(n.range[0]))}function h(e,n){for(var i=r(e.range[0]),s=r(e.range[1]),a=0,o=f.length-1;o>=0;o--)if(i>f[o][0]){a=o+1;break}f.splice(a,0,[i,n.length-s+i]),t=t.substring(0,i)+n+t.substring(s)}function u(t,e){if(t){for(var n in t)if("range"!==n&&"loc"!==n){var i=t[n];if(Array.isArray(i))for(var r=0,s=i.length;r<s;r++)u(i[r],t);else i&&"object"==typeof i&&u(i,t)}switch(t.type){case"UnaryExpression":if(t.operator in m&&"Literal"!==t.argument.type){var l=a(t.argument);h(t,'$__("'+t.operator+'", '+l+")")}break;case"BinaryExpression":if(t.operator in p&&"Literal"!==t.left.type){var c=a(t.left),f=a(t.right),d=o(t.left,t.right),_=t.operator;h(t,"__$__("+c+","+d.replace(new RegExp("\\"+_),'"'+_+'"')+", "+f+")")}break;case"UpdateExpression":case"AssignmentExpression":var g=e&&e.type;if(!("ForStatement"===g||"BinaryExpression"===g&&/^[=!<>]/.test(e.operator)||"MemberExpression"===g&&e.computed))if("UpdateExpression"===t.type){var l=a(t.argument),v="__$__("+l+', "'+t.operator[0]+'", 1)',y=l+" = "+v;t.prefix||"AssignmentExpression"!==g&&"VariableDeclarator"!==g||(a(e.left||e.id)===l&&(y=v),y=l+"; "+y),h(t,y)}else if(/^.=$/.test(t.operator)&&"Literal"!==t.left.type){var c=a(t.left),f=a(t.right);h(t,c+" = __$__("+c+', "'+t.operator[0]+'", '+f+")")}}}}function l(t){var e="",n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(t=(Math.abs(t)<<1)+(t<0?1:0);t||!e;){var i=31&t;t>>=5,t&&(i|=32),e+=n[i]}return e}if(!t)return"";e=e||{};var c,f=[],d=e.url||"",_=paper.agent,g=_.versionNumber,v=!1,y=e.sourceMaps,w=e.source||t,x=/\r\n|\n|\r/gm,b=e.offset||0;if(y&&(_.chrome&&g>=30||_.webkit&&g>=537.76||_.firefox&&g>=23||_.node)){if(_.node)b-=2;else if(n&&d&&!n.location.href.indexOf(d)){var C=i.getElementsByTagName("html")[0].innerHTML;b=C.substr(0,C.indexOf(t)+1).match(x).length+1}v=b>0&&!(_.chrome&&g>=36||_.safari&&g>=600||_.firefox&&g>=40||_.node);var S=["AA"+l(v?0:b)+"A"];S.length=(t.match(x)||[]).length+1+(v?b:0),c={version:3,file:d,names:[],mappings:S.join(";AACA"),sourceRoot:"",sources:[d],sourcesContent:[w]}}return u(s(t,{ranges:!0})),c&&(v&&(t=new Array(b+1).join("\n")+t),/^(inline|both)$/.test(y)&&(t+="\n//# sourceMappingURL=data:application/json;base64,"+n.btoa(unescape(encodeURIComponent(JSON.stringify(c))))),t+="\n//# sourceURL="+(d||"paperscript")),{url:d,source:w,code:t,map:c}}function h(n,s,a){function h(t,e){for(var i in t)!e&&/^_/.test(i)||!new RegExp("([\\b\\s\\W]|^)"+i.replace(/\$/g,"\\$")+"\\b").test(n)||(g.push(i),v.push(t[i]))}paper=s;var u,l=s.getView(),f=/\btool\.\w+|\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\b/.test(n)&&!/\bnew\s+Tool\b/.test(n)?new K:null,d=f?f._events:[],_=["onFrame","onResize"].concat(d),g=[],v=[],p="object"==typeof n?n:o(n,a);n=p.code,h({__$__:t,$__:e,paper:s,view:l,tool:f},!0),h(s),_=r.each(_,function(t){new RegExp("\\s+"+t+"\\b").test(n)&&(g.push(t),this.push(t+": "+t))},[]).join(", "),_&&(n+="\nreturn { "+_+" };");var m=paper.agent;if(i&&(m.chrome||m.firefox&&m.versionNumber<40)){var y=i.createElement("script"),w=i.head||i.getElementsByTagName("head")[0];m.firefox&&(n="\n"+n),y.appendChild(i.createTextNode("paper._execute = function("+g+") {"+n+"\n}")),w.appendChild(y),u=paper._execute,delete paper._execute,w.removeChild(y)}else u=Function(g,n);var x=u.apply(s,v)||{};return r.each(d,function(t){var e=x[t];e&&(f[t]=e)}),l&&(x.onResize&&l.setOnResize(x.onResize),l.emit("resize",{size:l.size,delta:new c}),x.onFrame&&l.setOnFrame(x.onFrame),l.requestUpdate()),p}function u(t){if(/^text\/(?:x-|)paperscript$/.test(t.type)&&"true"!==a.getAttribute(t,"ignore")){var e=a.getAttribute(t,"canvas"),n=i.getElementById(e),r=t.src||t.getAttribute("data-src"),s=a.hasAttribute(t,"async"),o="data-paper-scope";if(!n)throw new Error('Unable to find canvas with id "'+e+'"');var u=a.get(n.getAttribute(o))||(new a).setup(n);return n.setAttribute(o,u._id),r?Q.request({url:r,async:s,mimeType:"text/plain",onLoad:function(t){h(t,u,r)}}):h(t.innerHTML,u,t.baseURI),t.setAttribute("data-paper-ignore","true"),u}}function l(){r.each(i&&i.getElementsByTagName("script"),u)}function f(t){return t?u(t):l()}var _,g,v=this;!function(t,e){return"object"==typeof _&&"object"==typeof module?e(_):"function"==typeof g&&g.amd?g(["exports"],e):void e(t.acorn||(t.acorn={}))}(this,function(t){"use strict";function e(t){ct=t||{};for(var e in gt)Object.prototype.hasOwnProperty.call(ct,e)||(ct[e]=gt[e]);_t=ct.sourceFile||null}function n(t,e){var n=vt(ft,t);e+=" ("+n.line+":"+n.column+")";var i=new SyntaxError(e);throw i.pos=t,i.loc=n,i.raisedAt=pt,i}function i(t){function e(t){if(1==t.length)return n+="return str === "+JSON.stringify(t[0])+";";n+="switch(str){";for(var e=0;e<t.length;++e)n+="case "+JSON.stringify(t[e])+":";n+="return true}return false;"}t=t.split(" ");var n="",i=[];t:for(var r=0;r<t.length;++r){for(var s=0;s<i.length;++s)if(i[s][0].length==t[r].length){i[s].push(t[r]);continue t}i.push([t[r]])}if(i.length>3){i.sort(function(t,e){return e.length-t.length}),n+="switch(str.length){";for(var r=0;r<i.length;++r){var a=i[r];n+="case "+a[0].length+":",e(a)}n+="}"}else e(t);return new Function("str",n)}function r(){this.line=kt,this.column=pt-It}function s(){kt=1,pt=It=0,St=!0,u()}function a(t,e){yt=pt,ct.locations&&(xt=new r),bt=t,u(),Ct=e,St=t.beforeExpr}function o(){var t=ct.onComment&&ct.locations&&new r,e=pt,i=ft.indexOf("*/",pt+=2);if(-1===i&&n(pt-2,"Unterminated comment"),pt=i+2,ct.locations){Xe.lastIndex=e;for(var s;(s=Xe.exec(ft))&&s.index<pt;)++kt,It=s.index+s[0].length}ct.onComment&&ct.onComment(!0,ft.slice(e+2,i),e,pt,t,ct.locations&&new r)}function h(){for(var t=pt,e=ct.onComment&&ct.locations&&new r,n=ft.charCodeAt(pt+=2);dt>pt&&10!==n&&13!==n&&8232!==n&&8233!==n;)++pt,n=ft.charCodeAt(pt);ct.onComment&&ct.onComment(!1,ft.slice(t+2,pt),t,pt,e,ct.locations&&new r)}function u(){for(;dt>pt;){var t=ft.charCodeAt(pt);if(32===t)++pt;else if(13===t){++pt;var e=ft.charCodeAt(pt);10===e&&++pt,ct.locations&&(++kt,It=pt)}else if(10===t||8232===t||8233===t)++pt,ct.locations&&(++kt,It=pt);else if(t>8&&14>t)++pt;else if(47===t){var e=ft.charCodeAt(pt+1);if(42===e)o();else{if(47!==e)break;h()}}else if(160===t)++pt;else{if(!(t>=5760&&Ue.test(String.fromCharCode(t))))break;++pt}}}function l(){var t=ft.charCodeAt(pt+1);return t>=48&&57>=t?S(!0):(++pt,a(we))}function c(){var t=ft.charCodeAt(pt+1);return St?(++pt,x()):61===t?w(Se,2):w(be,1)}function f(){var t=ft.charCodeAt(pt+1);return 61===t?w(Se,2):w(Be,1)}function d(t){var e=ft.charCodeAt(pt+1);return e===t?w(124===t?Pe:Me,2):61===e?w(Se,2):w(124===t?Ae:ze,1)}function _(){var t=ft.charCodeAt(pt+1);return 61===t?w(Se,2):w(Te,1)}function g(t){var e=ft.charCodeAt(pt+1);return e===t?45==e&&62==ft.charCodeAt(pt+2)&&Je.test(ft.slice(Mt,pt))?(pt+=3,h(),u(),y()):w(ke,2):61===e?w(Se,2):w(Ne,1)}function v(t){var e=ft.charCodeAt(pt+1),n=1;return e===t?(n=62===t&&62===ft.charCodeAt(pt+2)?3:2,61===ft.charCodeAt(pt+n)?w(Se,n+1):w(Le,n)):33==e&&60==t&&45==ft.charCodeAt(pt+2)&&45==ft.charCodeAt(pt+3)?(pt+=4,h(),u(),y()):(61===e&&(n=61===ft.charCodeAt(pt+2)?3:2),w(Ee,n))}function p(t){var e=ft.charCodeAt(pt+1);return 61===e?w(Oe,61===ft.charCodeAt(pt+2)?3:2):w(61===t?Ce:Ie,1)}function m(t){switch(t){case 46:return l();case 40:return++pt,a(ge);case 41:return++pt,a(ve);case 59:return++pt,a(me);case 44:return++pt,a(pe);case 91:return++pt,a(ce);case 93:return++pt,a(fe);case 123:return++pt,a(de);case 125:return++pt,a(_e);case 58:return++pt,a(ye);case 63:return++pt,a(xe);case 48:var e=ft.charCodeAt(pt+1);if(120===e||88===e)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return S(!1);case 34:case 39:return k(t);case 47:return c(t);case 37:case 42:return f();case 124:case 38:return d(t);case 94:return _();case 43:case 45:return g(t);case 60:case 62:return v(t);case 61:case 33:return p(t);case 126:return w(Ie,1)}return!1}function y(t){if(t?pt=mt+1:mt=pt,ct.locations&&(wt=new r),t)return x();if(pt>=dt)return a(Ft);var e=ft.charCodeAt(pt);if(Ye(e)||92===e)return M();var i=m(e);if(i===!1){var s=String.fromCharCode(e);if("\\"===s||Ge.test(s))return M();n(pt,"Unexpected character '"+s+"'")}return i}function w(t,e){var n=ft.slice(pt,pt+e);pt+=e,a(t,n)}function x(){for(var t,e,i="",r=pt;;){pt>=dt&&n(r,"Unterminated regular expression");var s=ft.charAt(pt);if(Je.test(s)&&n(r,"Unterminated regular expression"),t)t=!1;else{if("["===s)e=!0;else if("]"===s&&e)e=!1;else if("/"===s&&!e)break;t="\\"===s}++pt}var i=ft.slice(r,pt);++pt;var o=P();o&&!/^[gmsiy]*$/.test(o)&&n(r,"Invalid regexp flag");try{var h=new RegExp(i,o)}catch(u){u instanceof SyntaxError&&n(r,u.message),n(u)}return a(Nt,h)}function b(t,e){for(var n=pt,i=0,r=0,s=null==e?1/0:e;s>r;++r){var a,o=ft.charCodeAt(pt);if(a=o>=97?o-97+10:o>=65?o-65+10:o>=48&&57>=o?o-48:1/0,a>=t)break;++pt,i=i*t+a}return pt===n||null!=e&&pt-n!==e?null:i}function C(){pt+=2;var t=b(16);return null==t&&n(mt+2,"Expected hexadecimal number"),Ye(ft.charCodeAt(pt))&&n(pt,"Identifier directly after number"),a(Lt,t)}function S(t){var e=pt,i=!1,r=48===ft.charCodeAt(pt);t||null!==b(10)||n(e,"Invalid number"),46===ft.charCodeAt(pt)&&(++pt,b(10),i=!0);var s=ft.charCodeAt(pt);69!==s&&101!==s||(s=ft.charCodeAt(++pt),43!==s&&45!==s||++pt,null===b(10)&&n(e,"Invalid number"),i=!0),Ye(ft.charCodeAt(pt))&&n(pt,"Identifier directly after number");var o,h=ft.slice(e,pt);return i?o=parseFloat(h):r&&1!==h.length?/[89]/.test(h)||Ot?n(e,"Invalid number"):o=parseInt(h,8):o=parseInt(h,10),a(Lt,o)}function k(t){pt++;for(var e="";;){pt>=dt&&n(mt,"Unterminated string constant");var i=ft.charCodeAt(pt);if(i===t)return++pt,a(Bt,e);if(92===i){i=ft.charCodeAt(++pt);var r=/^[0-7]+/.exec(ft.slice(pt,pt+3));for(r&&(r=r[0]);r&&parseInt(r,8)>255;)r=r.slice(0,-1);if("0"===r&&(r=null),++pt,r)Ot&&n(pt-2,"Octal literal in strict mode"),e+=String.fromCharCode(parseInt(r,8)),pt+=r.length-1;else switch(i){case 110:e+="\n";break;case 114:e+="\r";break;case 120:e+=String.fromCharCode(I(2));break;case 117:e+=String.fromCharCode(I(4));break;case 85:e+=String.fromCharCode(I(8));break;case 116:e+="\t";break;case 98:e+="\b";break;case 118:e+="\x0B";break;case 102:e+="\f";break;case 48:e+="\0";break;case 13:10===ft.charCodeAt(pt)&&++pt;case 10:ct.locations&&(It=pt,++kt);break;default:e+=String.fromCharCode(i)}}else 13!==i&&10!==i&&8232!==i&&8233!==i||n(mt,"Unterminated string constant"),e+=String.fromCharCode(i),++pt}}function I(t){var e=b(16,t);return null===e&&n(mt,"Bad character escape sequence"),e}function P(){Fe=!1;for(var t,e=!0,i=pt;;){var r=ft.charCodeAt(pt);if(Ke(r))Fe&&(t+=ft.charAt(pt)),++pt;else{if(92!==r)break;Fe||(t=ft.slice(i,pt)),Fe=!0,117!=ft.charCodeAt(++pt)&&n(pt,"Expecting Unicode escape sequence \\uXXXX"),++pt;var s=I(4),a=String.fromCharCode(s);a||n(pt-1,"Invalid Unicode escape"),(e?Ye(s):Ke(s))||n(pt-4,"Invalid Unicode escape"),t+=a}e=!1}return Fe?t:ft.slice(i,pt)}function M(){var t=P(),e=jt;return!Fe&&He(t)&&(e=le[t]),a(e,t)}function A(){Pt=mt,Mt=yt,At=xt,y()}function T(t){if(Ot=t,pt=mt,ct.locations)for(;It>pt;)It=ft.lastIndexOf("\n",It-2)+1,--kt;u(),y()}function z(){this.type=null,this.start=mt,this.end=null}function O(){this.start=wt,this.end=null,null!==_t&&(this.source=_t)}function E(){var t=new z;return ct.locations&&(t.loc=new O),ct.directSourceFile&&(t.sourceFile=ct.directSourceFile),ct.ranges&&(t.range=[mt,0]),t}function L(t){var e=new z;return e.start=t.start,ct.locations&&(e.loc=new O,e.loc.start=t.loc.start),ct.ranges&&(e.range=[t.range[0],0]),e}function N(t,e){return t.type=e,t.end=Mt,ct.locations&&(t.loc.end=At),ct.ranges&&(t.range[1]=Mt),t}function B(t){return ct.ecmaVersion>=5&&"ExpressionStatement"===t.type&&"Literal"===t.expression.type&&"use strict"===t.expression.value}function j(t){return bt===t?(A(),!0):void 0}function F(){return!ct.strictSemicolons&&(bt===Ft||bt===_e||Je.test(ft.slice(Mt,mt)))}function D(){j(me)||F()||q()}function R(t){bt===t?A():q()}function q(){n(mt,"Unexpected token")}function V(t){"Identifier"!==t.type&&"MemberExpression"!==t.type&&n(t.start,"Assigning to rvalue"),Ot&&"Identifier"===t.type&&Ve(t.name)&&n(t.start,"Assigning to "+t.name+" in strict mode")}function H(t){Pt=Mt=pt,ct.locations&&(At=new r),Tt=Ot=null,zt=[],y();var e=t||E(),n=!0;for(t||(e.body=[]);bt!==Ft;){var i=U();e.body.push(i),n&&B(i)&&T(!0),n=!1}return N(e,"Program")}function U(){(bt===be||bt===Se&&"/="==Ct)&&y(!0);var t=bt,e=E();switch(t){case Dt:case Vt:A();var i=t===Dt;j(me)||F()?e.label=null:bt!==jt?q():(e.label=lt(),D());for(var r=0;r<zt.length;++r){var s=zt[r];if(null==e.label||s.name===e.label.name){if(null!=s.kind&&(i||"loop"===s.kind))break;if(e.label&&i)break}}return r===zt.length&&n(e.start,"Unsyntactic "+t.keyword),N(e,i?"BreakStatement":"ContinueStatement");case Ht:return A(),D(),N(e,"DebuggerStatement");case Zt:return A(),zt.push(Qe),e.body=U(),zt.pop(),R(ne),e.test=Z(),D(),N(e,"DoWhileStatement");case $t:if(A(),zt.push(Qe),R(ge),bt===me)return G(e,null);if(bt===ee){var a=E();return A(),J(a,!0),N(a,"VariableDeclaration"),1===a.declarations.length&&j(ue)?$(e,a):G(e,a)}var a=X(!1,!0);return j(ue)?(V(a),$(e,a)):G(e,a);case Jt:return A(),ht(e,!0);case Xt:return A(),e.test=Z(),e.consequent=U(),e.alternate=j(Wt)?U():null,N(e,"IfStatement");case Yt:return Tt||ct.allowReturnOutsideFunction||n(mt,"'return' outside of function"),A(),j(me)||F()?e.argument=null:(e.argument=X(),D()),N(e,"ReturnStatement");case Kt:A(),e.discriminant=Z(),e.cases=[],R(de),zt.push(tn);for(var o,h;bt!=_e;)if(bt===Rt||bt===Ut){var u=bt===Rt;o&&N(o,"SwitchCase"),e.cases.push(o=E()),o.consequent=[],A(),u?o.test=X():(h&&n(Pt,"Multiple default clauses"),h=!0,o.test=null),R(ye)}else o||q(),o.consequent.push(U());return o&&N(o,"SwitchCase"),A(),zt.pop(),N(e,"SwitchStatement");case Qt:return A(),Je.test(ft.slice(Mt,mt))&&n(Mt,"Illegal newline after throw"),e.argument=X(),D(),N(e,"ThrowStatement");case te:if(A(),e.block=W(),e.handler=null,bt===qt){var l=E();A(),R(ge),l.param=lt(),Ot&&Ve(l.param.name)&&n(l.param.start,"Binding "+l.param.name+" in strict mode"),R(ve),l.guard=null,l.body=W(),e.handler=N(l,"CatchClause")}return e.guardedHandlers=Et,e.finalizer=j(Gt)?W():null,e.handler||e.finalizer||n(e.start,"Missing catch or finally clause"),N(e,"TryStatement");case ee:return A(),J(e),D(),N(e,"VariableDeclaration");case ne:return A(),e.test=Z(),zt.push(Qe),e.body=U(),zt.pop(),N(e,"WhileStatement");case ie:return Ot&&n(mt,"'with' in strict mode"),A(),e.object=Z(),e.body=U(),N(e,"WithStatement");case de:return W();case me:return A(),N(e,"EmptyStatement");default:var c=Ct,f=X();if(t===jt&&"Identifier"===f.type&&j(ye)){for(var r=0;r<zt.length;++r)zt[r].name===c&&n(f.start,"Label '"+c+"' is already declared");var d=bt.isLoop?"loop":bt===Kt?"switch":null;return zt.push({name:c,kind:d}),e.body=U(),zt.pop(),e.label=f,N(e,"LabeledStatement")}return e.expression=f,D(),N(e,"ExpressionStatement")}}function Z(){R(ge);var t=X();return R(ve),t}function W(t){var e,n=E(),i=!0,r=!1;for(n.body=[],R(de);!j(_e);){var s=U();n.body.push(s),i&&t&&B(s)&&(e=r,T(r=!0)),i=!1}return r&&!e&&T(!1),N(n,"BlockStatement")}function G(t,e){return t.init=e,R(me),t.test=bt===me?null:X(),R(me),t.update=bt===ve?null:X(),R(ve),t.body=U(),zt.pop(),N(t,"ForStatement")}function $(t,e){return t.left=e,t.right=X(),R(ve),t.body=U(),zt.pop(),N(t,"ForInStatement")}function J(t,e){for(t.declarations=[],t.kind="var";;){var i=E();if(i.id=lt(),Ot&&Ve(i.id.name)&&n(i.id.start,"Binding "+i.id.name+" in strict mode"),i.init=j(Ce)?X(!0,e):null,t.declarations.push(N(i,"VariableDeclarator")),!j(pe))break}return t}function X(t,e){var n=Y(e);if(!t&&bt===pe){var i=L(n);for(i.expressions=[n];j(pe);)i.expressions.push(Y(e));return N(i,"SequenceExpression")}return n}function Y(t){var e=K(t);if(bt.isAssign){var n=L(e);return n.operator=Ct,n.left=e,A(),n.right=Y(t),V(e),N(n,"AssignmentExpression")}return e}function K(t){var e=Q(t);if(j(xe)){var n=L(e);return n.test=e,n.consequent=X(!0),R(ye),n.alternate=X(!0,t),N(n,"ConditionalExpression")}return e}function Q(t){return tt(et(),-1,t)}function tt(t,e,n){var i=bt.binop;if(null!=i&&(!n||bt!==ue)&&i>e){var r=L(t);r.left=t,r.operator=Ct;var s=bt;A(),r.right=tt(et(),i,n);var a=N(r,s===Pe||s===Me?"LogicalExpression":"BinaryExpression");return tt(a,e,n)}return t}function et(){if(bt.prefix){var t=E(),e=bt.isUpdate;return t.operator=Ct,t.prefix=!0,St=!0,A(),t.argument=et(),e?V(t.argument):Ot&&"delete"===t.operator&&"Identifier"===t.argument.type&&n(t.start,"Deleting local variable in strict mode"),N(t,e?"UpdateExpression":"UnaryExpression")}for(var i=nt();bt.postfix&&!F();){var t=L(i);t.operator=Ct,t.prefix=!1,t.argument=i,V(i),A(),i=N(t,"UpdateExpression")}return i}function nt(){return it(rt())}function it(t,e){if(j(we)){var n=L(t);return n.object=t,n.property=lt(!0),n.computed=!1,it(N(n,"MemberExpression"),e)}if(j(ce)){var n=L(t);return n.object=t,n.property=X(),n.computed=!0,R(fe),it(N(n,"MemberExpression"),e)}if(!e&&j(ge)){var n=L(t);return n.callee=t,n.arguments=ut(ve,!1),it(N(n,"CallExpression"),e)}return t}function rt(){switch(bt){case se:var t=E();return A(),N(t,"ThisExpression");case jt:return lt();case Lt:case Bt:case Nt:var t=E();return t.value=Ct,t.raw=ft.slice(mt,yt),A(),N(t,"Literal");case ae:case oe:case he:var t=E();return t.value=bt.atomValue,t.raw=bt.keyword,A(),N(t,"Literal");case ge:var e=wt,n=mt;A();var i=X();return i.start=n,i.end=yt,ct.locations&&(i.loc.start=e,i.loc.end=xt),ct.ranges&&(i.range=[n,yt]),R(ve),i;case ce:var t=E();return A(),t.elements=ut(fe,!0,!0),N(t,"ArrayExpression");case de:return at();case Jt:var t=E();return A(),ht(t,!1);case re:return st();default:q()}}function st(){var t=E();return A(),t.callee=it(rt(),!0),j(ge)?t.arguments=ut(ve,!1):t.arguments=Et,N(t,"NewExpression")}function at(){var t=E(),e=!0,i=!1;for(t.properties=[],A();!j(_e);){if(e)e=!1;else if(R(pe),ct.allowTrailingCommas&&j(_e))break;var r,s={key:ot()},a=!1;if(j(ye)?(s.value=X(!0),r=s.kind="init"):ct.ecmaVersion>=5&&"Identifier"===s.key.type&&("get"===s.key.name||"set"===s.key.name)?(a=i=!0,r=s.kind=s.key.name,s.key=ot(),bt!==ge&&q(),s.value=ht(E(),!1)):q(),"Identifier"===s.key.type&&(Ot||i))for(var o=0;o<t.properties.length;++o){var h=t.properties[o];if(h.key.name===s.key.name){var u=r==h.kind||a&&"init"===h.kind||"init"===r&&("get"===h.kind||"set"===h.kind);u&&!Ot&&"init"===r&&"init"===h.kind&&(u=!1),u&&n(s.key.start,"Redefinition of property")}}t.properties.push(s)}return N(t,"ObjectExpression")}function ot(){return bt===Lt||bt===Bt?rt():lt(!0)}function ht(t,e){bt===jt?t.id=lt():e?q():t.id=null,t.params=[];var i=!0;for(R(ge);!j(ve);)i?i=!1:R(pe),t.params.push(lt());var r=Tt,s=zt;if(Tt=!0,zt=[],t.body=W(!0),Tt=r,zt=s,Ot||t.body.body.length&&B(t.body.body[0]))for(var a=t.id?-1:0;a<t.params.length;++a){var o=0>a?t.id:t.params[a];if((qe(o.name)||Ve(o.name))&&n(o.start,"Defining '"+o.name+"' in strict mode"),a>=0)for(var h=0;a>h;++h)o.name===t.params[h].name&&n(o.start,"Argument name clash in strict mode")}return N(t,e?"FunctionDeclaration":"FunctionExpression")}function ut(t,e,n){for(var i=[],r=!0;!j(t);){if(r)r=!1;else if(R(pe),e&&ct.allowTrailingCommas&&j(t))break;n&&bt===pe?i.push(null):i.push(X(!0))}return i}function lt(t){var e=E();return t&&"everywhere"==ct.forbidReserved&&(t=!1),bt===jt?(!t&&(ct.forbidReserved&&(3===ct.ecmaVersion?De:Re)(Ct)||Ot&&qe(Ct))&&-1==ft.slice(mt,yt).indexOf("\\")&&n(mt,"The keyword '"+Ct+"' is reserved"),e.name=Ct):t&&bt.keyword?e.name=bt.keyword:q(),St=!1,A(),N(e,"Identifier")}t.version="0.5.0";var ct,ft,dt,_t;t.parse=function(t,n){return ft=String(t),dt=ft.length,e(n),s(),H(ct.program)};var gt=t.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,allowReturnOutsideFunction:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null},vt=t.getLineInfo=function(t,e){for(var n=1,i=0;;){Xe.lastIndex=i;var r=Xe.exec(t);if(!(r&&r.index<e))break;++n,i=r.index+r[0].length}return{line:n,column:e-i}};t.tokenize=function(t,n){function i(t){return Mt=yt,y(t),r.start=mt,r.end=yt,r.startLoc=wt,r.endLoc=xt,r.type=bt,r.value=Ct,r}ft=String(t),dt=ft.length,e(n),s();var r={};return i.jumpTo=function(t,e){if(pt=t,ct.locations){kt=1,It=Xe.lastIndex=0;for(var n;(n=Xe.exec(ft))&&n.index<t;)++kt,It=n.index+n[0].length}St=e,u()},i};var pt,mt,yt,wt,xt,bt,Ct,St,kt,It,Pt,Mt,At,Tt,zt,Ot,Et=[],Lt={type:"num"},Nt={type:"regexp"},Bt={type:"string"},jt={type:"name"},Ft={type:"eof"},Dt={keyword:"break"},Rt={keyword:"case",beforeExpr:!0},qt={keyword:"catch"},Vt={keyword:"continue"},Ht={keyword:"debugger"},Ut={keyword:"default"},Zt={keyword:"do",isLoop:!0},Wt={keyword:"else",beforeExpr:!0},Gt={keyword:"finally"},$t={keyword:"for",isLoop:!0},Jt={keyword:"function"},Xt={keyword:"if"},Yt={keyword:"return",beforeExpr:!0},Kt={keyword:"switch"},Qt={keyword:"throw",beforeExpr:!0},te={keyword:"try"},ee={keyword:"var"},ne={keyword:"while",isLoop:!0},ie={keyword:"with"},re={keyword:"new",beforeExpr:!0},se={keyword:"this"},ae={keyword:"null",atomValue:null},oe={keyword:"true",atomValue:!0},he={keyword:"false",atomValue:!1},ue={keyword:"in",binop:7,beforeExpr:!0},le={"break":Dt,"case":Rt,"catch":qt,"continue":Vt,"debugger":Ht,"default":Ut,"do":Zt,"else":Wt,"finally":Gt,"for":$t,"function":Jt,"if":Xt,"return":Yt,"switch":Kt,"throw":Qt,"try":te,"var":ee,"while":ne,"with":ie,"null":ae,"true":oe,"false":he,"new":re,"in":ue,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":se,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},ce={type:"[",beforeExpr:!0},fe={type:"]"},de={type:"{",beforeExpr:!0},_e={type:"}"},ge={type:"(",beforeExpr:!0},ve={type:")"},pe={type:",",beforeExpr:!0},me={type:";",beforeExpr:!0},ye={type:":",beforeExpr:!0},we={type:"."},xe={type:"?",beforeExpr:!0},be={binop:10,beforeExpr:!0},Ce={isAssign:!0,beforeExpr:!0},Se={isAssign:!0,beforeExpr:!0},ke={postfix:!0,prefix:!0,isUpdate:!0},Ie={prefix:!0,beforeExpr:!0},Pe={binop:1,beforeExpr:!0},Me={binop:2,beforeExpr:!0},Ae={binop:3,beforeExpr:!0},Te={binop:4,beforeExpr:!0},ze={binop:5,beforeExpr:!0},Oe={binop:6,beforeExpr:!0},Ee={binop:7,beforeExpr:!0},Le={binop:8,beforeExpr:!0},Ne={binop:9,prefix:!0,beforeExpr:!0},Be={binop:10,beforeExpr:!0};t.tokTypes={bracketL:ce,bracketR:fe,braceL:de,braceR:_e,parenL:ge,parenR:ve,comma:pe,semi:me,colon:ye,dot:we,question:xe,slash:be,eq:Ce,name:jt,eof:Ft,num:Lt,regexp:Nt,string:Bt};for(var je in le)t.tokTypes["_"+je]=le[je];var Fe,De=i("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),Re=i("class enum extends super const export import"),qe=i("implements interface let package private protected public static yield"),Ve=i("eval arguments"),He=i("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Ue=/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/,Ze="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",We="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",Ge=new RegExp("["+Ze+"]"),$e=new RegExp("["+Ze+We+"]"),Je=/[\n\r\u2028\u2029]/,Xe=/\r\n|[\n\r\u2028\u2029]/g,Ye=t.isIdentifierStart=function(t){
+return 65>t?36===t:91>t||(97>t?95===t:123>t||t>=170&&Ge.test(String.fromCharCode(t)))},Ke=t.isIdentifierChar=function(t){return 48>t?36===t:58>t||!(65>t)&&(91>t||(97>t?95===t:123>t||t>=170&&$e.test(String.fromCharCode(t))))},Qe={kind:"loop"},tn={kind:"switch"}});var p={"+":"__add","-":"__subtract","*":"__multiply","/":"__divide","%":"__modulo","==":"__equals","!=":"__equals"},m={"-":"__negate","+":null},y=r.each(["add","subtract","multiply","divide","modulo","equals","negate"],function(t){this["__"+t]="#"+t},{});return c.inject(y),d.inject(y),D.inject(y),n&&("complete"===i.readyState?setTimeout(l):U.add(n,{load:l})),{compile:o,execute:h,load:f,parse:s}}.call(this),paper=new(a.inject(r.exports,{enumerable:!0,Base:r,Numerical:u,Key:J,DomEvent:U,DomElement:H,document:i,window:n,Symbol:I,PlacedSymbol:k})),paper.agent.node&&require("./node/extend")(paper),"function"==typeof define&&define.amd?define("paper",paper):"object"==typeof module&&module&&(module.exports=paper),paper}.call(this,"object"==typeof self?self:null);
\ No newline at end of file
diff --git a/package.json b/package.json
index cddcc5bc..75c2710c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "paper",
-  "version": "0.10.1",
+  "version": "0.10.2",
   "description": "The Swiss Army Knife of Vector Graphics Scripting",
   "license": "MIT",
   "homepage": "http://paperjs.org",
diff --git a/src/options.js b/src/options.js
index d0397f12..9947b2f1 100644
--- a/src/options.js
+++ b/src/options.js
@@ -17,7 +17,7 @@
 // The paper.js version.
 // NOTE: Adjust value here before calling `gulp publish`, which then updates and
 // publishes the various JSON package files automatically.
-var version = '0.10.1';
+var version = '0.10.2';
 // If this file is loaded in the browser, we're in load.js mode.
 var load = typeof window === 'object';
 

From 3a7c0f5775f9bc57dc2d3691e0a96700bd1ffc93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 21:13:43 +0200
Subject: [PATCH 44/58] Switch back to load.js versions on develop branch.

---
 dist/paper-core.js     | 14250 +-------------------------------------
 dist/paper-core.min.js |    38 -
 dist/paper-full.js     | 14624 +--------------------------------------
 dist/paper-full.min.js |    39 -
 4 files changed, 2 insertions(+), 28949 deletions(-)
 mode change 100644 => 120000 dist/paper-core.js
 delete mode 100644 dist/paper-core.min.js
 mode change 100644 => 120000 dist/paper-full.js
 delete mode 100644 dist/paper-full.min.js

diff --git a/dist/paper-core.js b/dist/paper-core.js
deleted file mode 100644
index f2d5a28f..00000000
--- a/dist/paper-core.js
+++ /dev/null
@@ -1,14249 +0,0 @@
-/*!
- * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
- * http://paperjs.org/
- *
- * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
- * http://scratchdisk.com/ & http://jonathanpuckey.com/
- *
- * Distributed under the MIT license. See LICENSE file for details.
- *
- * All rights reserved.
- *
- * Date: Sat Jul 9 20:56:58 2016 +0200
- *
- ***
- *
- * Straps.js - Class inheritance library with support for bean-style accessors
- *
- * Copyright (c) 2006 - 2016 Juerg Lehni
- * http://scratchdisk.com/
- *
- * Distributed under the MIT license.
- *
- ***
- *
- * Acorn.js
- * http://marijnhaverbeke.nl/acorn/
- *
- * Acorn is a tiny, fast JavaScript parser written in JavaScript,
- * created by Marijn Haverbeke and released under an MIT license.
- *
- */
-
-var paper = function(self, undefined) {
-
-var window = self ? self.window : require('./node/window'),
-	document = window && window.document;
-
-self = self || window;
-
-var Base = new function() {
-	var hidden = /^(statics|enumerable|beans|preserve)$/,
-
-		forEach = [].forEach || function(iter, bind) {
-			for (var i = 0, l = this.length; i < l; i++)
-				iter.call(bind, this[i], i, this);
-		},
-
-		forIn = function(iter, bind) {
-			for (var i in this)
-				if (this.hasOwnProperty(i))
-					iter.call(bind, this[i], i, this);
-		},
-
-		create = Object.create || function(proto) {
-			return { __proto__: proto };
-		},
-
-		describe = Object.getOwnPropertyDescriptor || function(obj, name) {
-			var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
-			return get
-					? { get: get, set: obj.__lookupSetter__(name),
-						enumerable: true, configurable: true }
-					: obj.hasOwnProperty(name)
-						? { value: obj[name], enumerable: true,
-							configurable: true, writable: true }
-						: null;
-		},
-
-		_define = Object.defineProperty || function(obj, name, desc) {
-			if ((desc.get || desc.set) && obj.__defineGetter__) {
-				if (desc.get)
-					obj.__defineGetter__(name, desc.get);
-				if (desc.set)
-					obj.__defineSetter__(name, desc.set);
-			} else {
-				obj[name] = desc.value;
-			}
-			return obj;
-		},
-
-		define = function(obj, name, desc) {
-			delete obj[name];
-			return _define(obj, name, desc);
-		};
-
-	function inject(dest, src, enumerable, beans, preserve) {
-		var beansNames = {};
-
-		function field(name, val) {
-			val = val || (val = describe(src, name))
-					&& (val.get ? val : val.value);
-			if (typeof val === 'string' && val[0] === '#')
-				val = dest[val.substring(1)] || val;
-			var isFunc = typeof val === 'function',
-				res = val,
-				prev = preserve || isFunc && !val.base
-						? (val && val.get ? name in dest : dest[name])
-						: null,
-				bean;
-			if (!preserve || !prev) {
-				if (isFunc && prev)
-					val.base = prev;
-				if (isFunc && beans !== false
-						&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
-					beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
-				if (!res || isFunc || !res.get || typeof res.get !== 'function'
-						|| !Base.isPlainObject(res))
-					res = { value: res, writable: true };
-				if ((describe(dest, name)
-						|| { configurable: true }).configurable) {
-					res.configurable = true;
-					res.enumerable = enumerable;
-				}
-				define(dest, name, res);
-			}
-		}
-		if (src) {
-			for (var name in src) {
-				if (src.hasOwnProperty(name) && !hidden.test(name))
-					field(name);
-			}
-			for (var name in beansNames) {
-				var part = beansNames[name],
-					set = dest['set' + part],
-					get = dest['get' + part] || set && dest['is' + part];
-				if (get && (beans === true || get.length === 0))
-					field(name, { get: get, set: set });
-			}
-		}
-		return dest;
-	}
-
-	function each(obj, iter, bind) {
-		if (obj)
-			('length' in obj && !obj.getLength
-					&& typeof obj.length === 'number'
-				? forEach
-				: forIn).call(obj, iter, bind = bind || obj);
-		return bind;
-	}
-
-	function set(obj, args, start) {
-		for (var i = start, l = args.length; i < l; i++) {
-			var props = args[i];
-			for (var key in props)
-				if (props.hasOwnProperty(key))
-					obj[key] = props[key];
-		}
-		return obj;
-	}
-
-	return inject(function Base() {
-		set(this, arguments, 0);
-	}, {
-		inject: function(src) {
-			if (src) {
-				var statics = src.statics === true ? src : src.statics,
-					beans = src.beans,
-					preserve = src.preserve;
-				if (statics !== src)
-					inject(this.prototype, src, src.enumerable, beans, preserve);
-				inject(this, statics, true, beans, preserve);
-			}
-			for (var i = 1, l = arguments.length; i < l; i++)
-				this.inject(arguments[i]);
-			return this;
-		},
-
-		extend: function() {
-			var base = this,
-				ctor,
-				proto;
-			for (var i = 0, obj, l = arguments.length;
-					i < l && !(ctor && proto); i++) {
-				obj = arguments[i];
-				ctor = ctor || obj.initialize;
-				proto = proto || obj.prototype;
-			}
-			ctor = ctor || function() {
-				base.apply(this, arguments);
-			};
-			proto = ctor.prototype = proto || create(this.prototype);
-			define(proto, 'constructor',
-					{ value: ctor, writable: true, configurable: true });
-			inject(ctor, this, true);
-			if (arguments.length)
-				this.inject.apply(ctor, arguments);
-			ctor.base = base;
-			return ctor;
-		}
-	}, true).inject({
-		inject: function() {
-			for (var i = 0, l = arguments.length; i < l; i++) {
-				var src = arguments[i];
-				if (src)
-					inject(this, src, src.enumerable, src.beans, src.preserve);
-			}
-			return this;
-		},
-
-		extend: function() {
-			var res = create(this);
-			return res.inject.apply(res, arguments);
-		},
-
-		each: function(iter, bind) {
-			return each(this, iter, bind);
-		},
-
-		set: function() {
-			return set(this, arguments, 0);
-		},
-
-		clone: function() {
-			return new this.constructor(this);
-		},
-
-		statics: {
-			each: each,
-			create: create,
-			define: define,
-			describe: describe,
-
-			set: function(obj) {
-				return set(obj, arguments, 1);
-			},
-
-			clone: function(obj) {
-				return set(new obj.constructor(), arguments, 0);
-			},
-
-			isPlainObject: function(obj) {
-				var ctor = obj != null && obj.constructor;
-				return ctor && (ctor === Object || ctor === Base
-						|| ctor.name === 'Object');
-			},
-
-			pick: function(a, b) {
-				return a !== undefined ? a : b;
-			}
-		}
-	});
-};
-
-if (typeof module !== 'undefined')
-	module.exports = Base;
-
-Base.inject({
-	toString: function() {
-		return this._id != null
-			?  (this._class || 'Object') + (this._name
-				? " '" + this._name + "'"
-				: ' @' + this._id)
-			: '{ ' + Base.each(this, function(value, key) {
-				if (!/^_/.test(key)) {
-					var type = typeof value;
-					this.push(key + ': ' + (type === 'number'
-							? Formatter.instance.number(value)
-							: type === 'string' ? "'" + value + "'" : value));
-				}
-			}, []).join(', ') + ' }';
-	},
-
-	getClassName: function() {
-		return this._class || '';
-	},
-
-	importJSON: function(json) {
-		return Base.importJSON(json, this);
-	},
-
-	exportJSON: function(options) {
-		return Base.exportJSON(this, options);
-	},
-
-	toJSON: function() {
-		return Base.serialize(this);
-	},
-
-	_set: function(props) {
-		if (props && Base.isPlainObject(props))
-			return Base.filter(this, props);
-	},
-
-	statics: {
-
-		exports: {
-			enumerable: true
-		},
-
-		extend: function extend() {
-			var res = extend.base.apply(this, arguments),
-				name = res.prototype._class;
-			if (name && !Base.exports[name])
-				Base.exports[name] = res;
-			return res;
-		},
-
-		equals: function(obj1, obj2) {
-			if (obj1 === obj2)
-				return true;
-			if (obj1 && obj1.equals)
-				return obj1.equals(obj2);
-			if (obj2 && obj2.equals)
-				return obj2.equals(obj1);
-			if (obj1 && obj2
-					&& typeof obj1 === 'object' && typeof obj2 === 'object') {
-				if (Array.isArray(obj1) && Array.isArray(obj2)) {
-					var length = obj1.length;
-					if (length !== obj2.length)
-						return false;
-					while (length--) {
-						if (!Base.equals(obj1[length], obj2[length]))
-							return false;
-					}
-				} else {
-					var keys = Object.keys(obj1),
-						length = keys.length;
-					if (length !== Object.keys(obj2).length)
-						return false;
-					while (length--) {
-						var key = keys[length];
-						if (!(obj2.hasOwnProperty(key)
-								&& Base.equals(obj1[key], obj2[key])))
-							return false;
-					}
-				}
-				return true;
-			}
-			return false;
-		},
-
-		read: function(list, start, options, length) {
-			if (this === Base) {
-				var value = this.peek(list, start);
-				list.__index++;
-				return value;
-			}
-			var proto = this.prototype,
-				readIndex = proto._readIndex,
-				index = start || readIndex && list.__index || 0;
-			if (!length)
-				length = list.length - index;
-			var obj = list[index];
-			if (obj instanceof this
-				|| options && options.readNull && obj == null && length <= 1) {
-				if (readIndex)
-					list.__index = index + 1;
-				return obj && options && options.clone ? obj.clone() : obj;
-			}
-			obj = Base.create(this.prototype);
-			if (readIndex)
-				obj.__read = true;
-			obj = obj.initialize.apply(obj, index > 0 || length < list.length
-				? Array.prototype.slice.call(list, index, index + length)
-				: list) || obj;
-			if (readIndex) {
-				list.__index = index + obj.__read;
-				obj.__read = undefined;
-			}
-			return obj;
-		},
-
-		peek: function(list, start) {
-			return list[list.__index = start || list.__index || 0];
-		},
-
-		remain: function(list) {
-			return list.length - (list.__index || 0);
-		},
-
-		readAll: function(list, start, options) {
-			var res = [],
-				entry;
-			for (var i = start || 0, l = list.length; i < l; i++) {
-				res.push(Array.isArray(entry = list[i])
-						? this.read(entry, 0, options)
-						: this.read(list, i, options, 1));
-			}
-			return res;
-		},
-
-		readNamed: function(list, name, start, options, length) {
-			var value = this.getNamed(list, name),
-				hasObject = value !== undefined;
-			if (hasObject) {
-				var filtered = list._filtered;
-				if (!filtered) {
-					filtered = list._filtered = Base.create(list[0]);
-					filtered._filtering = list[0];
-				}
-				filtered[name] = undefined;
-			}
-			return this.read(hasObject ? [value] : list, start, options, length);
-		},
-
-		getNamed: function(list, name) {
-			var arg = list[0];
-			if (list._hasObject === undefined)
-				list._hasObject = list.length === 1 && Base.isPlainObject(arg);
-			if (list._hasObject)
-				return name ? arg[name] : list._filtered || arg;
-		},
-
-		hasNamed: function(list, name) {
-			return !!this.getNamed(list, name);
-		},
-
-		filter: function(dest, source, exclude) {
-			var keys = Object.keys(source._filtering || source);
-			for (var i = 0, l = keys.length; i < l; i++) {
-				var key = keys[i];
-				if (!(exclude && exclude[key])) {
-					var value = source[key];
-					if (value !== undefined)
-						dest[key] = value;
-				}
-			}
-			return dest;
-		},
-
-		isPlainValue: function(obj, asString) {
-			return this.isPlainObject(obj) || Array.isArray(obj)
-					|| asString && typeof obj === 'string';
-		},
-
-		serialize: function(obj, options, compact, dictionary) {
-			options = options || {};
-
-			var isRoot = !dictionary,
-				res;
-			if (isRoot) {
-				options.formatter = new Formatter(options.precision);
-				dictionary = {
-					length: 0,
-					definitions: {},
-					references: {},
-					add: function(item, create) {
-						var id = '#' + item._id,
-							ref = this.references[id];
-						if (!ref) {
-							this.length++;
-							var res = create.call(item),
-								name = item._class;
-							if (name && res[0] !== name)
-								res.unshift(name);
-							this.definitions[id] = res;
-							ref = this.references[id] = [id];
-						}
-						return ref;
-					}
-				};
-			}
-			if (obj && obj._serialize) {
-				res = obj._serialize(options, dictionary);
-				var name = obj._class;
-				if (name && !obj._compactSerialize && (isRoot || !compact)
-						&& res[0] !== name) {
-					res.unshift(name);
-				}
-			} else if (Array.isArray(obj)) {
-				res = [];
-				for (var i = 0, l = obj.length; i < l; i++)
-					res[i] = Base.serialize(obj[i], options, compact,
-							dictionary);
-			} else if (Base.isPlainObject(obj)) {
-				res = {};
-				var keys = Object.keys(obj);
-				for (var i = 0, l = keys.length; i < l; i++) {
-					var key = keys[i];
-					res[key] = Base.serialize(obj[key], options, compact,
-							dictionary);
-				}
-			} else if (typeof obj === 'number') {
-				res = options.formatter.number(obj, options.precision);
-			} else {
-				res = obj;
-			}
-			return isRoot && dictionary.length > 0
-					? [['dictionary', dictionary.definitions], res]
-					: res;
-		},
-
-		deserialize: function(json, create, _data, _setDictionary, _isRoot) {
-			var res = json,
-				isFirst = !_data,
-				hasDictionary = isFirst && json && json.length
-					&& json[0][0] === 'dictionary';
-			_data = _data || {};
-			if (Array.isArray(json)) {
-				var type = json[0],
-					isDictionary = type === 'dictionary';
-				if (json.length == 1 && /^#/.test(type)) {
-					return _data.dictionary[type];
-				}
-				type = Base.exports[type];
-				res = [];
-				for (var i = type ? 1 : 0, l = json.length; i < l; i++) {
-					res.push(Base.deserialize(json[i], create, _data,
-							isDictionary, hasDictionary));
-				}
-				if (type) {
-					var args = res;
-					if (create) {
-						res = create(type, args, isFirst || _isRoot);
-					} else {
-						res = Base.create(type.prototype);
-						type.apply(res, args);
-					}
-				}
-			} else if (Base.isPlainObject(json)) {
-				res = {};
-				if (_setDictionary)
-					_data.dictionary = res;
-				for (var key in json)
-					res[key] = Base.deserialize(json[key], create, _data);
-			}
-			return hasDictionary ? res[1] : res;
-		},
-
-		exportJSON: function(obj, options) {
-			var json = Base.serialize(obj, options);
-			return options && options.asString === false
-					? json
-					: JSON.stringify(json);
-		},
-
-		importJSON: function(json, target) {
-			return Base.deserialize(
-					typeof json === 'string' ? JSON.parse(json) : json,
-					function(ctor, args, isRoot) {
-						var useTarget = isRoot && target
-								&& target.constructor === ctor,
-							obj = useTarget ? target
-								: Base.create(ctor.prototype);
-						if (args.length === 1 && obj instanceof Item
-								&& (useTarget || !(obj instanceof Layer))) {
-							var arg = args[0];
-							if (Base.isPlainObject(arg))
-								arg.insert = false;
-						}
-						(useTarget ? obj._set : ctor).apply(obj, args);
-						if (useTarget)
-							target = null;
-						return obj;
-					});
-		},
-
-		splice: function(list, items, index, remove) {
-			var amount = items && items.length,
-				append = index === undefined;
-			index = append ? list.length : index;
-			if (index > list.length)
-				index = list.length;
-			for (var i = 0; i < amount; i++)
-				items[i]._index = index + i;
-			if (append) {
-				list.push.apply(list, items);
-				return [];
-			} else {
-				var args = [index, remove];
-				if (items)
-					args.push.apply(args, items);
-				var removed = list.splice.apply(list, args);
-				for (var i = 0, l = removed.length; i < l; i++)
-					removed[i]._index = undefined;
-				for (var i = index + amount, l = list.length; i < l; i++)
-					list[i]._index = i;
-				return removed;
-			}
-		},
-
-		capitalize: function(str) {
-			return str.replace(/\b[a-z]/g, function(match) {
-				return match.toUpperCase();
-			});
-		},
-
-		camelize: function(str) {
-			return str.replace(/-(.)/g, function(all, chr) {
-				return chr.toUpperCase();
-			});
-		},
-
-		hyphenate: function(str) {
-			return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
-		}
-	}
-});
-
-var Emitter = {
-	on: function(type, func) {
-		if (typeof type !== 'string') {
-			Base.each(type, function(value, key) {
-				this.on(key, value);
-			}, this);
-		} else {
-			var types = this._eventTypes,
-				entry = types && types[type],
-				handlers = this._callbacks = this._callbacks || {};
-			handlers = handlers[type] = handlers[type] || [];
-			if (handlers.indexOf(func) === -1) {
-				handlers.push(func);
-				if (entry && entry.install && handlers.length === 1)
-					entry.install.call(this, type);
-			}
-		}
-		return this;
-	},
-
-	off: function(type, func) {
-		if (typeof type !== 'string') {
-			Base.each(type, function(value, key) {
-				this.off(key, value);
-			}, this);
-			return;
-		}
-		var types = this._eventTypes,
-			entry = types && types[type],
-			handlers = this._callbacks && this._callbacks[type],
-			index;
-		if (handlers) {
-			if (!func || (index = handlers.indexOf(func)) !== -1
-					&& handlers.length === 1) {
-				if (entry && entry.uninstall)
-					entry.uninstall.call(this, type);
-				delete this._callbacks[type];
-			} else if (index !== -1) {
-				handlers.splice(index, 1);
-			}
-		}
-		return this;
-	},
-
-	once: function(type, func) {
-		return this.on(type, function() {
-			func.apply(this, arguments);
-			this.off(type, func);
-		});
-	},
-
-	emit: function(type, event) {
-		var handlers = this._callbacks && this._callbacks[type];
-		if (!handlers)
-			return false;
-		var args = [].slice.call(arguments, 1),
-			setTarget = event && event.target && !event.currentTarget;
-		handlers = handlers.slice();
-		if (setTarget)
-			event.currentTarget = this;
-		for (var i = 0, l = handlers.length; i < l; i++) {
-			if (handlers[i].apply(this, args) === false) {
-				if (event && event.stop)
-					event.stop();
-				break;
-		   }
-		}
-		if (setTarget)
-			delete event.currentTarget;
-		return true;
-	},
-
-	responds: function(type) {
-		return !!(this._callbacks && this._callbacks[type]);
-	},
-
-	attach: '#on',
-	detach: '#off',
-	fire: '#emit',
-
-	_installEvents: function(install) {
-		var types = this._eventTypes,
-			handlers = this._callbacks,
-			key = install ? 'install' : 'uninstall';
-		if (types) {
-			for (var type in handlers) {
-				if (handlers[type].length > 0) {
-					var entry = types[type],
-						func = entry && entry[key];
-					if (func)
-						func.call(this, type);
-				}
-		}
-		}
-	},
-
-	statics: {
-		inject: function inject(src) {
-			var events = src._events;
-			if (events) {
-				var types = {};
-				Base.each(events, function(entry, key) {
-					var isString = typeof entry === 'string',
-						name = isString ? entry : key,
-						part = Base.capitalize(name),
-						type = name.substring(2).toLowerCase();
-					types[type] = isString ? {} : entry;
-					name = '_' + name;
-					src['get' + part] = function() {
-						return this[name];
-					};
-					src['set' + part] = function(func) {
-						var prev = this[name];
-						if (prev)
-							this.off(type, prev);
-						if (func)
-							this.on(type, func);
-						this[name] = func;
-					};
-				});
-				src._eventTypes = types;
-			}
-			return inject.base.apply(this, arguments);
-		}
-	}
-};
-
-var PaperScope = Base.extend({
-	_class: 'PaperScope',
-
-	initialize: function PaperScope() {
-		paper = this;
-		this.settings = new Base({
-			applyMatrix: true,
-			insertItems: true,
-			handleSize: 4,
-			hitTolerance: 0
-		});
-		this.project = null;
-		this.projects = [];
-		this.tools = [];
-		this.palettes = [];
-		this._id = PaperScope._id++;
-		PaperScope._scopes[this._id] = this;
-		var proto = PaperScope.prototype;
-		if (!this.support) {
-			var ctx = CanvasProvider.getContext(1, 1) || {};
-			proto.support = {
-				nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
-				nativeBlendModes: BlendMode.nativeModes
-			};
-			CanvasProvider.release(ctx);
-		}
-		if (!this.agent) {
-			var user = self.navigator.userAgent.toLowerCase(),
-				os = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],
-				platform = os === 'darwin' ? 'mac' : os,
-				agent = proto.agent = proto.browser = { platform: platform };
-			if (platform)
-				agent[platform] = true;
-			user.replace(
-				/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,
-				function(all, n, v1, v2, rv) {
-					if (!agent.chrome) {
-						var v = n === 'opera' ? v2 :
-								/^(node|trident)$/.test(n) ? rv : v1;
-						agent.version = v;
-						agent.versionNumber = parseFloat(v);
-						n = n === 'trident' ? 'msie' : n;
-						agent.name = n;
-						agent[n] = true;
-					}
-				}
-			);
-			if (agent.chrome)
-				delete agent.webkit;
-			if (agent.atom)
-				delete agent.chrome;
-		}
-	},
-
-	version: "0.10.2",
-
-	getView: function() {
-		var project = this.project;
-		return project && project._view;
-	},
-
-	getPaper: function() {
-		return this;
-	},
-
-	execute: function(code, options) {
-		paper.PaperScript.execute(code, this, options);
-		View.updateFocus();
-	},
-
-	install: function(scope) {
-		var that = this;
-		Base.each(['project', 'view', 'tool'], function(key) {
-			Base.define(scope, key, {
-				configurable: true,
-				get: function() {
-					return that[key];
-				}
-			});
-		});
-		for (var key in this)
-			if (!/^_/.test(key) && this[key])
-				scope[key] = this[key];
-	},
-
-	setup: function(element) {
-		paper = this;
-		this.project = new Project(element);
-		return this;
-	},
-
-	createCanvas: function(width, height) {
-		return CanvasProvider.getCanvas(width, height);
-	},
-
-	activate: function() {
-		paper = this;
-	},
-
-	clear: function() {
-		var projects = this.projects,
-			tools = this.tools,
-			palettes = this.palettes;
-		for (var i = projects.length - 1; i >= 0; i--)
-			projects[i].remove();
-		for (var i = tools.length - 1; i >= 0; i--)
-			tools[i].remove();
-		for (var i = palettes.length - 1; i >= 0; i--)
-			palettes[i].remove();
-	},
-
-	remove: function() {
-		this.clear();
-		delete PaperScope._scopes[this._id];
-	},
-
-	statics: new function() {
-		function handleAttribute(name) {
-			name += 'Attribute';
-			return function(el, attr) {
-				return el[name](attr) || el[name]('data-paper-' + attr);
-			};
-		}
-
-		return {
-			_scopes: {},
-			_id: 0,
-
-			get: function(id) {
-				return this._scopes[id] || null;
-			},
-
-			getAttribute: handleAttribute('get'),
-			hasAttribute: handleAttribute('has')
-		};
-	}
-});
-
-var PaperScopeItem = Base.extend(Emitter, {
-
-	initialize: function(activate) {
-		this._scope = paper;
-		this._index = this._scope[this._list].push(this) - 1;
-		if (activate || !this._scope[this._reference])
-			this.activate();
-	},
-
-	activate: function() {
-		if (!this._scope)
-			return false;
-		var prev = this._scope[this._reference];
-		if (prev && prev !== this)
-			prev.emit('deactivate');
-		this._scope[this._reference] = this;
-		this.emit('activate', prev);
-		return true;
-	},
-
-	isActive: function() {
-		return this._scope[this._reference] === this;
-	},
-
-	remove: function() {
-		if (this._index == null)
-			return false;
-		Base.splice(this._scope[this._list], null, this._index, 1);
-		if (this._scope[this._reference] == this)
-			this._scope[this._reference] = null;
-		this._scope = null;
-		return true;
-	},
-
-	getView: function() {
-		return this._scope.getView();
-	}
-});
-
-var Formatter = Base.extend({
-	initialize: function(precision) {
-		this.precision = Base.pick(precision, 5);
-		this.multiplier = Math.pow(10, this.precision);
-	},
-
-	number: function(val) {
-		return this.precision < 16
-				? Math.round(val * this.multiplier) / this.multiplier : val;
-	},
-
-	pair: function(val1, val2, separator) {
-		return this.number(val1) + (separator || ',') + this.number(val2);
-	},
-
-	point: function(val, separator) {
-		return this.number(val.x) + (separator || ',') + this.number(val.y);
-	},
-
-	size: function(val, separator) {
-		return this.number(val.width) + (separator || ',')
-				+ this.number(val.height);
-	},
-
-	rectangle: function(val, separator) {
-		return this.point(val, separator) + (separator || ',')
-				+ this.size(val, separator);
-	}
-});
-
-Formatter.instance = new Formatter();
-
-var Numerical = new function() {
-
-	var abscissas = [
-		[  0.5773502691896257645091488],
-		[0,0.7745966692414833770358531],
-		[  0.3399810435848562648026658,0.8611363115940525752239465],
-		[0,0.5384693101056830910363144,0.9061798459386639927976269],
-		[  0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],
-		[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],
-		[  0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],
-		[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],
-		[  0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],
-		[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],
-		[  0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],
-		[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],
-		[  0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],
-		[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],
-		[  0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]
-	];
-
-	var weights = [
-		[1],
-		[0.8888888888888888888888889,0.5555555555555555555555556],
-		[0.6521451548625461426269361,0.3478548451374538573730639],
-		[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],
-		[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],
-		[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],
-		[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],
-		[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],
-		[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],
-		[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],
-		[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],
-		[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],
-		[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],
-		[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],
-		[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]
-	];
-
-	var abs = Math.abs,
-		sqrt = Math.sqrt,
-		pow = Math.pow,
-		log2 = Math.log2 || function(x) {
-			return Math.log(x) * Math.LOG2E;
-		},
-		EPSILON = 1e-12,
-		MACHINE_EPSILON = 1.12e-16;
-
-	function clamp(value, min, max) {
-		return value < min ? min : value > max ? max : value;
-	}
-
-	function getDiscriminant(a, b, c) {
-		function split(v) {
-			var x = v * 134217729,
-				y = v - x,
-				hi = y + x,
-				lo = v - hi;
-			return [hi, lo];
-		}
-
-		var D = b * b - a * c,
-			E = b * b + a * c;
-		if (abs(D) * 3 < E) {
-			var ad = split(a),
-				bd = split(b),
-				cd = split(c),
-				p = b * b,
-				dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
-				q = a * c,
-				dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
-						+ ad[1] * cd[1];
-			D = (p - q) + (dp - dq);
-		}
-		return D;
-	}
-
-	function getNormalizationFactor() {
-		var norm = Math.max.apply(Math, arguments);
-		return norm && (norm < 1e-8 || norm > 1e8)
-				? pow(2, -Math.round(log2(norm)))
-				: 0;
-	}
-
-	return {
-		TOLERANCE: 1e-6,
-		EPSILON: EPSILON,
-		MACHINE_EPSILON: MACHINE_EPSILON,
-		CURVETIME_EPSILON: 4e-7,
-		GEOMETRIC_EPSILON: 2e-7,
-		WINDING_EPSILON: 2e-7,
-		TRIGONOMETRIC_EPSILON: 1e-7,
-		CLIPPING_EPSILON: 1e-9,
-		KAPPA: 4 * (sqrt(2) - 1) / 3,
-
-		isZero: function(val) {
-			return val >= -EPSILON && val <= EPSILON;
-		},
-
-		clamp: clamp,
-
-		integrate: function(f, a, b, n) {
-			var x = abscissas[n - 2],
-				w = weights[n - 2],
-				A = (b - a) * 0.5,
-				B = A + a,
-				i = 0,
-				m = (n + 1) >> 1,
-				sum = n & 1 ? w[i++] * f(B) : 0;
-			while (i < m) {
-				var Ax = A * x[i];
-				sum += w[i++] * (f(B + Ax) + f(B - Ax));
-			}
-			return A * sum;
-		},
-
-		findRoot: function(f, df, x, a, b, n, tolerance) {
-			for (var i = 0; i < n; i++) {
-				var fx = f(x),
-					dx = fx / df(x),
-					nx = x - dx;
-				if (abs(dx) < tolerance)
-					return nx;
-				if (fx > 0) {
-					b = x;
-					x = nx <= a ? (a + b) * 0.5 : nx;
-				} else {
-					a = x;
-					x = nx >= b ? (a + b) * 0.5 : nx;
-				}
-			}
-			return x;
-		},
-
-		solveQuadratic: function(a, b, c, roots, min, max) {
-			var x1, x2 = Infinity;
-			if (abs(a) < EPSILON) {
-				if (abs(b) < EPSILON)
-					return abs(c) < EPSILON ? -1 : 0;
-				x1 = -c / b;
-			} else {
-				b *= -0.5;
-				var D = getDiscriminant(a, b, c);
-				if (D && abs(D) < MACHINE_EPSILON) {
-					var f = getNormalizationFactor(abs(a), abs(b), abs(c));
-					if (f) {
-						a *= f;
-						b *= f;
-						c *= f;
-						D = getDiscriminant(a, b, c);
-					}
-				}
-				if (D >= -MACHINE_EPSILON) {
-					var Q = D < 0 ? 0 : sqrt(D),
-						R = b + (b < 0 ? -Q : Q);
-					if (R === 0) {
-						x1 = c / a;
-						x2 = -x1;
-					} else {
-						x1 = R / a;
-						x2 = c / R;
-					}
-				}
-			}
-			var count = 0,
-				boundless = min == null,
-				minB = min - EPSILON,
-				maxB = max + EPSILON;
-			if (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))
-				roots[count++] = boundless ? x1 : clamp(x1, min, max);
-			if (x2 !== x1
-					&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))
-				roots[count++] = boundless ? x2 : clamp(x2, min, max);
-			return count;
-		},
-
-		solveCubic: function(a, b, c, d, roots, min, max) {
-			var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),
-				x, b1, c2, qd, q;
-			if (f) {
-				a *= f;
-				b *= f;
-				c *= f;
-				d *= f;
-			}
-
-			function evaluate(x0) {
-				x = x0;
-				var tmp = a * x;
-				b1 = tmp + b;
-				c2 = b1 * x + c;
-				qd = (tmp + b1) * x + c2;
-				q = c2 * x + d;
-			}
-
-			if (abs(a) < EPSILON) {
-				a = b;
-				b1 = c;
-				c2 = d;
-				x = Infinity;
-			} else if (abs(d) < EPSILON) {
-				b1 = b;
-				c2 = c;
-				x = 0;
-			} else {
-				evaluate(-(b / a) / 3);
-				var t = q / a,
-					r = pow(abs(t), 1/3),
-					s = t < 0 ? -1 : 1,
-					td = -qd / a,
-					rd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,
-					x0 = x - s * rd;
-				if (x0 !== x) {
-					do {
-						evaluate(x0);
-						x0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);
-					} while (s * x0 > s * x);
-					if (abs(a) * x * x > abs(d / x)) {
-						c2 = -d / x;
-						b1 = (c2 - c) / x;
-					}
-				}
-			}
-			var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),
-				boundless = min == null;
-			if (isFinite(x) && (count === 0
-					|| count > 0 && x !== roots[0] && x !== roots[1])
-					&& (boundless || x > min - EPSILON && x < max + EPSILON))
-				roots[count++] = boundless ? x : clamp(x, min, max);
-			return count;
-		}
-	};
-};
-
-var UID = {
-	_id: 1,
-	_pools: {},
-
-	get: function(name) {
-		if (name) {
-			var pool = this._pools[name];
-			if (!pool)
-				pool = this._pools[name] = { _id: 1 };
-			return pool._id++;
-		} else {
-			return this._id++;
-		}
-	}
-};
-
-var Point = Base.extend({
-	_class: 'Point',
-	_readIndex: true,
-
-	initialize: function Point(arg0, arg1) {
-		var type = typeof arg0;
-		if (type === 'number') {
-			var hasY = typeof arg1 === 'number';
-			this.x = arg0;
-			this.y = hasY ? arg1 : arg0;
-			if (this.__read)
-				this.__read = hasY ? 2 : 1;
-		} else if (type === 'undefined' || arg0 === null) {
-			this.x = this.y = 0;
-			if (this.__read)
-				this.__read = arg0 === null ? 1 : 0;
-		} else {
-			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
-			if (Array.isArray(obj)) {
-				this.x = obj[0];
-				this.y = obj.length > 1 ? obj[1] : obj[0];
-			} else if ('x' in obj) {
-				this.x = obj.x;
-				this.y = obj.y;
-			} else if ('width' in obj) {
-				this.x = obj.width;
-				this.y = obj.height;
-			} else if ('angle' in obj) {
-				this.x = obj.length;
-				this.y = 0;
-				this.setAngle(obj.angle);
-			} else {
-				this.x = this.y = 0;
-				if (this.__read)
-					this.__read = 0;
-			}
-			if (this.__read)
-				this.__read = 1;
-		}
-	},
-
-	set: function(x, y) {
-		this.x = x;
-		this.y = y;
-		return this;
-	},
-
-	equals: function(point) {
-		return this === point || point
-				&& (this.x === point.x && this.y === point.y
-					|| Array.isArray(point)
-						&& this.x === point[0] && this.y === point[1])
-				|| false;
-	},
-
-	clone: function() {
-		return new Point(this.x, this.y);
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';
-	},
-
-	_serialize: function(options) {
-		var f = options.formatter;
-		return [f.number(this.x), f.number(this.y)];
-	},
-
-	getLength: function() {
-		return Math.sqrt(this.x * this.x + this.y * this.y);
-	},
-
-	setLength: function(length) {
-		if (this.isZero()) {
-			var angle = this._angle || 0;
-			this.set(
-				Math.cos(angle) * length,
-				Math.sin(angle) * length
-			);
-		} else {
-			var scale = length / this.getLength();
-			if (Numerical.isZero(scale))
-				this.getAngle();
-			this.set(
-				this.x * scale,
-				this.y * scale
-			);
-		}
-	},
-	getAngle: function() {
-		return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;
-	},
-
-	setAngle: function(angle) {
-		this.setAngleInRadians.call(this, angle * Math.PI / 180);
-	},
-
-	getAngleInDegrees: '#getAngle',
-	setAngleInDegrees: '#setAngle',
-
-	getAngleInRadians: function() {
-		if (!arguments.length) {
-			return this.isZero()
-					? this._angle || 0
-					: this._angle = Math.atan2(this.y, this.x);
-		} else {
-			var point = Point.read(arguments),
-				div = this.getLength() * point.getLength();
-			if (Numerical.isZero(div)) {
-				return NaN;
-			} else {
-				var a = this.dot(point) / div;
-				return Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);
-			}
-		}
-	},
-
-	setAngleInRadians: function(angle) {
-		this._angle = angle;
-		if (!this.isZero()) {
-			var length = this.getLength();
-			this.set(
-				Math.cos(angle) * length,
-				Math.sin(angle) * length
-			);
-		}
-	},
-
-	getQuadrant: function() {
-		return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
-	}
-}, {
-	beans: false,
-
-	getDirectedAngle: function() {
-		var point = Point.read(arguments);
-		return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;
-	},
-
-	getDistance: function() {
-		var point = Point.read(arguments),
-			x = point.x - this.x,
-			y = point.y - this.y,
-			d = x * x + y * y,
-			squared = Base.read(arguments);
-		return squared ? d : Math.sqrt(d);
-	},
-
-	normalize: function(length) {
-		if (length === undefined)
-			length = 1;
-		var current = this.getLength(),
-			scale = current !== 0 ? length / current : 0,
-			point = new Point(this.x * scale, this.y * scale);
-		if (scale >= 0)
-			point._angle = this._angle;
-		return point;
-	},
-
-	rotate: function(angle, center) {
-		if (angle === 0)
-			return this.clone();
-		angle = angle * Math.PI / 180;
-		var point = center ? this.subtract(center) : this,
-			sin = Math.sin(angle),
-			cos = Math.cos(angle);
-		point = new Point(
-			point.x * cos - point.y * sin,
-			point.x * sin + point.y * cos
-		);
-		return center ? point.add(center) : point;
-	},
-
-	transform: function(matrix) {
-		return matrix ? matrix._transformPoint(this) : this;
-	},
-
-	add: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x + point.x, this.y + point.y);
-	},
-
-	subtract: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x - point.x, this.y - point.y);
-	},
-
-	multiply: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x * point.x, this.y * point.y);
-	},
-
-	divide: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x / point.x, this.y / point.y);
-	},
-
-	modulo: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x % point.x, this.y % point.y);
-	},
-
-	negate: function() {
-		return new Point(-this.x, -this.y);
-	},
-
-	isInside: function() {
-		return Rectangle.read(arguments).contains(this);
-	},
-
-	isClose: function() {
-		var point = Point.read(arguments),
-			tolerance = Base.read(arguments);
-		return this.getDistance(point) <= tolerance;
-	},
-
-	isCollinear: function() {
-		var point = Point.read(arguments);
-		return Point.isCollinear(this.x, this.y, point.x, point.y);
-	},
-
-	isColinear: '#isCollinear',
-
-	isOrthogonal: function() {
-		var point = Point.read(arguments);
-		return Point.isOrthogonal(this.x, this.y, point.x, point.y);
-	},
-
-	isZero: function() {
-		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
-	},
-
-	isNaN: function() {
-		return isNaN(this.x) || isNaN(this.y);
-	},
-
-	dot: function() {
-		var point = Point.read(arguments);
-		return this.x * point.x + this.y * point.y;
-	},
-
-	cross: function() {
-		var point = Point.read(arguments);
-		return this.x * point.y - this.y * point.x;
-	},
-
-	project: function() {
-		var point = Point.read(arguments),
-			scale = point.isZero() ? 0 : this.dot(point) / point.dot(point);
-		return new Point(
-			point.x * scale,
-			point.y * scale
-		);
-	},
-
-	statics: {
-		min: function() {
-			var point1 = Point.read(arguments),
-				point2 = Point.read(arguments);
-			return new Point(
-				Math.min(point1.x, point2.x),
-				Math.min(point1.y, point2.y)
-			);
-		},
-
-		max: function() {
-			var point1 = Point.read(arguments),
-				point2 = Point.read(arguments);
-			return new Point(
-				Math.max(point1.x, point2.x),
-				Math.max(point1.y, point2.y)
-			);
-		},
-
-		random: function() {
-			return new Point(Math.random(), Math.random());
-		},
-
-		isCollinear: function(x1, y1, x2, y2) {
-			return Math.abs(x1 * y2 - y1 * x2)
-					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
-						* 1e-7;
-		},
-
-		isOrthogonal: function(x1, y1, x2, y2) {
-			return Math.abs(x1 * x2 + y1 * y2)
-					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
-						* 1e-7;
-		}
-	}
-}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
-	var op = Math[key];
-	this[key] = function() {
-		return new Point(op(this.x), op(this.y));
-	};
-}, {}));
-
-var LinkedPoint = Point.extend({
-	initialize: function Point(x, y, owner, setter) {
-		this._x = x;
-		this._y = y;
-		this._owner = owner;
-		this._setter = setter;
-	},
-
-	set: function(x, y, _dontNotify) {
-		this._x = x;
-		this._y = y;
-		if (!_dontNotify)
-			this._owner[this._setter](this);
-		return this;
-	},
-
-	getX: function() {
-		return this._x;
-	},
-
-	setX: function(x) {
-		this._x = x;
-		this._owner[this._setter](this);
-	},
-
-	getY: function() {
-		return this._y;
-	},
-
-	setY: function(y) {
-		this._y = y;
-		this._owner[this._setter](this);
-	},
-
-	isSelected: function() {
-		return !!(this._owner._selection & this._getSelection());
-	},
-
-	setSelected: function(selected) {
-		this._owner.changeSelection(this._getSelection(), selected);
-	},
-
-	_getSelection: function() {
-		return this._setter === 'setPosition' ? 4 : 0;
-	}
-});
-
-var Size = Base.extend({
-	_class: 'Size',
-	_readIndex: true,
-
-	initialize: function Size(arg0, arg1) {
-		var type = typeof arg0;
-		if (type === 'number') {
-			var hasHeight = typeof arg1 === 'number';
-			this.width = arg0;
-			this.height = hasHeight ? arg1 : arg0;
-			if (this.__read)
-				this.__read = hasHeight ? 2 : 1;
-		} else if (type === 'undefined' || arg0 === null) {
-			this.width = this.height = 0;
-			if (this.__read)
-				this.__read = arg0 === null ? 1 : 0;
-		} else {
-			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
-			if (Array.isArray(obj)) {
-				this.width = obj[0];
-				this.height = obj.length > 1 ? obj[1] : obj[0];
-			} else if ('width' in obj) {
-				this.width = obj.width;
-				this.height = obj.height;
-			} else if ('x' in obj) {
-				this.width = obj.x;
-				this.height = obj.y;
-			} else {
-				this.width = this.height = 0;
-				if (this.__read)
-					this.__read = 0;
-			}
-			if (this.__read)
-				this.__read = 1;
-		}
-	},
-
-	set: function(width, height) {
-		this.width = width;
-		this.height = height;
-		return this;
-	},
-
-	equals: function(size) {
-		return size === this || size && (this.width === size.width
-				&& this.height === size.height
-				|| Array.isArray(size) && this.width === size[0]
-					&& this.height === size[1]) || false;
-	},
-
-	clone: function() {
-		return new Size(this.width, this.height);
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '{ width: ' + f.number(this.width)
-				+ ', height: ' + f.number(this.height) + ' }';
-	},
-
-	_serialize: function(options) {
-		var f = options.formatter;
-		return [f.number(this.width),
-				f.number(this.height)];
-	},
-
-	add: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width + size.width, this.height + size.height);
-	},
-
-	subtract: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width - size.width, this.height - size.height);
-	},
-
-	multiply: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width * size.width, this.height * size.height);
-	},
-
-	divide: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width / size.width, this.height / size.height);
-	},
-
-	modulo: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width % size.width, this.height % size.height);
-	},
-
-	negate: function() {
-		return new Size(-this.width, -this.height);
-	},
-
-	isZero: function() {
-		return Numerical.isZero(this.width) && Numerical.isZero(this.height);
-	},
-
-	isNaN: function() {
-		return isNaN(this.width) || isNaN(this.height);
-	},
-
-	statics: {
-		min: function(size1, size2) {
-			return new Size(
-				Math.min(size1.width, size2.width),
-				Math.min(size1.height, size2.height));
-		},
-
-		max: function(size1, size2) {
-			return new Size(
-				Math.max(size1.width, size2.width),
-				Math.max(size1.height, size2.height));
-		},
-
-		random: function() {
-			return new Size(Math.random(), Math.random());
-		}
-	}
-}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
-	var op = Math[key];
-	this[key] = function() {
-		return new Size(op(this.width), op(this.height));
-	};
-}, {}));
-
-var LinkedSize = Size.extend({
-	initialize: function Size(width, height, owner, setter) {
-		this._width = width;
-		this._height = height;
-		this._owner = owner;
-		this._setter = setter;
-	},
-
-	set: function(width, height, _dontNotify) {
-		this._width = width;
-		this._height = height;
-		if (!_dontNotify)
-			this._owner[this._setter](this);
-		return this;
-	},
-
-	getWidth: function() {
-		return this._width;
-	},
-
-	setWidth: function(width) {
-		this._width = width;
-		this._owner[this._setter](this);
-	},
-
-	getHeight: function() {
-		return this._height;
-	},
-
-	setHeight: function(height) {
-		this._height = height;
-		this._owner[this._setter](this);
-	}
-});
-
-var Rectangle = Base.extend({
-	_class: 'Rectangle',
-	_readIndex: true,
-	beans: true,
-
-	initialize: function Rectangle(arg0, arg1, arg2, arg3) {
-		var type = typeof arg0,
-			read = 0;
-		if (type === 'number') {
-			this.x = arg0;
-			this.y = arg1;
-			this.width = arg2;
-			this.height = arg3;
-			read = 4;
-		} else if (type === 'undefined' || arg0 === null) {
-			this.x = this.y = this.width = this.height = 0;
-			read = arg0 === null ? 1 : 0;
-		} else if (arguments.length === 1) {
-			if (Array.isArray(arg0)) {
-				this.x = arg0[0];
-				this.y = arg0[1];
-				this.width = arg0[2];
-				this.height = arg0[3];
-				read = 1;
-			} else if (arg0.x !== undefined || arg0.width !== undefined) {
-				this.x = arg0.x || 0;
-				this.y = arg0.y || 0;
-				this.width = arg0.width || 0;
-				this.height = arg0.height || 0;
-				read = 1;
-			} else if (arg0.from === undefined && arg0.to === undefined) {
-				this.x = this.y = this.width = this.height = 0;
-				this._set(arg0);
-				read = 1;
-			}
-		}
-		if (!read) {
-			var point = Point.readNamed(arguments, 'from'),
-				next = Base.peek(arguments);
-			this.x = point.x;
-			this.y = point.y;
-			if (next && next.x !== undefined || Base.hasNamed(arguments, 'to')) {
-				var to = Point.readNamed(arguments, 'to');
-				this.width = to.x - point.x;
-				this.height = to.y - point.y;
-				if (this.width < 0) {
-					this.x = to.x;
-					this.width = -this.width;
-				}
-				if (this.height < 0) {
-					this.y = to.y;
-					this.height = -this.height;
-				}
-			} else {
-				var size = Size.read(arguments);
-				this.width = size.width;
-				this.height = size.height;
-			}
-			read = arguments.__index;
-		}
-		if (this.__read)
-			this.__read = read;
-	},
-
-	set: function(x, y, width, height) {
-		this.x = x;
-		this.y = y;
-		this.width = width;
-		this.height = height;
-		return this;
-	},
-
-	clone: function() {
-		return new Rectangle(this.x, this.y, this.width, this.height);
-	},
-
-	equals: function(rect) {
-		var rt = Base.isPlainValue(rect)
-				? Rectangle.read(arguments)
-				: rect;
-		return rt === this
-				|| rt && this.x === rt.x && this.y === rt.y
-					&& this.width === rt.width && this.height === rt.height
-				|| false;
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '{ x: ' + f.number(this.x)
-				+ ', y: ' + f.number(this.y)
-				+ ', width: ' + f.number(this.width)
-				+ ', height: ' + f.number(this.height)
-				+ ' }';
-	},
-
-	_serialize: function(options) {
-		var f = options.formatter;
-		return [f.number(this.x),
-				f.number(this.y),
-				f.number(this.width),
-				f.number(this.height)];
-	},
-
-	getPoint: function(_dontLink) {
-		var ctor = _dontLink ? Point : LinkedPoint;
-		return new ctor(this.x, this.y, this, 'setPoint');
-	},
-
-	setPoint: function() {
-		var point = Point.read(arguments);
-		this.x = point.x;
-		this.y = point.y;
-	},
-
-	getSize: function(_dontLink) {
-		var ctor = _dontLink ? Size : LinkedSize;
-		return new ctor(this.width, this.height, this, 'setSize');
-	},
-
-	setSize: function() {
-		var size = Size.read(arguments);
-		if (this._fixX)
-			this.x += (this.width - size.width) * this._fixX;
-		if (this._fixY)
-			this.y += (this.height - size.height) * this._fixY;
-		this.width = size.width;
-		this.height = size.height;
-		this._fixW = 1;
-		this._fixH = 1;
-	},
-
-	getLeft: function() {
-		return this.x;
-	},
-
-	setLeft: function(left) {
-		if (!this._fixW)
-			this.width -= left - this.x;
-		this.x = left;
-		this._fixX = 0;
-	},
-
-	getTop: function() {
-		return this.y;
-	},
-
-	setTop: function(top) {
-		if (!this._fixH)
-			this.height -= top - this.y;
-		this.y = top;
-		this._fixY = 0;
-	},
-
-	getRight: function() {
-		return this.x + this.width;
-	},
-
-	setRight: function(right) {
-		if (this._fixX !== undefined && this._fixX !== 1)
-			this._fixW = 0;
-		if (this._fixW)
-			this.x = right - this.width;
-		else
-			this.width = right - this.x;
-		this._fixX = 1;
-	},
-
-	getBottom: function() {
-		return this.y + this.height;
-	},
-
-	setBottom: function(bottom) {
-		if (this._fixY !== undefined && this._fixY !== 1)
-			this._fixH = 0;
-		if (this._fixH)
-			this.y = bottom - this.height;
-		else
-			this.height = bottom - this.y;
-		this._fixY = 1;
-	},
-
-	getCenterX: function() {
-		return this.x + this.width * 0.5;
-	},
-
-	setCenterX: function(x) {
-		this.x = x - this.width * 0.5;
-		this._fixX = 0.5;
-	},
-
-	getCenterY: function() {
-		return this.y + this.height * 0.5;
-	},
-
-	setCenterY: function(y) {
-		this.y = y - this.height * 0.5;
-		this._fixY = 0.5;
-	},
-
-	getCenter: function(_dontLink) {
-		var ctor = _dontLink ? Point : LinkedPoint;
-		return new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');
-	},
-
-	setCenter: function() {
-		var point = Point.read(arguments);
-		this.setCenterX(point.x);
-		this.setCenterY(point.y);
-		return this;
-	},
-
-	getArea: function() {
-		return this.width * this.height;
-	},
-
-	isEmpty: function() {
-		return this.width === 0 || this.height === 0;
-	},
-
-	contains: function(arg) {
-		return arg && arg.width !== undefined
-				|| (Array.isArray(arg) ? arg : arguments).length === 4
-				? this._containsRectangle(Rectangle.read(arguments))
-				: this._containsPoint(Point.read(arguments));
-	},
-
-	_containsPoint: function(point) {
-		var x = point.x,
-			y = point.y;
-		return x >= this.x && y >= this.y
-				&& x <= this.x + this.width
-				&& y <= this.y + this.height;
-	},
-
-	_containsRectangle: function(rect) {
-		var x = rect.x,
-			y = rect.y;
-		return x >= this.x && y >= this.y
-				&& x + rect.width <= this.x + this.width
-				&& y + rect.height <= this.y + this.height;
-	},
-
-	intersects: function() {
-		var rect = Rectangle.read(arguments);
-		return rect.x + rect.width > this.x
-				&& rect.y + rect.height > this.y
-				&& rect.x < this.x + this.width
-				&& rect.y < this.y + this.height;
-	},
-
-	touches: function() {
-		var rect = Rectangle.read(arguments);
-		return rect.x + rect.width >= this.x
-				&& rect.y + rect.height >= this.y
-				&& rect.x <= this.x + this.width
-				&& rect.y <= this.y + this.height;
-	},
-
-	intersect: function() {
-		var rect = Rectangle.read(arguments),
-			x1 = Math.max(this.x, rect.x),
-			y1 = Math.max(this.y, rect.y),
-			x2 = Math.min(this.x + this.width, rect.x + rect.width),
-			y2 = Math.min(this.y + this.height, rect.y + rect.height);
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	},
-
-	unite: function() {
-		var rect = Rectangle.read(arguments),
-			x1 = Math.min(this.x, rect.x),
-			y1 = Math.min(this.y, rect.y),
-			x2 = Math.max(this.x + this.width, rect.x + rect.width),
-			y2 = Math.max(this.y + this.height, rect.y + rect.height);
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	},
-
-	include: function() {
-		var point = Point.read(arguments);
-		var x1 = Math.min(this.x, point.x),
-			y1 = Math.min(this.y, point.y),
-			x2 = Math.max(this.x + this.width, point.x),
-			y2 = Math.max(this.y + this.height, point.y);
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	},
-
-	expand: function() {
-		var amount = Size.read(arguments),
-			hor = amount.width,
-			ver = amount.height;
-		return new Rectangle(this.x - hor / 2, this.y - ver / 2,
-				this.width + hor, this.height + ver);
-	},
-
-	scale: function(hor, ver) {
-		return this.expand(this.width * hor - this.width,
-				this.height * (ver === undefined ? hor : ver) - this.height);
-	}
-}, Base.each([
-		['Top', 'Left'], ['Top', 'Right'],
-		['Bottom', 'Left'], ['Bottom', 'Right'],
-		['Left', 'Center'], ['Top', 'Center'],
-		['Right', 'Center'], ['Bottom', 'Center']
-	],
-	function(parts, index) {
-		var part = parts.join(''),
-			xFirst = /^[RL]/.test(part);
-		if (index >= 4)
-			parts[1] += xFirst ? 'Y' : 'X';
-		var x = parts[xFirst ? 0 : 1],
-			y = parts[xFirst ? 1 : 0],
-			getX = 'get' + x,
-			getY = 'get' + y,
-			setX = 'set' + x,
-			setY = 'set' + y,
-			get = 'get' + part,
-			set = 'set' + part;
-		this[get] = function(_dontLink) {
-			var ctor = _dontLink ? Point : LinkedPoint;
-			return new ctor(this[getX](), this[getY](), this, set);
-		};
-		this[set] = function() {
-			var point = Point.read(arguments);
-			this[setX](point.x);
-			this[setY](point.y);
-		};
-	}, {
-		beans: true
-	}
-));
-
-var LinkedRectangle = Rectangle.extend({
-	initialize: function Rectangle(x, y, width, height, owner, setter) {
-		this.set(x, y, width, height, true);
-		this._owner = owner;
-		this._setter = setter;
-	},
-
-	set: function(x, y, width, height, _dontNotify) {
-		this._x = x;
-		this._y = y;
-		this._width = width;
-		this._height = height;
-		if (!_dontNotify)
-			this._owner[this._setter](this);
-		return this;
-	}
-},
-new function() {
-	var proto = Rectangle.prototype;
-
-	return Base.each(['x', 'y', 'width', 'height'], function(key) {
-		var part = Base.capitalize(key),
-			internal = '_' + key;
-		this['get' + part] = function() {
-			return this[internal];
-		};
-
-		this['set' + part] = function(value) {
-			this[internal] = value;
-			if (!this._dontNotify)
-				this._owner[this._setter](this);
-		};
-	}, Base.each(['Point', 'Size', 'Center',
-			'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',
-			'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
-			'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],
-		function(key) {
-			var name = 'set' + key;
-			this[name] = function() {
-				this._dontNotify = true;
-				proto[name].apply(this, arguments);
-				this._dontNotify = false;
-				this._owner[this._setter](this);
-			};
-		}, {
-			isSelected: function() {
-				return !!(this._owner._selection & 2);
-			},
-
-			setSelected: function(selected) {
-				var owner = this._owner;
-				if (owner.changeSelection) {
-					owner.changeSelection(2, selected);
-				}
-			}
-		})
-	);
-});
-
-var Matrix = Base.extend({
-	_class: 'Matrix',
-
-	initialize: function Matrix(arg) {
-		var count = arguments.length,
-			ok = true;
-		if (count === 6) {
-			this.set.apply(this, arguments);
-		} else if (count === 1) {
-			if (arg instanceof Matrix) {
-				this.set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty);
-			} else if (Array.isArray(arg)) {
-				this.set.apply(this, arg);
-			} else {
-				ok = false;
-			}
-		} else if (count === 0) {
-			this.reset();
-		} else {
-			ok = false;
-		}
-		if (!ok) {
-			throw new Error('Unsupported matrix parameters');
-		}
-	},
-
-	set: function(a, b, c, d, tx, ty, _dontNotify) {
-		this._a = a;
-		this._b = b;
-		this._c = c;
-		this._d = d;
-		this._tx = tx;
-		this._ty = ty;
-		if (!_dontNotify)
-			this._changed();
-		return this;
-	},
-
-	_serialize: function(options, dictionary) {
-		return Base.serialize(this.getValues(), options, true, dictionary);
-	},
-
-	_changed: function() {
-		var owner = this._owner;
-		if (owner) {
-			if (owner._applyMatrix) {
-				owner.transform(null, true);
-			} else {
-				owner._changed(9);
-			}
-		}
-	},
-
-	clone: function() {
-		return new Matrix(this._a, this._b, this._c, this._d,
-				this._tx, this._ty);
-	},
-
-	equals: function(mx) {
-		return mx === this || mx && this._a === mx._a && this._b === mx._b
-				&& this._c === mx._c && this._d === mx._d
-				&& this._tx === mx._tx && this._ty === mx._ty;
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '[[' + [f.number(this._a), f.number(this._c),
-					f.number(this._tx)].join(', ') + '], ['
-				+ [f.number(this._b), f.number(this._d),
-					f.number(this._ty)].join(', ') + ']]';
-	},
-
-	reset: function(_dontNotify) {
-		this._a = this._d = 1;
-		this._b = this._c = this._tx = this._ty = 0;
-		if (!_dontNotify)
-			this._changed();
-		return this;
-	},
-
-	apply: function(recursively, _setApplyMatrix) {
-		var owner = this._owner;
-		if (owner) {
-			owner.transform(null, true, Base.pick(recursively, true),
-					_setApplyMatrix);
-			return this.isIdentity();
-		}
-		return false;
-	},
-
-	translate: function() {
-		var point = Point.read(arguments),
-			x = point.x,
-			y = point.y;
-		this._tx += x * this._a + y * this._c;
-		this._ty += x * this._b + y * this._d;
-		this._changed();
-		return this;
-	},
-
-	scale: function() {
-		var scale = Point.read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		if (center)
-			this.translate(center);
-		this._a *= scale.x;
-		this._b *= scale.x;
-		this._c *= scale.y;
-		this._d *= scale.y;
-		if (center)
-			this.translate(center.negate());
-		this._changed();
-		return this;
-	},
-
-	rotate: function(angle ) {
-		angle *= Math.PI / 180;
-		var center = Point.read(arguments, 1),
-			x = center.x,
-			y = center.y,
-			cos = Math.cos(angle),
-			sin = Math.sin(angle),
-			tx = x - x * cos + y * sin,
-			ty = y - x * sin - y * cos,
-			a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d;
-		this._a = cos * a + sin * c;
-		this._b = cos * b + sin * d;
-		this._c = -sin * a + cos * c;
-		this._d = -sin * b + cos * d;
-		this._tx += tx * a + ty * c;
-		this._ty += tx * b + ty * d;
-		this._changed();
-		return this;
-	},
-
-	shear: function() {
-		var shear = Point.read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		if (center)
-			this.translate(center);
-		var a = this._a,
-			b = this._b;
-		this._a += shear.y * this._c;
-		this._b += shear.y * this._d;
-		this._c += shear.x * a;
-		this._d += shear.x * b;
-		if (center)
-			this.translate(center.negate());
-		this._changed();
-		return this;
-	},
-
-	skew: function() {
-		var skew = Point.read(arguments),
-			center = Point.read(arguments, 0, { readNull: true }),
-			toRadians = Math.PI / 180,
-			shear = new Point(Math.tan(skew.x * toRadians),
-				Math.tan(skew.y * toRadians));
-		return this.shear(shear, center);
-	},
-
-	append: function(mx) {
-		if (mx) {
-			var a1 = this._a,
-				b1 = this._b,
-				c1 = this._c,
-				d1 = this._d,
-				a2 = mx._a,
-				b2 = mx._c,
-				c2 = mx._b,
-				d2 = mx._d,
-				tx2 = mx._tx,
-				ty2 = mx._ty;
-			this._a = a2 * a1 + c2 * c1;
-			this._c = b2 * a1 + d2 * c1;
-			this._b = a2 * b1 + c2 * d1;
-			this._d = b2 * b1 + d2 * d1;
-			this._tx += tx2 * a1 + ty2 * c1;
-			this._ty += tx2 * b1 + ty2 * d1;
-			this._changed();
-		}
-		return this;
-	},
-
-	prepend: function(mx) {
-		if (mx) {
-			var a1 = this._a,
-				b1 = this._b,
-				c1 = this._c,
-				d1 = this._d,
-				tx1 = this._tx,
-				ty1 = this._ty,
-				a2 = mx._a,
-				b2 = mx._c,
-				c2 = mx._b,
-				d2 = mx._d,
-				tx2 = mx._tx,
-				ty2 = mx._ty;
-			this._a = a2 * a1 + b2 * b1;
-			this._c = a2 * c1 + b2 * d1;
-			this._b = c2 * a1 + d2 * b1;
-			this._d = c2 * c1 + d2 * d1;
-			this._tx = a2 * tx1 + b2 * ty1 + tx2;
-			this._ty = c2 * tx1 + d2 * ty1 + ty2;
-			this._changed();
-		}
-		return this;
-	},
-
-	appended: function(mx) {
-		return this.clone().append(mx);
-	},
-
-	prepended: function(mx) {
-		return this.clone().prepend(mx);
-	},
-
-	invert: function() {
-		var a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d,
-			tx = this._tx,
-			ty = this._ty,
-			det = a * d - b * c,
-			res = null;
-		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
-			this._a = d / det;
-			this._b = -b / det;
-			this._c = -c / det;
-			this._d = a / det;
-			this._tx = (c * ty - d * tx) / det;
-			this._ty = (b * tx - a * ty) / det;
-			res = this;
-		}
-		return res;
-	},
-
-	inverted: function() {
-		return this.clone().invert();
-	},
-
-	concatenate: '#append',
-	preConcatenate: '#prepend',
-	chain: '#appended',
-
-	_shiftless: function() {
-		return new Matrix(this._a, this._b, this._c, this._d, 0, 0);
-	},
-
-	_orNullIfIdentity: function() {
-		return this.isIdentity() ? null : this;
-	},
-
-	isIdentity: function() {
-		return this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1
-				&& this._tx === 0 && this._ty === 0;
-	},
-
-	isInvertible: function() {
-		var det = this._a * this._d - this._c * this._b;
-		return det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);
-	},
-
-	isSingular: function() {
-		return !this.isInvertible();
-	},
-
-	transform: function( src, dst, count) {
-		return arguments.length < 3
-			? this._transformPoint(Point.read(arguments))
-			: this._transformCoordinates(src, dst, count);
-	},
-
-	_transformPoint: function(point, dest, _dontNotify) {
-		var x = point.x,
-			y = point.y;
-		if (!dest)
-			dest = new Point();
-		return dest.set(
-				x * this._a + y * this._c + this._tx,
-				x * this._b + y * this._d + this._ty,
-				_dontNotify);
-	},
-
-	_transformCoordinates: function(src, dst, count) {
-		for (var i = 0, max = 2 * count; i < max; i += 2) {
-			var x = src[i],
-				y = src[i + 1];
-			dst[i] = x * this._a + y * this._c + this._tx;
-			dst[i + 1] = x * this._b + y * this._d + this._ty;
-		}
-		return dst;
-	},
-
-	_transformCorners: function(rect) {
-		var x1 = rect.x,
-			y1 = rect.y,
-			x2 = x1 + rect.width,
-			y2 = y1 + rect.height,
-			coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];
-		return this._transformCoordinates(coords, coords, 4);
-	},
-
-	_transformBounds: function(bounds, dest, _dontNotify) {
-		var coords = this._transformCorners(bounds),
-			min = coords.slice(0, 2),
-			max = min.slice();
-		for (var i = 2; i < 8; i++) {
-			var val = coords[i],
-				j = i & 1;
-			if (val < min[j]) {
-				min[j] = val;
-			} else if (val > max[j]) {
-				max[j] = val;
-			}
-		}
-		if (!dest)
-			dest = new Rectangle();
-		return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1],
-				_dontNotify);
-	},
-
-	inverseTransform: function() {
-		return this._inverseTransform(Point.read(arguments));
-	},
-
-	_inverseTransform: function(point, dest, _dontNotify) {
-		var a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d,
-			tx = this._tx,
-			ty = this._ty,
-			det = a * d - b * c,
-			res = null;
-		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
-			var x = point.x - this._tx,
-				y = point.y - this._ty;
-			if (!dest)
-				dest = new Point();
-			res = dest.set(
-					(x * d - y * c) / det,
-					(y * a - x * b) / det,
-					_dontNotify);
-		}
-		return res;
-	},
-
-	decompose: function() {
-		var a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d,
-			det = a * d - b * c,
-			sqrt = Math.sqrt,
-			atan2 = Math.atan2,
-			degrees = 180 / Math.PI,
-			rotate,
-			scale,
-			skew;
-		if (a !== 0 || b !== 0) {
-			var r = sqrt(a * a + b * b);
-			rotate = Math.acos(a / r) * (b > 0 ? 1 : -1);
-			scale = [r, det / r];
-			skew = [atan2(a * c + b * d, r * r), 0];
-		} else if (c !== 0 || d !== 0) {
-			var s = sqrt(c * c + d * d);
-			rotate = Math.asin(c / s)  * (d > 0 ? 1 : -1);
-			scale = [det / s, s];
-			skew = [0, atan2(a * c + b * d, s * s)];
-		} else {
-			rotate = 0;
-			skew = scale = [0, 0];
-		}
-		return {
-			translation: this.getTranslation(),
-			rotation: rotate * degrees,
-			scaling: new Point(scale),
-			skewing: new Point(skew[0] * degrees, skew[1] * degrees)
-		};
-	},
-
-	getValues: function() {
-		return [ this._a, this._b, this._c, this._d, this._tx, this._ty ];
-	},
-
-	getTranslation: function() {
-		return new Point(this._tx, this._ty);
-	},
-
-	getScaling: function() {
-		return (this.decompose() || {}).scaling;
-	},
-
-	getRotation: function() {
-		return (this.decompose() || {}).rotation;
-	},
-
-	applyToContext: function(ctx) {
-		if (!this.isIdentity()) {
-			ctx.transform(this._a, this._b, this._c, this._d,
-					this._tx, this._ty);
-		}
-	}
-}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {
-	var part = Base.capitalize(key),
-		prop = '_' + key;
-	this['get' + part] = function() {
-		return this[prop];
-	};
-	this['set' + part] = function(value) {
-		this[prop] = value;
-		this._changed();
-	};
-}, {}));
-
-var Line = Base.extend({
-	_class: 'Line',
-
-	initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
-		var asVector = false;
-		if (arguments.length >= 4) {
-			this._px = arg0;
-			this._py = arg1;
-			this._vx = arg2;
-			this._vy = arg3;
-			asVector = arg4;
-		} else {
-			this._px = arg0.x;
-			this._py = arg0.y;
-			this._vx = arg1.x;
-			this._vy = arg1.y;
-			asVector = arg2;
-		}
-		if (!asVector) {
-			this._vx -= this._px;
-			this._vy -= this._py;
-		}
-	},
-
-	getPoint: function() {
-		return new Point(this._px, this._py);
-	},
-
-	getVector: function() {
-		return new Point(this._vx, this._vy);
-	},
-
-	getLength: function() {
-		return this.getVector().getLength();
-	},
-
-	intersect: function(line, isInfinite) {
-		return Line.intersect(
-				this._px, this._py, this._vx, this._vy,
-				line._px, line._py, line._vx, line._vy,
-				true, isInfinite);
-	},
-
-	getSide: function(point, isInfinite) {
-		return Line.getSide(
-				this._px, this._py, this._vx, this._vy,
-				point.x, point.y, true, isInfinite);
-	},
-
-	getDistance: function(point) {
-		return Math.abs(Line.getSignedDistance(
-				this._px, this._py, this._vx, this._vy,
-				point.x, point.y, true));
-	},
-
-	isCollinear: function(line) {
-		return Point.isCollinear(this._vx, this._vy, line._vx, line._vy);
-	},
-
-	isOrthogonal: function(line) {
-		return Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);
-	},
-
-	statics: {
-		intersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,
-				isInfinite) {
-			if (!asVector) {
-				v1x -= p1x;
-				v1y -= p1y;
-				v2x -= p2x;
-				v2y -= p2y;
-			}
-			var cross = v1x * v2y - v1y * v2x;
-			if (!Numerical.isZero(cross)) {
-				var dx = p1x - p2x,
-					dy = p1y - p2y,
-					u1 = (v2x * dy - v2y * dx) / cross,
-					u2 = (v1x * dy - v1y * dx) / cross,
-					epsilon = 1e-12,
-					uMin = -epsilon,
-					uMax = 1 + epsilon;
-				if (isInfinite
-						|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {
-					if (!isInfinite) {
-						u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;
-					}
-					return new Point(
-							p1x + u1 * v1x,
-							p1y + u1 * v1y);
-				}
-			}
-		},
-
-		getSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {
-			if (!asVector) {
-				vx -= px;
-				vy -= py;
-			}
-			var v2x = x - px,
-				v2y = y - py,
-				ccw = v2x * vy - v2y * vx;
-			if (ccw === 0 && !isInfinite) {
-				ccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);
-				if (ccw >= 0 && ccw <= 1)
-					ccw = 0;
-			}
-			return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
-		},
-
-		getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
-			if (!asVector) {
-				vx -= px;
-				vy -= py;
-			}
-			return vx === 0 ? vy > 0 ? x - px : px - x
-				 : vy === 0 ? vx < 0 ? y - py : py - y
-				 : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);
-		}
-	}
-});
-
-var Project = PaperScopeItem.extend({
-	_class: 'Project',
-	_list: 'projects',
-	_reference: 'project',
-	_compactSerialize: true,
-
-	initialize: function Project(element) {
-		PaperScopeItem.call(this, true);
-		this._children = [];
-		this._namedChildren = {};
-		this._activeLayer = null;
-		this._currentStyle = new Style(null, null, this);
-		this._view = View.create(this,
-				element || CanvasProvider.getCanvas(1, 1));
-		this._selectionItems = {};
-		this._selectionCount = 0;
-		this._updateVersion = 0;
-	},
-
-	_serialize: function(options, dictionary) {
-		return Base.serialize(this._children, options, true, dictionary);
-	},
-
-	_changed: function(flags, item) {
-		if (flags & 1) {
-			var view = this._view;
-			if (view) {
-				view._needsUpdate = true;
-				if (!view._requested && view._autoUpdate)
-					view.requestUpdate();
-			}
-		}
-		var changes = this._changes;
-		if (changes && item) {
-			var changesById = this._changesById,
-				id = item._id,
-				entry = changesById[id];
-			if (entry) {
-				entry.flags |= flags;
-			} else {
-				changes.push(changesById[id] = { item: item, flags: flags });
-			}
-		}
-	},
-
-	clear: function() {
-		var children = this._children;
-		for (var i = children.length - 1; i >= 0; i--)
-			children[i].remove();
-	},
-
-	isEmpty: function() {
-		return this._children.length === 0;
-	},
-
-	remove: function remove() {
-		if (!remove.base.call(this))
-			return false;
-		if (this._view)
-			this._view.remove();
-		return true;
-	},
-
-	getView: function() {
-		return this._view;
-	},
-
-	getCurrentStyle: function() {
-		return this._currentStyle;
-	},
-
-	setCurrentStyle: function(style) {
-		this._currentStyle.initialize(style);
-	},
-
-	getIndex: function() {
-		return this._index;
-	},
-
-	getOptions: function() {
-		return this._scope.settings;
-	},
-
-	getLayers: function() {
-		return this._children;
-	},
-
-	getActiveLayer: function() {
-		return this._activeLayer || new Layer({ project: this, insert: true });
-	},
-
-	getSymbolDefinitions: function() {
-		var definitions = [],
-			ids = {};
-		this.getItems({
-			class: SymbolItem,
-			match: function(item) {
-				var definition = item._definition,
-					id = definition._id;
-				if (!ids[id]) {
-					ids[id] = true;
-					definitions.push(definition);
-				}
-				return false;
-			}
-		});
-		return definitions;
-	},
-
-	getSymbols: 'getSymbolDefinitions',
-
-	getSelectedItems: function() {
-		var selectionItems = this._selectionItems,
-			items = [];
-		for (var id in selectionItems) {
-			var item = selectionItems[id],
-				selection = item._selection;
-			if (selection & 1 && item.isInserted()) {
-				items.push(item);
-			} else if (!selection) {
-				this._updateSelection(item);
-			}
-		}
-		return items;
-	},
-
-	_updateSelection: function(item) {
-		var id = item._id,
-			selectionItems = this._selectionItems;
-		if (item._selection) {
-			if (selectionItems[id] !== item) {
-				this._selectionCount++;
-				selectionItems[id] = item;
-			}
-		} else if (selectionItems[id] === item) {
-			this._selectionCount--;
-			delete selectionItems[id];
-		}
-	},
-
-	selectAll: function() {
-		var children = this._children;
-		for (var i = 0, l = children.length; i < l; i++)
-			children[i].setFullySelected(true);
-	},
-
-	deselectAll: function() {
-		var selectionItems = this._selectionItems;
-		for (var i in selectionItems)
-			selectionItems[i].setFullySelected(false);
-	},
-
-	addLayer: function(layer) {
-		return this.insertLayer(undefined, layer);
-	},
-
-	insertLayer: function(index, layer) {
-		if (layer instanceof Layer) {
-			layer._remove(false, true);
-			Base.splice(this._children, [layer], index, 0);
-			layer._setProject(this, true);
-			var name = layer._name;
-			if (name)
-				layer.setName(name);
-			if (this._changes)
-				layer._changed(5);
-			if (!this._activeLayer)
-				this._activeLayer = layer;
-		} else {
-			layer = null;
-		}
-		return layer;
-	},
-
-	_insertItem: function(index, item, _preserve, _created) {
-		item = this.insertLayer(index, item)
-				|| (this._activeLayer || this._insertItem(undefined,
-						new Layer(Item.NO_INSERT), true, true))
-						.insertChild(index, item, _preserve);
-		if (_created && item.activate)
-			item.activate();
-		return item;
-	},
-
-	getItems: function(options) {
-		return Item._getItems(this, options);
-	},
-
-	getItem: function(options) {
-		return Item._getItems(this, options, null, null, true)[0] || null;
-	},
-
-	importJSON: function(json) {
-		this.activate();
-		var layer = this._activeLayer;
-		return Base.importJSON(json, layer && layer.isEmpty() && layer);
-	},
-
-	removeOn: function(type) {
-		var sets = this._removeSets;
-		if (sets) {
-			if (type === 'mouseup')
-				sets.mousedrag = null;
-			var set = sets[type];
-			if (set) {
-				for (var id in set) {
-					var item = set[id];
-					for (var key in sets) {
-						var other = sets[key];
-						if (other && other != set)
-							delete other[item._id];
-					}
-					item.remove();
-				}
-				sets[type] = null;
-			}
-		}
-	},
-
-	draw: function(ctx, matrix, pixelRatio) {
-		this._updateVersion++;
-		ctx.save();
-		matrix.applyToContext(ctx);
-		var children = this._children,
-			param = new Base({
-				offset: new Point(0, 0),
-				pixelRatio: pixelRatio,
-				viewMatrix: matrix.isIdentity() ? null : matrix,
-				matrices: [new Matrix()],
-				updateMatrix: true
-			});
-		for (var i = 0, l = children.length; i < l; i++) {
-			children[i].draw(ctx, param);
-		}
-		ctx.restore();
-
-		if (this._selectionCount > 0) {
-			ctx.save();
-			ctx.strokeWidth = 1;
-			var items = this._selectionItems,
-				size = this._scope.settings.handleSize,
-				version = this._updateVersion;
-			for (var id in items) {
-				items[id]._drawSelection(ctx, matrix, size, items, version);
-			}
-			ctx.restore();
-		}
-	}
-});
-
-var Item = Base.extend(Emitter, {
-	statics: {
-		extend: function extend(src) {
-			if (src._serializeFields)
-				src._serializeFields = Base.set({},
-					this.prototype._serializeFields, src._serializeFields);
-			return extend.base.apply(this, arguments);
-		},
-
-		NO_INSERT: { insert: false }
-	},
-
-	_class: 'Item',
-	_name: null,
-	_applyMatrix: true,
-	_canApplyMatrix: true,
-	_canScaleStroke: false,
-	_pivot: null,
-	_visible: true,
-	_blendMode: 'normal',
-	_opacity: 1,
-	_locked: false,
-	_guide: false,
-	_clipMask: false,
-	_selection: 0,
-	_selectBounds: true,
-	_selectChildren: false,
-	_serializeFields: {
-		name: null,
-		applyMatrix: null,
-		matrix: new Matrix(),
-		pivot: null,
-		visible: true,
-		blendMode: 'normal',
-		opacity: 1,
-		locked: false,
-		guide: false,
-		clipMask: false,
-		selected: false,
-		data: {}
-	}
-},
-new function() {
-	var handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
-			'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];
-	return Base.each(handlers,
-		function(name) {
-			this._events[name] = {
-				install: function(type) {
-					this.getView()._countItemEvent(type, 1);
-				},
-
-				uninstall: function(type) {
-					this.getView()._countItemEvent(type, -1);
-				}
-			};
-		}, {
-			_events: {
-				onFrame: {
-					install: function() {
-						this.getView()._animateItem(this, true);
-					},
-
-					uninstall: function() {
-						this.getView()._animateItem(this, false);
-					}
-				},
-
-				onLoad: {},
-				onError: {}
-			},
-			statics: {
-				_itemHandlers: handlers
-			}
-		}
-	);
-}, {
-	initialize: function Item() {
-	},
-
-	_initialize: function(props, point) {
-		var hasProps = props && Base.isPlainObject(props),
-			internal = hasProps && props.internal === true,
-			matrix = this._matrix = new Matrix(),
-			project = hasProps && props.project || paper.project,
-			settings = paper.settings;
-		this._id = internal ? null : UID.get();
-		this._parent = this._index = null;
-		this._applyMatrix = this._canApplyMatrix && settings.applyMatrix;
-		if (point)
-			matrix.translate(point);
-		matrix._owner = this;
-		this._style = new Style(project._currentStyle, this, project);
-		if (internal || hasProps && props.insert === false
-			|| !settings.insertItems && !(hasProps && props.insert === true)) {
-			this._setProject(project);
-		} else {
-			(hasProps && props.parent || project)
-					._insertItem(undefined, this, true, true);
-		}
-		if (hasProps && props !== Item.NO_INSERT) {
-			Base.filter(this, props, {
-				internal: true, insert: true, project: true, parent: true
-			});
-		}
-		return hasProps;
-	},
-
-	_serialize: function(options, dictionary) {
-		var props = {},
-			that = this;
-
-		function serialize(fields) {
-			for (var key in fields) {
-				var value = that[key];
-				if (!Base.equals(value, key === 'leading'
-						? fields.fontSize * 1.2 : fields[key])) {
-					props[key] = Base.serialize(value, options,
-							key !== 'data', dictionary);
-				}
-			}
-		}
-
-		serialize(this._serializeFields);
-		if (!(this instanceof Group))
-			serialize(this._style._defaults);
-		return [ this._class, props ];
-	},
-
-	_changed: function(flags) {
-		var symbol = this._symbol,
-			cacheParent = this._parent || symbol,
-			project = this._project;
-		if (flags & 8) {
-			this._bounds = this._position = this._decomposed =
-					this._globalMatrix = undefined;
-		}
-		if (cacheParent
-				&& (flags & 40)) {
-			Item._clearBoundsCache(cacheParent);
-		}
-		if (flags & 2) {
-			Item._clearBoundsCache(this);
-		}
-		if (project)
-			project._changed(flags, this);
-		if (symbol)
-			symbol._changed(flags);
-	},
-
-	set: function(props) {
-		if (props)
-			this._set(props);
-		return this;
-	},
-
-	getId: function() {
-		return this._id;
-	},
-
-	getName: function() {
-		return this._name;
-	},
-
-	setName: function(name) {
-
-		if (this._name)
-			this._removeNamed();
-		if (name === (+name) + '')
-			throw new Error(
-					'Names consisting only of numbers are not supported.');
-		var owner = this._getOwner();
-		if (name && owner) {
-			var children = owner._children,
-				namedChildren = owner._namedChildren;
-			(namedChildren[name] = namedChildren[name] || []).push(this);
-			if (!(name in children))
-				children[name] = this;
-		}
-		this._name = name || undefined;
-		this._changed(128);
-	},
-
-	getStyle: function() {
-		return this._style;
-	},
-
-	setStyle: function(style) {
-		this.getStyle().set(style);
-	}
-}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],
-	function(name) {
-		var part = Base.capitalize(name),
-			name = '_' + name;
-		this['get' + part] = function() {
-			return this[name];
-		};
-		this['set' + part] = function(value) {
-			if (value != this[name]) {
-				this[name] = value;
-				this._changed(name === '_locked'
-						? 128 : 129);
-			}
-		};
-	},
-{}), {
-	beans: true,
-
-	getSelection: function() {
-		return this._selection;
-	},
-
-	setSelection: function(selection) {
-		if (selection !== this._selection) {
-			this._selection = selection;
-			var project = this._project;
-			if (project) {
-				project._updateSelection(this);
-				this._changed(129);
-			}
-		}
-	},
-
-	changeSelection: function(flag, selected) {
-		var selection = this._selection;
-		this.setSelection(selected ? selection | flag : selection & ~flag);
-	},
-
-	isSelected: function() {
-		if (this._selectChildren) {
-			var children = this._children;
-			for (var i = 0, l = children.length; i < l; i++)
-				if (children[i].isSelected())
-					return true;
-		}
-		return !!(this._selection & 1);
-	},
-
-	setSelected: function(selected) {
-		if (this._selectChildren) {
-			var children = this._children;
-			for (var i = 0, l = children.length; i < l; i++)
-				children[i].setSelected(selected);
-		}
-		this.changeSelection(1, selected);
-	},
-
-	isFullySelected: function() {
-		var children = this._children,
-			selected = !!(this._selection & 1);
-		if (children && selected) {
-			for (var i = 0, l = children.length; i < l; i++)
-				if (!children[i].isFullySelected())
-					return false;
-			return true;
-		}
-		return selected;
-	},
-
-	setFullySelected: function(selected) {
-		var children = this._children;
-		if (children) {
-			for (var i = 0, l = children.length; i < l; i++)
-				children[i].setFullySelected(selected);
-		}
-		this.changeSelection(1, selected);
-	},
-
-	isClipMask: function() {
-		return this._clipMask;
-	},
-
-	setClipMask: function(clipMask) {
-		if (this._clipMask != (clipMask = !!clipMask)) {
-			this._clipMask = clipMask;
-			if (clipMask) {
-				this.setFillColor(null);
-				this.setStrokeColor(null);
-			}
-			this._changed(129);
-			if (this._parent)
-				this._parent._changed(1024);
-		}
-	},
-
-	getData: function() {
-		if (!this._data)
-			this._data = {};
-		return this._data;
-	},
-
-	setData: function(data) {
-		this._data = data;
-	},
-
-	getPosition: function(_dontLink) {
-		var position = this._position,
-			ctor = _dontLink ? Point : LinkedPoint;
-		if (!position) {
-			var pivot = this._pivot;
-			position = this._position = pivot
-					? this._matrix._transformPoint(pivot)
-					: this.getBounds().getCenter(true);
-		}
-		return new ctor(position.x, position.y, this, 'setPosition');
-	},
-
-	setPosition: function() {
-		this.translate(Point.read(arguments).subtract(this.getPosition(true)));
-	},
-
-	getPivot: function(_dontLink) {
-		var pivot = this._pivot;
-		if (pivot) {
-			var ctor = _dontLink ? Point : LinkedPoint;
-			pivot = new ctor(pivot.x, pivot.y, this, 'setPivot');
-		}
-		return pivot;
-	},
-
-	setPivot: function() {
-		this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
-		this._position = undefined;
-	}
-}, Base.each({
-		getStrokeBounds: { stroke: true },
-		getHandleBounds: { handle: true },
-		getInternalBounds: { internal: true }
-	},
-	function(options, key) {
-		this[key] = function(matrix) {
-			return this.getBounds(matrix, options);
-		};
-	},
-{
-	beans: true,
-
-	getBounds: function(matrix, options) {
-		var hasMatrix = options || matrix instanceof Matrix,
-			opts = Base.set({}, hasMatrix ? options : matrix,
-					this._boundsOptions);
-		if (!opts.stroke || this.getStrokeScaling())
-			opts.cacheItem = this;
-		var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
-		return arguments.length === 0
-				? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
-						bounds.height, this, 'setBounds')
-				: bounds;
-	},
-
-	setBounds: function() {
-		var rect = Rectangle.read(arguments),
-			bounds = this.getBounds(),
-			_matrix = this._matrix,
-			matrix = new Matrix(),
-			center = rect.getCenter();
-		matrix.translate(center);
-		if (rect.width != bounds.width || rect.height != bounds.height) {
-			if (!_matrix.isInvertible()) {
-				_matrix.initialize(_matrix._backup
-						|| new Matrix().translate(_matrix.getTranslation()));
-				bounds = this.getBounds();
-			}
-			matrix.scale(
-					bounds.width !== 0 ? rect.width / bounds.width : 0,
-					bounds.height !== 0 ? rect.height / bounds.height : 0);
-		}
-		center = bounds.getCenter();
-		matrix.translate(-center.x, -center.y);
-		this.transform(matrix);
-	},
-
-	_getBounds: function(matrix, options) {
-		var children = this._children;
-		if (!children || children.length === 0)
-			return new Rectangle();
-		Item._updateBoundsCache(this, options.cacheItem);
-		return Item._getBounds(children, matrix, options);
-	},
-
-	_getCachedBounds: function(matrix, options) {
-		matrix = matrix && matrix._orNullIfIdentity();
-		var internal = options.internal,
-			cacheItem = options.cacheItem,
-			_matrix = internal ? null : this._matrix._orNullIfIdentity(),
-			cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
-				options.stroke ? 1 : 0,
-				options.handle ? 1 : 0,
-				internal ? 1 : 0
-			].join('');
-		Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
-		if (cacheKey && this._bounds && cacheKey in this._bounds)
-			return this._bounds[cacheKey].rect.clone();
-		var bounds = this._getBounds(matrix || _matrix, options);
-		if (cacheKey) {
-			if (!this._bounds)
-				this._bounds = {};
-			var cached = this._bounds[cacheKey] = {
-				rect: bounds.clone(),
-				internal: options.internal
-			};
-		}
-		return bounds;
-	},
-
-	_getStrokeMatrix: function(matrix, options) {
-		var parent = this.getStrokeScaling() ? null
-				: options && options.internal ? this
-					: this._parent || this._symbol && this._symbol._item,
-			mx = parent ? parent.getViewMatrix().invert() : matrix;
-		return mx && mx._shiftless();
-	},
-
-	statics: {
-		_updateBoundsCache: function(parent, item) {
-			if (parent && item) {
-				var id = item._id,
-					ref = parent._boundsCache = parent._boundsCache || {
-						ids: {},
-						list: []
-					};
-				if (!ref.ids[id]) {
-					ref.list.push(item);
-					ref.ids[id] = item;
-				}
-			}
-		},
-
-		_clearBoundsCache: function(item) {
-			var cache = item._boundsCache;
-			if (cache) {
-				item._bounds = item._position = item._boundsCache = undefined;
-				for (var i = 0, list = cache.list, l = list.length; i < l; i++){
-					var other = list[i];
-					if (other !== item) {
-						other._bounds = other._position = undefined;
-						if (other._boundsCache)
-							Item._clearBoundsCache(other);
-					}
-				}
-			}
-		},
-
-		_getBounds: function(items, matrix, options) {
-			var x1 = Infinity,
-				x2 = -x1,
-				y1 = x1,
-				y2 = x2;
-			options = options || {};
-			for (var i = 0, l = items.length; i < l; i++) {
-				var item = items[i];
-				if (item._visible && !item.isEmpty()) {
-					var rect = item._getCachedBounds(
-						matrix && matrix.appended(item._matrix), options);
-					x1 = Math.min(rect.x, x1);
-					y1 = Math.min(rect.y, y1);
-					x2 = Math.max(rect.x + rect.width, x2);
-					y2 = Math.max(rect.y + rect.height, y2);
-				}
-			}
-			return isFinite(x1)
-					? new Rectangle(x1, y1, x2 - x1, y2 - y1)
-					: new Rectangle();
-		}
-	}
-
-}), {
-	beans: true,
-
-	_decompose: function() {
-		return this._decomposed || (this._decomposed = this._matrix.decompose());
-	},
-
-	getRotation: function() {
-		var decomposed = this._decompose();
-		return decomposed && decomposed.rotation;
-	},
-
-	setRotation: function(rotation) {
-		var current = this.getRotation();
-		if (current != null && rotation != null) {
-			this.rotate(rotation - current);
-		}
-	},
-
-	getScaling: function(_dontLink) {
-		var decomposed = this._decompose(),
-			scaling = decomposed && decomposed.scaling,
-			ctor = _dontLink ? Point : LinkedPoint;
-		return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling');
-	},
-
-	setScaling: function() {
-		var current = this.getScaling(),
-			scaling = Point.read(arguments, 0, { clone: true, readNull: true });
-		if (current && scaling) {
-			this.scale(scaling.x / current.x, scaling.y / current.y);
-		}
-	},
-
-	getMatrix: function() {
-		return this._matrix;
-	},
-
-	setMatrix: function() {
-		var matrix = this._matrix;
-		matrix.initialize.apply(matrix, arguments);
-	},
-
-	getGlobalMatrix: function(_dontClone) {
-		var matrix = this._globalMatrix,
-			updateVersion = this._project._updateVersion;
-		if (matrix && matrix._updateVersion !== updateVersion)
-			matrix = null;
-		if (!matrix) {
-			matrix = this._globalMatrix = this._matrix.clone();
-			var parent = this._parent;
-			if (parent)
-				matrix.prepend(parent.getGlobalMatrix(true));
-			matrix._updateVersion = updateVersion;
-		}
-		return _dontClone ? matrix : matrix.clone();
-	},
-
-	getViewMatrix: function() {
-		return this.getGlobalMatrix().prepend(this.getView()._matrix);
-	},
-
-	getApplyMatrix: function() {
-		return this._applyMatrix;
-	},
-
-	setApplyMatrix: function(apply) {
-		if (this._applyMatrix = this._canApplyMatrix && !!apply)
-			this.transform(null, true);
-	},
-
-	getTransformContent: '#getApplyMatrix',
-	setTransformContent: '#setApplyMatrix',
-}, {
-	getProject: function() {
-		return this._project;
-	},
-
-	_setProject: function(project, installEvents) {
-		if (this._project !== project) {
-			if (this._project)
-				this._installEvents(false);
-			this._project = project;
-			var children = this._children;
-			for (var i = 0, l = children && children.length; i < l; i++)
-				children[i]._setProject(project);
-			installEvents = true;
-		}
-		if (installEvents)
-			this._installEvents(true);
-	},
-
-	getView: function() {
-		return this._project._view;
-	},
-
-	_installEvents: function _installEvents(install) {
-		_installEvents.base.call(this, install);
-		var children = this._children;
-		for (var i = 0, l = children && children.length; i < l; i++)
-			children[i]._installEvents(install);
-	},
-
-	getLayer: function() {
-		var parent = this;
-		while (parent = parent._parent) {
-			if (parent instanceof Layer)
-				return parent;
-		}
-		return null;
-	},
-
-	getParent: function() {
-		return this._parent;
-	},
-
-	setParent: function(item) {
-		return item.addChild(this);
-	},
-
-	_getOwner: '#getParent',
-
-	getChildren: function() {
-		return this._children;
-	},
-
-	setChildren: function(items, _preserve) {
-		this.removeChildren();
-		this.addChildren(items, _preserve);
-	},
-
-	getFirstChild: function() {
-		return this._children && this._children[0] || null;
-	},
-
-	getLastChild: function() {
-		return this._children && this._children[this._children.length - 1]
-				|| null;
-	},
-
-	getNextSibling: function() {
-		var owner = this._getOwner();
-		return owner && owner._children[this._index + 1] || null;
-	},
-
-	getPreviousSibling: function() {
-		var owner = this._getOwner();
-		return owner && owner._children[this._index - 1] || null;
-	},
-
-	getIndex: function() {
-		return this._index;
-	},
-
-	equals: function(item) {
-		return item === this || item && this._class === item._class
-				&& this._style.equals(item._style)
-				&& this._matrix.equals(item._matrix)
-				&& this._locked === item._locked
-				&& this._visible === item._visible
-				&& this._blendMode === item._blendMode
-				&& this._opacity === item._opacity
-				&& this._clipMask === item._clipMask
-				&& this._guide === item._guide
-				&& this._equals(item)
-				|| false;
-	},
-
-	_equals: function(item) {
-		return Base.equals(this._children, item._children);
-	},
-
-	clone: function(options) {
-		var copy = new this.constructor(Item.NO_INSERT),
-			children = this._children,
-			insert = Base.pick(options ? options.insert : undefined,
-					options === undefined || options === true),
-			deep = Base.pick(options ? options.deep : undefined, true);
-		if (children)
-			copy.copyAttributes(this);
-		if (!children || deep)
-			copy.copyContent(this);
-		if (!children)
-			copy.copyAttributes(this);
-		if (insert)
-			copy.insertAbove(this);
-		var name = this._name,
-			parent = this._parent;
-		if (name && parent) {
-			var children = parent._children,
-				orig = name,
-				i = 1;
-			while (children[name])
-				name = orig + ' ' + (i++);
-			if (name !== orig)
-				copy.setName(name);
-		}
-		return copy;
-	},
-
-	copyContent: function(source) {
-		var children = source._children;
-		for (var i = 0, l = children && children.length; i < l; i++) {
-			this.addChild(children[i].clone(false), true);
-		}
-	},
-
-	copyAttributes: function(source, excludeMatrix) {
-		this.setStyle(source._style);
-		var keys = ['_locked', '_visible', '_blendMode', '_opacity',
-				'_clipMask', '_guide'];
-		for (var i = 0, l = keys.length; i < l; i++) {
-			var key = keys[i];
-			if (source.hasOwnProperty(key))
-				this[key] = source[key];
-		}
-		if (!excludeMatrix)
-			this._matrix.initialize(source._matrix);
-		this.setApplyMatrix(source._applyMatrix);
-		this.setPivot(source._pivot);
-		this.setSelection(source._selection);
-		var data = source._data,
-			name = source._name;
-		this._data = data ? Base.clone(data) : null;
-		if (name)
-			this.setName(name);
-	},
-
-	rasterize: function(resolution, insert) {
-		var bounds = this.getStrokeBounds(),
-			scale = (resolution || this.getView().getResolution()) / 72,
-			topLeft = bounds.getTopLeft().floor(),
-			bottomRight = bounds.getBottomRight().ceil(),
-			size = new Size(bottomRight.subtract(topLeft)),
-			raster = new Raster(Item.NO_INSERT);
-		if (!size.isZero()) {
-			var canvas = CanvasProvider.getCanvas(size.multiply(scale)),
-				ctx = canvas.getContext('2d'),
-				matrix = new Matrix().scale(scale).translate(topLeft.negate());
-			ctx.save();
-			matrix.applyToContext(ctx);
-			this.draw(ctx, new Base({ matrices: [matrix] }));
-			ctx.restore();
-			raster.setCanvas(canvas);
-		}
-		raster.transform(new Matrix().translate(topLeft.add(size.divide(2)))
-				.scale(1 / scale));
-		if (insert === undefined || insert)
-			raster.insertAbove(this);
-		return raster;
-	},
-
-	contains: function() {
-		return !!this._contains(
-				this._matrix._inverseTransform(Point.read(arguments)));
-	},
-
-	_contains: function(point) {
-		var children = this._children;
-		if (children) {
-			for (var i = children.length - 1; i >= 0; i--) {
-				if (children[i].contains(point))
-					return true;
-			}
-			return false;
-		}
-		return point.isInside(this.getInternalBounds());
-	},
-
-	isInside: function() {
-		return Rectangle.read(arguments).contains(this.getBounds());
-	},
-
-	_asPathItem: function() {
-		return new Path.Rectangle({
-			rectangle: this.getInternalBounds(),
-			matrix: this._matrix,
-			insert: false,
-		});
-	},
-
-	intersects: function(item, _matrix) {
-		if (!(item instanceof Item))
-			return false;
-		return this._asPathItem().getIntersections(item._asPathItem(), null,
-				_matrix, true).length > 0;
-	}
-},
-new function() {
-	function hitTest() {
-		return this._hitTest(
-				Point.read(arguments),
-				HitResult.getOptions(arguments));
-	}
-
-	function hitTestAll() {
-		var point = Point.read(arguments),
-			options = HitResult.getOptions(arguments),
-			callback = options.match,
-			results = [];
-		options = Base.set({}, options, {
-			match: function(hit) {
-				if (!callback || callback(hit))
-					results.push(hit);
-			}
-		});
-		this._hitTest(point, options);
-		return results;
-	}
-
-	function hitTestChildren(point, options, viewMatrix, _exclude) {
-		var children = this._children;
-		if (children) {
-			for (var i = children.length - 1; i >= 0; i--) {
-				var child = children[i];
-				var res = child !== _exclude && child._hitTest(point, options,
-						viewMatrix);
-				if (res)
-					return res;
-			}
-		}
-		return null;
-	}
-
-	Project.inject({
-		hitTest: hitTest,
-		hitTestAll: hitTestAll,
-		_hitTest: hitTestChildren
-	});
-
-	return {
-		hitTest: hitTest,
-		hitTestAll: hitTestAll,
-		_hitTestChildren: hitTestChildren,
-	};
-}, {
-
-	_hitTest: function(point, options, parentViewMatrix) {
-		if (this._locked || !this._visible || this._guide && !options.guides
-				|| this.isEmpty()) {
-			return null;
-		}
-
-		var matrix = this._matrix,
-			viewMatrix = parentViewMatrix
-					? parentViewMatrix.appended(matrix)
-					: this.getGlobalMatrix().prepend(this.getView()._matrix),
-			strokeMatrix = this.getStrokeScaling()
-					? null
-					: viewMatrix.inverted()._shiftless(),
-			tolerance = Math.max(options.tolerance, 1e-6),
-			tolerancePadding = options._tolerancePadding = new Size(
-					Path._getStrokePadding(tolerance, strokeMatrix));
-		point = matrix._inverseTransform(point);
-		if (!point || !this._children &&
-			!this.getBounds({ internal: true, stroke: true, handle: true })
-				.expand(tolerancePadding.multiply(2))._containsPoint(point)) {
-			return null;
-		}
-
-		var checkSelf = !(options.guides && !this._guide
-				|| options.selected && !this.isSelected()
-				|| options.type && options.type !== Base.hyphenate(this._class)
-				|| options.class && !(this instanceof options.class)),
-			callback = options.match,
-			that = this,
-			bounds,
-			res;
-
-		function match(hit) {
-			return !callback || hit && callback(hit) ? hit : null;
-		}
-
-		function checkBounds(type, part) {
-			var pt = bounds['get' + part]();
-			if (point.subtract(pt).divide(tolerancePadding).length <= 1) {
-				return new HitResult(type, that,
-						{ name: Base.hyphenate(part), point: pt });
-			}
-		}
-
-		if (checkSelf && (options.center || options.bounds) && this._parent) {
-			bounds = this.getInternalBounds();
-			if (options.center) {
-				res = checkBounds('center', 'Center');
-			}
-			if (!res && options.bounds) {
-				var points = [
-					'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
-					'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'
-				];
-				for (var i = 0; i < 8 && !res; i++) {
-					res = checkBounds('bounds', points[i]);
-				}
-			}
-			res = match(res);
-		}
-
-		if (!res) {
-			res = this._hitTestChildren(point, options, viewMatrix)
-				|| checkSelf
-					&& match(this._hitTestSelf(point, options, viewMatrix,
-						strokeMatrix))
-				|| null;
-		}
-		if (res && res.point) {
-			res.point = matrix.transform(res.point);
-		}
-		return res;
-	},
-
-	_hitTestSelf: function(point, options) {
-		if (options.fill && this.hasFill() && this._contains(point))
-			return new HitResult('fill', this);
-	},
-
-	matches: function(name, compare) {
-		function matchObject(obj1, obj2) {
-			for (var i in obj1) {
-				if (obj1.hasOwnProperty(i)) {
-					var val1 = obj1[i],
-						val2 = obj2[i];
-					if (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {
-						if (!matchObject(val1, val2))
-							return false;
-					} else if (!Base.equals(val1, val2)) {
-						return false;
-					}
-				}
-			}
-			return true;
-		}
-		var type = typeof name;
-		if (type === 'object') {
-			for (var key in name) {
-				if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
-					return false;
-			}
-			return true;
-		} else if (type === 'function') {
-			return name(this);
-		} else if (name === 'match') {
-			return compare(this);
-		} else {
-			var value = /^(empty|editable)$/.test(name)
-					? this['is' + Base.capitalize(name)]()
-					: name === 'type'
-						? Base.hyphenate(this._class)
-						: this[name];
-			if (name === 'class') {
-				if (typeof compare === 'function')
-					return this instanceof compare;
-				value = this._class;
-			}
-			if (typeof compare === 'function') {
-				return !!compare(value);
-			} else if (compare) {
-				if (compare.test) {
-					return compare.test(value);
-				} else if (Base.isPlainObject(compare)) {
-					return matchObject(compare, value);
-				}
-			}
-			return Base.equals(value, compare);
-		}
-	},
-
-	getItems: function(options) {
-		return Item._getItems(this, options, this._matrix);
-	},
-
-	getItem: function(options) {
-		return Item._getItems(this, options, this._matrix, null, true)[0]
-				|| null;
-	},
-
-	statics: {
-		_getItems: function _getItems(item, options, matrix, param, firstOnly) {
-			if (!param) {
-				var obj = typeof options === 'object' && options,
-					overlapping = obj && obj.overlapping,
-					inside = obj && obj.inside,
-					bounds = overlapping || inside,
-					rect = bounds && Rectangle.read([bounds]);
-				param = {
-					items: [],
-					recursive: obj && obj.recursive !== false,
-					inside: !!inside,
-					overlapping: !!overlapping,
-					rect: rect,
-					path: overlapping && new Path.Rectangle({
-						rectangle: rect,
-						insert: false
-					})
-				};
-				if (obj) {
-					options = Base.filter({}, options, {
-						recursive: true, inside: true, overlapping: true
-					});
-				}
-			}
-			var children = item._children,
-				items = param.items,
-				rect = param.rect;
-			matrix = rect && (matrix || new Matrix());
-			for (var i = 0, l = children && children.length; i < l; i++) {
-				var child = children[i],
-					childMatrix = matrix && matrix.appended(child._matrix),
-					add = true;
-				if (rect) {
-					var bounds = child.getBounds(childMatrix);
-					if (!rect.intersects(bounds))
-						continue;
-					if (!(rect.contains(bounds)
-							|| param.overlapping && (bounds.contains(rect)
-								|| param.path.intersects(child, childMatrix))))
-						add = false;
-				}
-				if (add && child.matches(options)) {
-					items.push(child);
-					if (firstOnly)
-						break;
-				}
-				if (param.recursive !== false) {
-					_getItems(child, options, childMatrix, param, firstOnly);
-				}
-				if (firstOnly && items.length > 0)
-					break;
-			}
-			return items;
-		}
-	}
-}, {
-
-	importJSON: function(json) {
-		var res = Base.importJSON(json, this);
-		return res !== this ? this.addChild(res) : res;
-	},
-
-	addChild: function(item, _preserve) {
-		return this.insertChild(undefined, item, _preserve);
-	},
-
-	insertChild: function(index, item, _preserve) {
-		var res = item ? this.insertChildren(index, [item], _preserve) : null;
-		return res && res[0];
-	},
-
-	addChildren: function(items, _preserve) {
-		return this.insertChildren(this._children.length, items, _preserve);
-	},
-
-	insertChildren: function(index, items, _preserve, _proto) {
-		var children = this._children;
-		if (children && items && items.length > 0) {
-			items = Array.prototype.slice.apply(items);
-			for (var i = items.length - 1; i >= 0; i--) {
-				var item = items[i];
-				if (!item || _proto && !(item instanceof _proto)) {
-					items.splice(i, 1);
-				} else {
-					item._remove(false, true);
-				}
-			}
-			Base.splice(children, items, index, 0);
-			var project = this._project,
-				notifySelf = project._changes;
-			for (var i = 0, l = items.length; i < l; i++) {
-				var item = items[i],
-					name = item._name;
-				item._parent = this;
-				item._setProject(project, true);
-				if (name)
-					item.setName(name);
-				if (notifySelf)
-					this._changed(5);
-			}
-			this._changed(11);
-		} else {
-			items = null;
-		}
-		return items;
-	},
-
-	_insertItem: '#insertChild',
-
-	_insertAt: function(item, offset, _preserve) {
-		var res = this;
-		if (res !== item) {
-			var owner = item && item._getOwner();
-			if (owner) {
-				res._remove(false, true);
-				owner._insertItem(item._index + offset, res, _preserve);
-			} else {
-				res = null;
-			}
-		}
-		return res;
-	},
-
-	insertAbove: function(item, _preserve) {
-		return this._insertAt(item, 1, _preserve);
-	},
-
-	insertBelow: function(item, _preserve) {
-		return this._insertAt(item, 0, _preserve);
-	},
-
-	sendToBack: function() {
-		var owner = this._getOwner();
-		return owner ? owner._insertItem(0, this) : null;
-	},
-
-	bringToFront: function() {
-		var owner = this._getOwner();
-		return owner ? owner._insertItem(undefined, this) : null;
-	},
-
-	appendTop: '#addChild',
-
-	appendBottom: function(item) {
-		return this.insertChild(0, item);
-	},
-
-	moveAbove: '#insertAbove',
-
-	moveBelow: '#insertBelow',
-
-	copyTo: function(owner) {
-		return owner._insertItem(undefined, this.clone(false));
-	},
-
-	reduce: function(options) {
-		var children = this._children;
-		if (children && children.length === 1) {
-			var child = children[0].reduce(options);
-			if (this._parent) {
-				child.insertAbove(this);
-				this.remove();
-			} else {
-				child.remove();
-			}
-			return child;
-		}
-		return this;
-	},
-
-	_removeNamed: function() {
-		var owner = this._getOwner();
-		if (owner) {
-			var children = owner._children,
-				namedChildren = owner._namedChildren,
-				name = this._name,
-				namedArray = namedChildren[name],
-				index = namedArray ? namedArray.indexOf(this) : -1;
-			if (index !== -1) {
-				if (children[name] == this)
-					delete children[name];
-				namedArray.splice(index, 1);
-				if (namedArray.length) {
-					children[name] = namedArray[0];
-				} else {
-					delete namedChildren[name];
-				}
-			}
-		}
-	},
-
-	_remove: function(notifySelf, notifyParent) {
-		var owner = this._getOwner(),
-			project = this._project,
-			index = this._index;
-		if (owner) {
-			if (index != null) {
-				if (project._activeLayer === this)
-					project._activeLayer = this.getNextSibling()
-							|| this.getPreviousSibling();
-				Base.splice(owner._children, null, index, 1);
-			}
-			if (this._name)
-				this._removeNamed();
-			this._installEvents(false);
-			if (notifySelf && project._changes)
-				this._changed(5);
-			if (notifyParent)
-				owner._changed(11, this);
-			this._parent = null;
-			return true;
-		}
-		return false;
-	},
-
-	remove: function() {
-		return this._remove(true, true);
-	},
-
-	replaceWith: function(item) {
-		var ok = item && item.insertBelow(this);
-		if (ok)
-			this.remove();
-		return ok;
-	},
-
-	removeChildren: function(start, end) {
-		if (!this._children)
-			return null;
-		start = start || 0;
-		end = Base.pick(end, this._children.length);
-		var removed = Base.splice(this._children, null, start, end - start);
-		for (var i = removed.length - 1; i >= 0; i--) {
-			removed[i]._remove(true, false);
-		}
-		if (removed.length > 0)
-			this._changed(11);
-		return removed;
-	},
-
-	clear: '#removeChildren',
-
-	reverseChildren: function() {
-		if (this._children) {
-			this._children.reverse();
-			for (var i = 0, l = this._children.length; i < l; i++)
-				this._children[i]._index = i;
-			this._changed(11);
-		}
-	},
-
-	isEmpty: function() {
-		return !this._children || this._children.length === 0;
-	},
-
-	isEditable: function() {
-		var item = this;
-		while (item) {
-			if (!item._visible || item._locked)
-				return false;
-			item = item._parent;
-		}
-		return true;
-	},
-
-	hasFill: function() {
-		return this.getStyle().hasFill();
-	},
-
-	hasStroke: function() {
-		return this.getStyle().hasStroke();
-	},
-
-	hasShadow: function() {
-		return this.getStyle().hasShadow();
-	},
-
-	_getOrder: function(item) {
-		function getList(item) {
-			var list = [];
-			do {
-				list.unshift(item);
-			} while (item = item._parent);
-			return list;
-		}
-		var list1 = getList(this),
-			list2 = getList(item);
-		for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {
-			if (list1[i] != list2[i]) {
-				return list1[i]._index < list2[i]._index ? 1 : -1;
-			}
-		}
-		return 0;
-	},
-
-	hasChildren: function() {
-		return this._children && this._children.length > 0;
-	},
-
-	isInserted: function() {
-		return this._parent ? this._parent.isInserted() : false;
-	},
-
-	isAbove: function(item) {
-		return this._getOrder(item) === -1;
-	},
-
-	isBelow: function(item) {
-		return this._getOrder(item) === 1;
-	},
-
-	isParent: function(item) {
-		return this._parent === item;
-	},
-
-	isChild: function(item) {
-		return item && item._parent === this;
-	},
-
-	isDescendant: function(item) {
-		var parent = this;
-		while (parent = parent._parent) {
-			if (parent === item)
-				return true;
-		}
-		return false;
-	},
-
-	isAncestor: function(item) {
-		return item ? item.isDescendant(this) : false;
-	},
-
-	isSibling: function(item) {
-		return this._parent === item._parent;
-	},
-
-	isGroupedWith: function(item) {
-		var parent = this._parent;
-		while (parent) {
-			if (parent._parent
-				&& /^(Group|Layer|CompoundPath)$/.test(parent._class)
-				&& item.isDescendant(parent))
-					return true;
-			parent = parent._parent;
-		}
-		return false;
-	},
-
-}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
-	var rotate = key === 'rotate';
-	this[key] = function() {
-		var value = (rotate ? Base : Point).read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		return this.transform(new Matrix()[key](value,
-				center || this.getPosition(true)));
-	};
-}, {
-	translate: function() {
-		var mx = new Matrix();
-		return this.transform(mx.translate.apply(mx, arguments));
-	},
-
-	transform: function(matrix, _applyMatrix, _applyRecursively,
-			_setApplyMatrix) {
-		if (matrix && matrix.isIdentity())
-			matrix = null;
-		var _matrix = this._matrix,
-			applyMatrix = (_applyMatrix || this._applyMatrix)
-					&& ((!_matrix.isIdentity() || matrix)
-						|| _applyMatrix && _applyRecursively && this._children);
-		if (!matrix && !applyMatrix)
-			return this;
-		if (matrix) {
-			if (!matrix.isInvertible() && _matrix.isInvertible())
-				_matrix._backup = _matrix.getValues();
-			_matrix.prepend(matrix);
-		}
-		if (applyMatrix = applyMatrix && this._transformContent(_matrix,
-					_applyRecursively, _setApplyMatrix)) {
-			var pivot = this._pivot,
-				style = this._style,
-				fillColor = style.getFillColor(true),
-				strokeColor = style.getStrokeColor(true);
-			if (pivot)
-				_matrix._transformPoint(pivot, pivot, true);
-			if (fillColor)
-				fillColor.transform(_matrix);
-			if (strokeColor)
-				strokeColor.transform(_matrix);
-			_matrix.reset(true);
-			if (_setApplyMatrix && this._canApplyMatrix)
-				this._applyMatrix = true;
-		}
-		var bounds = this._bounds,
-			position = this._position;
-		this._changed(9);
-		var decomp = bounds && matrix && matrix.decompose();
-		if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
-			for (var key in bounds) {
-				var cache = bounds[key];
-				if (applyMatrix || !cache.internal) {
-					var rect = cache.rect;
-					matrix._transformBounds(rect, rect);
-				}
-			}
-			var getter = this._boundsGetter,
-				rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
-			if (rect)
-				this._position = rect.getCenter(true);
-			this._bounds = bounds;
-		} else if (matrix && position) {
-			this._position = matrix._transformPoint(position, position);
-		}
-		return this;
-	},
-
-	_transformContent: function(matrix, applyRecursively, setApplyMatrix) {
-		var children = this._children;
-		if (children) {
-			for (var i = 0, l = children.length; i < l; i++)
-				children[i].transform(matrix, true, applyRecursively,
-						setApplyMatrix);
-			return true;
-		}
-	},
-
-	globalToLocal: function() {
-		return this.getGlobalMatrix(true)._inverseTransform(
-				Point.read(arguments));
-	},
-
-	localToGlobal: function() {
-		return this.getGlobalMatrix(true)._transformPoint(
-				Point.read(arguments));
-	},
-
-	parentToLocal: function() {
-		return this._matrix._inverseTransform(Point.read(arguments));
-	},
-
-	localToParent: function() {
-		return this._matrix._transformPoint(Point.read(arguments));
-	},
-
-	fitBounds: function(rectangle, fill) {
-		rectangle = Rectangle.read(arguments);
-		var bounds = this.getBounds(),
-			itemRatio = bounds.height / bounds.width,
-			rectRatio = rectangle.height / rectangle.width,
-			scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
-					? rectangle.width / bounds.width
-					: rectangle.height / bounds.height,
-			newBounds = new Rectangle(new Point(),
-					new Size(bounds.width * scale, bounds.height * scale));
-		newBounds.setCenter(rectangle.getCenter());
-		this.setBounds(newBounds);
-	}
-}), {
-
-	_setStyles: function(ctx, param, viewMatrix) {
-		var style = this._style;
-		if (style.hasFill()) {
-			ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx);
-		}
-		if (style.hasStroke()) {
-			ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx);
-			ctx.lineWidth = style.getStrokeWidth();
-			var strokeJoin = style.getStrokeJoin(),
-				strokeCap = style.getStrokeCap(),
-				miterLimit = style.getMiterLimit();
-			if (strokeJoin)
-				ctx.lineJoin = strokeJoin;
-			if (strokeCap)
-				ctx.lineCap = strokeCap;
-			if (miterLimit)
-				ctx.miterLimit = miterLimit;
-			if (paper.support.nativeDash) {
-				var dashArray = style.getDashArray(),
-					dashOffset = style.getDashOffset();
-				if (dashArray && dashArray.length) {
-					if ('setLineDash' in ctx) {
-						ctx.setLineDash(dashArray);
-						ctx.lineDashOffset = dashOffset;
-					} else {
-						ctx.mozDash = dashArray;
-						ctx.mozDashOffset = dashOffset;
-					}
-				}
-			}
-		}
-		if (style.hasShadow()) {
-			var pixelRatio = param.pixelRatio || 1,
-				mx = viewMatrix._shiftless().prepend(
-					new Matrix().scale(pixelRatio, pixelRatio)),
-				blur = mx.transform(new Point(style.getShadowBlur(), 0)),
-				offset = mx.transform(this.getShadowOffset());
-			ctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);
-			ctx.shadowBlur = blur.getLength();
-			ctx.shadowOffsetX = offset.x;
-			ctx.shadowOffsetY = offset.y;
-		}
-	},
-
-	draw: function(ctx, param, parentStrokeMatrix) {
-		var updateVersion = this._updateVersion = this._project._updateVersion;
-		if (!this._visible || this._opacity === 0)
-			return;
-		var matrices = param.matrices,
-			viewMatrix = param.viewMatrix,
-			matrix = this._matrix,
-			globalMatrix = matrices[matrices.length - 1].appended(matrix);
-		if (!globalMatrix.isInvertible())
-			return;
-
-		viewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)
-				: globalMatrix;
-
-		matrices.push(globalMatrix);
-		if (param.updateMatrix) {
-			globalMatrix._updateVersion = updateVersion;
-			this._globalMatrix = globalMatrix;
-		}
-
-		var blendMode = this._blendMode,
-			opacity = this._opacity,
-			normalBlend = blendMode === 'normal',
-			nativeBlend = BlendMode.nativeModes[blendMode],
-			direct = normalBlend && opacity === 1
-					|| param.dontStart
-					|| param.clip
-					|| (nativeBlend || normalBlend && opacity < 1)
-						&& this._canComposite(),
-			pixelRatio = param.pixelRatio || 1,
-			mainCtx, itemOffset, prevOffset;
-		if (!direct) {
-			var bounds = this.getStrokeBounds(viewMatrix);
-			if (!bounds.width || !bounds.height)
-				return;
-			prevOffset = param.offset;
-			itemOffset = param.offset = bounds.getTopLeft().floor();
-			mainCtx = ctx;
-			ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)
-					.multiply(pixelRatio));
-			if (pixelRatio !== 1)
-				ctx.scale(pixelRatio, pixelRatio);
-		}
-		ctx.save();
-		var strokeMatrix = parentStrokeMatrix
-				? parentStrokeMatrix.appended(matrix)
-				: this._canScaleStroke && !this.getStrokeScaling(true)
-					&& viewMatrix,
-			clip = !direct && param.clipItem,
-			transform = !strokeMatrix || clip;
-		if (direct) {
-			ctx.globalAlpha = opacity;
-			if (nativeBlend)
-				ctx.globalCompositeOperation = blendMode;
-		} else if (transform) {
-			ctx.translate(-itemOffset.x, -itemOffset.y);
-		}
-		if (transform) {
-			(direct ? matrix : viewMatrix).applyToContext(ctx);
-		}
-		if (clip) {
-			param.clipItem.draw(ctx, param.extend({ clip: true }));
-		}
-		if (strokeMatrix) {
-			ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
-			var offset = param.offset;
-			if (offset)
-				ctx.translate(-offset.x, -offset.y);
-		}
-		this._draw(ctx, param, viewMatrix, strokeMatrix);
-		ctx.restore();
-		matrices.pop();
-		if (param.clip && !param.dontFinish)
-			ctx.clip();
-		if (!direct) {
-			BlendMode.process(blendMode, ctx, mainCtx, opacity,
-					itemOffset.subtract(prevOffset).multiply(pixelRatio));
-			CanvasProvider.release(ctx);
-			param.offset = prevOffset;
-		}
-	},
-
-	_isUpdated: function(updateVersion) {
-		var parent = this._parent;
-		if (parent instanceof CompoundPath)
-			return parent._isUpdated(updateVersion);
-		var updated = this._updateVersion === updateVersion;
-		if (!updated && parent && parent._visible
-				&& parent._isUpdated(updateVersion)) {
-			this._updateVersion = updateVersion;
-			updated = true;
-		}
-		return updated;
-	},
-
-	_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {
-		var selection = this._selection,
-			itemSelected = selection & 1,
-			boundsSelected = selection & 2
-					|| itemSelected && this._selectBounds,
-			positionSelected = selection & 4;
-		if (!this._drawSelected)
-			itemSelected = false;
-		if ((itemSelected || boundsSelected || positionSelected)
-				&& this._isUpdated(updateVersion)) {
-			var layer,
-				color = this.getSelectedColor(true) || (layer = this.getLayer())
-					&& layer.getSelectedColor(true),
-				mx = matrix.appended(this.getGlobalMatrix(true)),
-				half = size / 2;
-			ctx.strokeStyle = ctx.fillStyle = color
-					? color.toCanvasStyle(ctx) : '#009dec';
-			if (itemSelected)
-				this._drawSelected(ctx, mx, selectionItems);
-			if (positionSelected) {
-				var point = this.getPosition(true),
-					x = point.x,
-					y = point.y;
-				ctx.beginPath();
-				ctx.arc(x, y, half, 0, Math.PI * 2, true);
-				ctx.stroke();
-				var deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],
-					start = half,
-					end = size + 1;
-				for (var i = 0; i < 4; i++) {
-					var delta = deltas[i],
-						dx = delta[0],
-						dy = delta[1];
-					ctx.moveTo(x + dx * start, y + dy * start);
-					ctx.lineTo(x + dx * end, y + dy * end);
-					ctx.stroke();
-				}
-			}
-			if (boundsSelected) {
-				var coords = mx._transformCorners(this.getInternalBounds());
-				ctx.beginPath();
-				for (var i = 0; i < 8; i++) {
-					ctx[i === 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);
-				}
-				ctx.closePath();
-				ctx.stroke();
-				for (var i = 0; i < 8; i++) {
-					ctx.fillRect(coords[i] - half, coords[++i] - half,
-							size, size);
-				}
-			}
-		}
-	},
-
-	_canComposite: function() {
-		return false;
-	}
-}, Base.each(['down', 'drag', 'up', 'move'], function(key) {
-	this['removeOn' + Base.capitalize(key)] = function() {
-		var hash = {};
-		hash[key] = true;
-		return this.removeOn(hash);
-	};
-}, {
-
-	removeOn: function(obj) {
-		for (var name in obj) {
-			if (obj[name]) {
-				var key = 'mouse' + name,
-					project = this._project,
-					sets = project._removeSets = project._removeSets || {};
-				sets[key] = sets[key] || {};
-				sets[key][this._id] = this;
-			}
-		}
-		return this;
-	}
-}));
-
-var Group = Item.extend({
-	_class: 'Group',
-	_selectBounds: false,
-	_selectChildren: true,
-	_serializeFields: {
-		children: []
-	},
-
-	initialize: function Group(arg) {
-		this._children = [];
-		this._namedChildren = {};
-		if (!this._initialize(arg))
-			this.addChildren(Array.isArray(arg) ? arg : arguments);
-	},
-
-	_changed: function _changed(flags) {
-		_changed.base.call(this, flags);
-		if (flags & 1026) {
-			this._clipItem = undefined;
-		}
-	},
-
-	_getClipItem: function() {
-		var clipItem = this._clipItem;
-		if (clipItem === undefined) {
-			clipItem = null;
-			var children = this._children;
-			for (var i = 0, l = children.length; i < l; i++) {
-				if (children[i]._clipMask) {
-					clipItem = children[i];
-					break;
-				}
-			}
-			this._clipItem = clipItem;
-		}
-		return clipItem;
-	},
-
-	isClipped: function() {
-		return !!this._getClipItem();
-	},
-
-	setClipped: function(clipped) {
-		var child = this.getFirstChild();
-		if (child)
-			child.setClipMask(clipped);
-	},
-
-	_getBounds: function _getBounds(matrix, options) {
-		var clipItem = this._getClipItem();
-		return clipItem
-			? clipItem._getCachedBounds(
-				matrix && matrix.appended(clipItem._matrix),
-				Base.set({}, options, { stroke: false }))
-			: _getBounds.base.call(this, matrix, options);
-	},
-
-	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
-		var clipItem = this._getClipItem();
-		return (!clipItem || clipItem.contains(point))
-				&& _hitTestChildren.base.call(this, point, options, viewMatrix,
-					clipItem);
-	},
-
-	_draw: function(ctx, param) {
-		var clip = param.clip,
-			clipItem = !clip && this._getClipItem();
-		param = param.extend({ clipItem: clipItem, clip: false });
-		if (clip) {
-			ctx.beginPath();
-			param.dontStart = param.dontFinish = true;
-		} else if (clipItem) {
-			clipItem.draw(ctx, param.extend({ clip: true }));
-		}
-		var children = this._children;
-		for (var i = 0, l = children.length; i < l; i++) {
-			var item = children[i];
-			if (item !== clipItem)
-				item.draw(ctx, param);
-		}
-	}
-});
-
-var Layer = Group.extend({
-	_class: 'Layer',
-
-	initialize: function Layer() {
-		Group.apply(this, arguments);
-	},
-
-	_getOwner: function() {
-		return this._parent || this._index != null && this._project;
-	},
-
-	isInserted: function isInserted() {
-		return this._parent ? isInserted.base.call(this) : this._index != null;
-	},
-
-	activate: function() {
-		this._project._activeLayer = this;
-	},
-
-	_hitTestSelf: function() {
-	}
-});
-
-var Shape = Item.extend({
-	_class: 'Shape',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_canScaleStroke: true,
-	_serializeFields: {
-		type: null,
-		size: null,
-		radius: null
-	},
-
-	initialize: function Shape(props) {
-		this._initialize(props);
-	},
-
-	_equals: function(item) {
-		return this._type === item._type
-			&& this._size.equals(item._size)
-			&& Base.equals(this._radius, item._radius);
-	},
-
-	copyContent: function(source) {
-		this.setType(source._type);
-		this.setSize(source._size);
-		this.setRadius(source._radius);
-	},
-
-	getType: function() {
-		return this._type;
-	},
-
-	setType: function(type) {
-		this._type = type;
-	},
-
-	getShape: '#getType',
-	setShape: '#setType',
-
-	getSize: function() {
-		var size = this._size;
-		return new LinkedSize(size.width, size.height, this, 'setSize');
-	},
-
-	setSize: function() {
-		var size = Size.read(arguments);
-		if (!this._size) {
-			this._size = size.clone();
-		} else if (!this._size.equals(size)) {
-			var type = this._type,
-				width = size.width,
-				height = size.height;
-			if (type === 'rectangle') {
-				var radius = Size.min(this._radius, size.divide(2));
-				this._radius.set(radius.width, radius.height);
-			} else if (type === 'circle') {
-				width = height = (width + height) / 2;
-				this._radius = width / 2;
-			} else if (type === 'ellipse') {
-				this._radius.set(width / 2, height / 2);
-			}
-			this._size.set(width, height);
-			this._changed(9);
-		}
-	},
-
-	getRadius: function() {
-		var rad = this._radius;
-		return this._type === 'circle'
-				? rad
-				: new LinkedSize(rad.width, rad.height, this, 'setRadius');
-	},
-
-	setRadius: function(radius) {
-		var type = this._type;
-		if (type === 'circle') {
-			if (radius === this._radius)
-				return;
-			var size = radius * 2;
-			this._radius = radius;
-			this._size.set(size, size);
-		} else {
-			radius = Size.read(arguments);
-			if (!this._radius) {
-				this._radius = radius.clone();
-			} else {
-				if (this._radius.equals(radius))
-					return;
-				this._radius.set(radius.width, radius.height);
-				if (type === 'rectangle') {
-					var size = Size.max(this._size, radius.multiply(2));
-					this._size.set(size.width, size.height);
-				} else if (type === 'ellipse') {
-					this._size.set(radius.width * 2, radius.height * 2);
-				}
-			}
-		}
-		this._changed(9);
-	},
-
-	isEmpty: function() {
-		return false;
-	},
-
-	toPath: function(insert) {
-		var path = new Path[Base.capitalize(this._type)]({
-			center: new Point(),
-			size: this._size,
-			radius: this._radius,
-			insert: false
-		});
-		path.copyAttributes(this);
-		if (paper.settings.applyMatrix)
-			path.setApplyMatrix(true);
-		if (insert === undefined || insert)
-			path.insertAbove(this);
-		return path;
-	},
-
-	toShape: '#clone',
-
-	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
-		var style = this._style,
-			hasFill = style.hasFill(),
-			hasStroke = style.hasStroke(),
-			dontPaint = param.dontFinish || param.clip,
-			untransformed = !strokeMatrix;
-		if (hasFill || hasStroke || dontPaint) {
-			var type = this._type,
-				radius = this._radius,
-				isCircle = type === 'circle';
-			if (!param.dontStart)
-				ctx.beginPath();
-			if (untransformed && isCircle) {
-				ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
-			} else {
-				var rx = isCircle ? radius : radius.width,
-					ry = isCircle ? radius : radius.height,
-					size = this._size,
-					width = size.width,
-					height = size.height;
-				if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
-					ctx.rect(-width / 2, -height / 2, width, height);
-				} else {
-					var x = width / 2,
-						y = height / 2,
-						kappa = 1 - 0.5522847498307936,
-						cx = rx * kappa,
-						cy = ry * kappa,
-						c = [
-							-x, -y + ry,
-							-x, -y + cy,
-							-x + cx, -y,
-							-x + rx, -y,
-							x - rx, -y,
-							x - cx, -y,
-							x, -y + cy,
-							x, -y + ry,
-							x, y - ry,
-							x, y - cy,
-							x - cx, y,
-							x - rx, y,
-							-x + rx, y,
-							-x + cx, y,
-							-x, y - cy,
-							-x, y - ry
-						];
-					if (strokeMatrix)
-						strokeMatrix.transform(c, c, 32);
-					ctx.moveTo(c[0], c[1]);
-					ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);
-					if (x !== rx)
-						ctx.lineTo(c[8], c[9]);
-					ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);
-					if (y !== ry)
-						ctx.lineTo(c[16], c[17]);
-					ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);
-					if (x !== rx)
-						ctx.lineTo(c[24], c[25]);
-					ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);
-				}
-			}
-			ctx.closePath();
-		}
-		if (!dontPaint && (hasFill || hasStroke)) {
-			this._setStyles(ctx, param, viewMatrix);
-			if (hasFill) {
-				ctx.fill(style.getFillRule());
-				ctx.shadowColor = 'rgba(0,0,0,0)';
-			}
-			if (hasStroke)
-				ctx.stroke();
-		}
-	},
-
-	_canComposite: function() {
-		return !(this.hasFill() && this.hasStroke());
-	},
-
-	_getBounds: function(matrix, options) {
-		var rect = new Rectangle(this._size).setCenter(0, 0),
-			style = this._style,
-			strokeWidth = options.stroke && style.hasStroke()
-					&& style.getStrokeWidth();
-		if (matrix)
-			rect = matrix._transformBounds(rect);
-		return strokeWidth
-				? rect.expand(Path._getStrokePadding(strokeWidth,
-					this._getStrokeMatrix(matrix, options)))
-				: rect;
-	}
-},
-new function() {
-	function getCornerCenter(that, point, expand) {
-		var radius = that._radius;
-		if (!radius.isZero()) {
-			var halfSize = that._size.divide(2);
-			for (var i = 0; i < 4; i++) {
-				var dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),
-					corner = dir.multiply(halfSize),
-					center = corner.subtract(dir.multiply(radius)),
-					rect = new Rectangle(corner, center);
-				if ((expand ? rect.expand(expand) : rect).contains(point))
-					return center;
-			}
-		}
-	}
-
-	function isOnEllipseStroke(point, radius, padding, quadrant) {
-		var vector = point.divide(radius);
-		return (!quadrant || vector.quadrant === quadrant) &&
-				vector.subtract(vector.normalize()).multiply(radius)
-					.divide(padding).length <= 1;
-	}
-
-	return {
-		_contains: function _contains(point) {
-			if (this._type === 'rectangle') {
-				var center = getCornerCenter(this, point);
-				return center
-						? point.subtract(center).divide(this._radius)
-							.getLength() <= 1
-						: _contains.base.call(this, point);
-			} else {
-				return point.divide(this.size).getLength() <= 0.5;
-			}
-		},
-
-		_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,
-				strokeMatrix) {
-			var hit = false,
-				style = this._style,
-				hitStroke = options.stroke && style.hasStroke(),
-				hitFill = options.fill && style.hasFill();
-			if (hitStroke || hitFill) {
-				var type = this._type,
-					radius = this._radius,
-					strokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,
-					strokePadding = options._tolerancePadding.add(
-						Path._getStrokePadding(strokeRadius,
-							!style.getStrokeScaling() && strokeMatrix));
-				if (type === 'rectangle') {
-					var padding = strokePadding.multiply(2),
-						center = getCornerCenter(this, point, padding);
-					if (center) {
-						hit = isOnEllipseStroke(point.subtract(center), radius,
-								strokePadding, center.getQuadrant());
-					} else {
-						var rect = new Rectangle(this._size).setCenter(0, 0),
-							outer = rect.expand(padding),
-							inner = rect.expand(padding.negate());
-						hit = outer._containsPoint(point)
-								&& !inner._containsPoint(point);
-					}
-				} else {
-					hit = isOnEllipseStroke(point, radius, strokePadding);
-				}
-			}
-			return hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)
-					: _hitTestSelf.base.apply(this, arguments);
-		}
-	};
-}, {
-
-statics: new function() {
-	function createShape(type, point, size, radius, args) {
-		var item = new Shape(Base.getNamed(args));
-		item._type = type;
-		item._size = size;
-		item._radius = radius;
-		return item.translate(point);
-	}
-
-	return {
-		Circle: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				radius = Base.readNamed(arguments, 'radius');
-			return createShape('circle', center, new Size(radius * 2), radius,
-					arguments);
-		},
-
-		Rectangle: function() {
-			var rect = Rectangle.readNamed(arguments, 'rectangle'),
-				radius = Size.min(Size.readNamed(arguments, 'radius'),
-						rect.getSize(true).divide(2));
-			return createShape('rectangle', rect.getCenter(true),
-					rect.getSize(true), radius, arguments);
-		},
-
-		Ellipse: function() {
-			var ellipse = Shape._readEllipse(arguments),
-				radius = ellipse.radius;
-			return createShape('ellipse', ellipse.center, radius.multiply(2),
-					radius, arguments);
-		},
-
-		_readEllipse: function(args) {
-			var center,
-				radius;
-			if (Base.hasNamed(args, 'radius')) {
-				center = Point.readNamed(args, 'center');
-				radius = Size.readNamed(args, 'radius');
-			} else {
-				var rect = Rectangle.readNamed(args, 'rectangle');
-				center = rect.getCenter(true);
-				radius = rect.getSize(true).divide(2);
-			}
-			return { center: center, radius: radius };
-		}
-	};
-}});
-
-var Raster = Item.extend({
-	_class: 'Raster',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_boundsOptions: { stroke: false, handle: false },
-	_serializeFields: {
-		crossOrigin: null,
-		source: null
-	},
-
-	initialize: function Raster(object, position) {
-		if (!this._initialize(object,
-				position !== undefined && Point.read(arguments, 1))) {
-			var image = typeof object === 'string'
-					? document.getElementById(object) : object;
-			if (image) {
-				this.setImage(image);
-			} else {
-				this.setSource(object);
-			}
-		}
-		if (!this._size) {
-			this._size = new Size();
-			this._loaded = false;
-		}
-	},
-
-	_equals: function(item) {
-		return this.getSource() === item.getSource();
-	},
-
-	copyContent: function(source) {
-		var image = source._image,
-			canvas = source._canvas;
-		if (image) {
-			this._setImage(image);
-		} else if (canvas) {
-			var copyCanvas = CanvasProvider.getCanvas(source._size);
-			copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
-			this._setImage(copyCanvas);
-		}
-		this._crossOrigin = source._crossOrigin;
-	},
-
-	getSize: function() {
-		var size = this._size;
-		return new LinkedSize(size ? size.width : 0, size ? size.height : 0,
-				this, 'setSize');
-	},
-
-	setSize: function() {
-		var size = Size.read(arguments);
-		if (!size.equals(this._size)) {
-			if (size.width > 0 && size.height > 0) {
-				var element = this.getElement();
-				this._setImage(CanvasProvider.getCanvas(size));
-				if (element)
-					this.getContext(true).drawImage(element, 0, 0,
-							size.width, size.height);
-			} else {
-				if (this._canvas)
-					CanvasProvider.release(this._canvas);
-				this._size = size.clone();
-			}
-		}
-	},
-
-	getWidth: function() {
-		return this._size ? this._size.width : 0;
-	},
-
-	setWidth: function(width) {
-		this.setSize(width, this.getHeight());
-	},
-
-	getHeight: function() {
-		return this._size ? this._size.height : 0;
-	},
-
-	setHeight: function(height) {
-		this.setSize(this.getWidth(), height);
-	},
-
-	getLoaded: function() {
-		return this._loaded;
-	},
-
-	isEmpty: function() {
-		var size = this._size;
-		return !size || size.width === 0 && size.height === 0;
-	},
-
-	getResolution: function() {
-		var matrix = this._matrix,
-			orig = new Point(0, 0).transform(matrix),
-			u = new Point(1, 0).transform(matrix).subtract(orig),
-			v = new Point(0, 1).transform(matrix).subtract(orig);
-		return new Size(
-			72 / u.getLength(),
-			72 / v.getLength()
-		);
-	},
-
-	getPpi: '#getResolution',
-
-	getImage: function() {
-		return this._image;
-	},
-
-	setImage: function(image) {
-		var that = this;
-
-		function emit(event) {
-			var view = that.getView(),
-				type = event && event.type || 'load';
-			if (view && that.responds(type)) {
-				paper = view._scope;
-				that.emit(type, new Event(event));
-			}
-		}
-
-		this._setImage(image);
-		if (this._loaded) {
-			setTimeout(emit, 0);
-		} else if (image) {
-			DomEvent.add(image, {
-				load: function(event) {
-					that._setImage(image);
-					emit(event);
-				},
-				error: emit
-			});
-		}
-	},
-
-	_setImage: function(image) {
-		if (this._canvas)
-			CanvasProvider.release(this._canvas);
-		if (image && image.getContext) {
-			this._image = null;
-			this._canvas = image;
-			this._loaded = true;
-		} else {
-			this._image = image;
-			this._canvas = null;
-			this._loaded = !!(image && image.src && image.complete);
-		}
-		this._size = new Size(
-				image ? image.naturalWidth || image.width : 0,
-				image ? image.naturalHeight || image.height : 0);
-		this._context = null;
-		this._changed(521);
-	},
-
-	getCanvas: function() {
-		if (!this._canvas) {
-			var ctx = CanvasProvider.getContext(this._size);
-			try {
-				if (this._image)
-					ctx.drawImage(this._image, 0, 0);
-				this._canvas = ctx.canvas;
-			} catch (e) {
-				CanvasProvider.release(ctx);
-			}
-		}
-		return this._canvas;
-	},
-
-	setCanvas: '#setImage',
-
-	getContext: function(modify) {
-		if (!this._context)
-			this._context = this.getCanvas().getContext('2d');
-		if (modify) {
-			this._image = null;
-			this._changed(513);
-		}
-		return this._context;
-	},
-
-	setContext: function(context) {
-		this._context = context;
-	},
-
-	getSource: function() {
-		var image = this._image;
-		return image && image.src || this.toDataURL();
-	},
-
-	setSource: function(src) {
-		var image = new window.Image(),
-			crossOrigin = this._crossOrigin;
-		if (crossOrigin)
-			image.crossOrigin = crossOrigin;
-		image.src = src;
-		this.setImage(image);
-	},
-
-	getCrossOrigin: function() {
-		var image = this._image;
-		return image && image.crossOrigin || this._crossOrigin || '';
-	},
-
-	setCrossOrigin: function(crossOrigin) {
-		this._crossOrigin = crossOrigin;
-		var image = this._image;
-		if (image)
-			image.crossOrigin = crossOrigin;
-	},
-
-	getElement: function() {
-		return this._canvas || this._loaded && this._image;
-	}
-}, {
-	beans: false,
-
-	getSubCanvas: function() {
-		var rect = Rectangle.read(arguments),
-			ctx = CanvasProvider.getContext(rect.getSize());
-		ctx.drawImage(this.getCanvas(), rect.x, rect.y,
-				rect.width, rect.height, 0, 0, rect.width, rect.height);
-		return ctx.canvas;
-	},
-
-	getSubRaster: function() {
-		var rect = Rectangle.read(arguments),
-			raster = new Raster(Item.NO_INSERT);
-		raster._setImage(this.getSubCanvas(rect));
-		raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
-		raster._matrix.prepend(this._matrix);
-		raster.insertAbove(this);
-		return raster;
-	},
-
-	toDataURL: function() {
-		var image = this._image,
-			src = image && image.src;
-		if (/^data:/.test(src))
-			return src;
-		var canvas = this.getCanvas();
-		return canvas ? canvas.toDataURL.apply(canvas, arguments) : null;
-	},
-
-	drawImage: function(image ) {
-		var point = Point.read(arguments, 1);
-		this.getContext(true).drawImage(image, point.x, point.y);
-	},
-
-	getAverageColor: function(object) {
-		var bounds, path;
-		if (!object) {
-			bounds = this.getBounds();
-		} else if (object instanceof PathItem) {
-			path = object;
-			bounds = object.getBounds();
-		} else if (typeof object === 'object') {
-			if ('width' in object) {
-				bounds = new Rectangle(object);
-			} else if ('x' in object) {
-				bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
-			}
-		}
-		if (!bounds)
-			return null;
-		var sampleSize = 32,
-			width = Math.min(bounds.width, sampleSize),
-			height = Math.min(bounds.height, sampleSize);
-		var ctx = Raster._sampleContext;
-		if (!ctx) {
-			ctx = Raster._sampleContext = CanvasProvider.getContext(
-					new Size(sampleSize));
-		} else {
-			ctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);
-		}
-		ctx.save();
-		var matrix = new Matrix()
-				.scale(width / bounds.width, height / bounds.height)
-				.translate(-bounds.x, -bounds.y);
-		matrix.applyToContext(ctx);
-		if (path)
-			path.draw(ctx, new Base({ clip: true, matrices: [matrix] }));
-		this._matrix.applyToContext(ctx);
-		var element = this.getElement(),
-			size = this._size;
-		if (element)
-			ctx.drawImage(element, -size.width / 2, -size.height / 2);
-		ctx.restore();
-		var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),
-				Math.ceil(height)).data,
-			channels = [0, 0, 0],
-			total = 0;
-		for (var i = 0, l = pixels.length; i < l; i += 4) {
-			var alpha = pixels[i + 3];
-			total += alpha;
-			alpha /= 255;
-			channels[0] += pixels[i] * alpha;
-			channels[1] += pixels[i + 1] * alpha;
-			channels[2] += pixels[i + 2] * alpha;
-		}
-		for (var i = 0; i < 3; i++)
-			channels[i] /= total;
-		return total ? Color.read(channels) : null;
-	},
-
-	getPixel: function() {
-		var point = Point.read(arguments);
-		var data = this.getContext().getImageData(point.x, point.y, 1, 1).data;
-		return new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],
-				data[3] / 255);
-	},
-
-	setPixel: function() {
-		var point = Point.read(arguments),
-			color = Color.read(arguments),
-			components = color._convert('rgb'),
-			alpha = color._alpha,
-			ctx = this.getContext(true),
-			imageData = ctx.createImageData(1, 1),
-			data = imageData.data;
-		data[0] = components[0] * 255;
-		data[1] = components[1] * 255;
-		data[2] = components[2] * 255;
-		data[3] = alpha != null ? alpha * 255 : 255;
-		ctx.putImageData(imageData, point.x, point.y);
-	},
-
-	createImageData: function() {
-		var size = Size.read(arguments);
-		return this.getContext().createImageData(size.width, size.height);
-	},
-
-	getImageData: function() {
-		var rect = Rectangle.read(arguments);
-		if (rect.isEmpty())
-			rect = new Rectangle(this._size);
-		return this.getContext().getImageData(rect.x, rect.y,
-				rect.width, rect.height);
-	},
-
-	setImageData: function(data ) {
-		var point = Point.read(arguments, 1);
-		this.getContext(true).putImageData(data, point.x, point.y);
-	},
-
-	_getBounds: function(matrix, options) {
-		var rect = new Rectangle(this._size).setCenter(0, 0);
-		return matrix ? matrix._transformBounds(rect) : rect;
-	},
-
-	_hitTestSelf: function(point) {
-		if (this._contains(point)) {
-			var that = this;
-			return new HitResult('pixel', that, {
-				offset: point.add(that._size.divide(2)).round(),
-				color: {
-					get: function() {
-						return that.getPixel(this.offset);
-					}
-				}
-			});
-		}
-	},
-
-	_draw: function(ctx) {
-		var element = this.getElement();
-		if (element) {
-			ctx.globalAlpha = this._opacity;
-			ctx.drawImage(element,
-					-this._size.width / 2, -this._size.height / 2);
-		}
-	},
-
-	_canComposite: function() {
-		return true;
-	}
-});
-
-var SymbolItem = Item.extend({
-	_class: 'SymbolItem',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_boundsOptions: { stroke: true },
-	_serializeFields: {
-		symbol: null
-	},
-
-	initialize: function SymbolItem(arg0, arg1) {
-		if (!this._initialize(arg0,
-				arg1 !== undefined && Point.read(arguments, 1)))
-			this.setDefinition(arg0 instanceof SymbolDefinition ?
-					arg0 : new SymbolDefinition(arg0));
-	},
-
-	_equals: function(item) {
-		return this._definition === item._definition;
-	},
-
-	copyContent: function(source) {
-		this.setDefinition(source._definition);
-	},
-
-	getDefinition: function() {
-		return this._definition;
-	},
-
-	setDefinition: function(definition) {
-		this._definition = definition;
-		this._changed(9);
-	},
-
-	getSymbol: '#getDefinition',
-	setSymbol: '#setDefinition',
-
-	isEmpty: function() {
-		return this._definition._item.isEmpty();
-	},
-
-	_getBounds: function(matrix, options) {
-		var item = this._definition._item;
-		return item._getCachedBounds(item._matrix.prepended(matrix), options);
-	},
-
-	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
-		var res = this._definition._item._hitTest(point, options, viewMatrix);
-		if (res)
-			res.item = this;
-		return res;
-	},
-
-	_draw: function(ctx, param) {
-		this._definition._item.draw(ctx, param);
-	}
-
-});
-
-var SymbolDefinition = Base.extend({
-	_class: 'SymbolDefinition',
-
-	initialize: function SymbolDefinition(item, dontCenter) {
-		this._id = UID.get();
-		this.project = paper.project;
-		if (item)
-			this.setItem(item, dontCenter);
-	},
-
-	_serialize: function(options, dictionary) {
-		return dictionary.add(this, function() {
-			return Base.serialize([this._class, this._item],
-					options, false, dictionary);
-		});
-	},
-
-	_changed: function(flags) {
-		if (flags & 8)
-			Item._clearBoundsCache(this);
-		if (flags & 1)
-			this.project._changed(flags);
-	},
-
-	getItem: function() {
-		return this._item;
-	},
-
-	setItem: function(item, _dontCenter) {
-		if (item._symbol)
-			item = item.clone();
-		if (this._item)
-			this._item._symbol = null;
-		this._item = item;
-		item.remove();
-		item.setSelected(false);
-		if (!_dontCenter)
-			item.setPosition(new Point());
-		item._symbol = this;
-		this._changed(9);
-	},
-
-	getDefinition: '#getItem',
-	setDefinition: '#setItem',
-
-	place: function(position) {
-		return new SymbolItem(this, position);
-	},
-
-	clone: function() {
-		return new SymbolDefinition(this._item.clone(false));
-	},
-
-	equals: function(symbol) {
-		return symbol === this
-				|| symbol && this._item.equals(symbol._item)
-				|| false;
-	}
-});
-
-var HitResult = Base.extend({
-	_class: 'HitResult',
-
-	initialize: function HitResult(type, item, values) {
-		this.type = type;
-		this.item = item;
-		if (values) {
-			values.enumerable = true;
-			this.inject(values);
-		}
-	},
-
-	statics: {
-		getOptions: function(args) {
-			var options = args && Base.read(args);
-			return Base.set({
-				type: null,
-				tolerance: paper.settings.hitTolerance,
-				fill: !options,
-				stroke: !options,
-				segments: !options,
-				handles: false,
-				ends: false,
-				center: false,
-				bounds: false,
-				guides: false,
-				selected: false
-			}, options);
-		}
-	}
-});
-
-var Segment = Base.extend({
-	_class: 'Segment',
-	beans: true,
-	_selection: 0,
-
-	initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
-		var count = arguments.length,
-			point, handleIn, handleOut,
-			selection;
-		if (count === 0) {
-		} else if (count === 1) {
-			if (arg0 && 'point' in arg0) {
-				point = arg0.point;
-				handleIn = arg0.handleIn;
-				handleOut = arg0.handleOut;
-				selection = arg0.selection;
-			} else {
-				point = arg0;
-			}
-		} else if (arg0 == null || typeof arg0 === 'object') {
-			point = arg0;
-			handleIn = arg1;
-			handleOut = arg2;
-			selection = arg3;
-		} else {
-			point = arg0 !== undefined ? [ arg0, arg1 ] : null;
-			handleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;
-			handleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;
-		}
-		new SegmentPoint(point, this, '_point');
-		new SegmentPoint(handleIn, this, '_handleIn');
-		new SegmentPoint(handleOut, this, '_handleOut');
-		if (selection)
-			this.setSelection(selection);
-	},
-
-	_serialize: function(options, dictionary) {
-		var point = this._point,
-			selection = this._selection,
-			obj = selection || this.hasHandles()
-					? [point, this._handleIn, this._handleOut]
-					: point;
-		if (selection)
-			obj.push(selection);
-		return Base.serialize(obj, options, true, dictionary);
-	},
-
-	_changed: function(point) {
-		var path = this._path;
-		if (!path)
-			return;
-		var curves = path._curves,
-			index = this._index,
-			curve;
-		if (curves) {
-			if ((!point || point === this._point || point === this._handleIn)
-					&& (curve = index > 0 ? curves[index - 1] : path._closed
-						? curves[curves.length - 1] : null))
-				curve._changed();
-			if ((!point || point === this._point || point === this._handleOut)
-					&& (curve = curves[index]))
-				curve._changed();
-		}
-		path._changed(25);
-	},
-
-	getPoint: function() {
-		return this._point;
-	},
-
-	setPoint: function() {
-		var point = Point.read(arguments);
-		this._point.set(point.x, point.y);
-	},
-
-	getHandleIn: function() {
-		return this._handleIn;
-	},
-
-	setHandleIn: function() {
-		var point = Point.read(arguments);
-		this._handleIn.set(point.x, point.y);
-	},
-
-	getHandleOut: function() {
-		return this._handleOut;
-	},
-
-	setHandleOut: function() {
-		var point = Point.read(arguments);
-		this._handleOut.set(point.x, point.y);
-	},
-
-	hasHandles: function() {
-		return !this._handleIn.isZero() || !this._handleOut.isZero();
-	},
-
-	clearHandles: function() {
-		this._handleIn.set(0, 0);
-		this._handleOut.set(0, 0);
-	},
-
-	getSelection: function() {
-		return this._selection;
-	},
-
-	setSelection: function(selection) {
-		var oldSelection = this._selection,
-			path = this._path;
-		this._selection = selection = selection || 0;
-		if (path && selection !== oldSelection) {
-			path._updateSelection(this, oldSelection, selection);
-			path._changed(129);
-		}
-	},
-
-	changeSelection: function(flag, selected) {
-		var selection = this._selection;
-		this.setSelection(selected ? selection | flag : selection & ~flag);
-	},
-
-	isSelected: function() {
-		return !!(this._selection & 7);
-	},
-
-	setSelected: function(selected) {
-		this.changeSelection(7, selected);
-	},
-
-	getIndex: function() {
-		return this._index !== undefined ? this._index : null;
-	},
-
-	getPath: function() {
-		return this._path || null;
-	},
-
-	getCurve: function() {
-		var path = this._path,
-			index = this._index;
-		if (path) {
-			if (index > 0 && !path._closed
-					&& index === path._segments.length - 1)
-				index--;
-			return path.getCurves()[index] || null;
-		}
-		return null;
-	},
-
-	getLocation: function() {
-		var curve = this.getCurve();
-		return curve
-				? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)
-				: null;
-	},
-
-	getNext: function() {
-		var segments = this._path && this._path._segments;
-		return segments && (segments[this._index + 1]
-				|| this._path._closed && segments[0]) || null;
-	},
-
-	smooth: function(options, _first, _last) {
-		var opts = options || {},
-			type = opts.type,
-			factor = opts.factor,
-			prev = this.getPrevious(),
-			next = this.getNext(),
-			p0 = (prev || this)._point,
-			p1 = this._point,
-			p2 = (next || this)._point,
-			d1 = p0.getDistance(p1),
-			d2 = p1.getDistance(p2);
-		if (!type || type === 'catmull-rom') {
-			var a = factor === undefined ? 0.5 : factor,
-				d1_a = Math.pow(d1, a),
-				d1_2a = d1_a * d1_a,
-				d2_a = Math.pow(d2, a),
-				d2_2a = d2_a * d2_a;
-			if (!_first && prev) {
-				var A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,
-					N = 3 * d2_a * (d2_a + d1_a);
-				this.setHandleIn(N !== 0
-					? new Point(
-						(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,
-						(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)
-					: new Point());
-			}
-			if (!_last && next) {
-				var A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,
-					N = 3 * d1_a * (d1_a + d2_a);
-				this.setHandleOut(N !== 0
-					? new Point(
-						(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,
-						(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)
-					: new Point());
-			}
-		} else if (type === 'geometric') {
-			if (prev && next) {
-				var vector = p0.subtract(p2),
-					t = factor === undefined ? 0.4 : factor,
-					k = t * d1 / (d1 + d2);
-				if (!_first)
-					this.setHandleIn(vector.multiply(k));
-				if (!_last)
-					this.setHandleOut(vector.multiply(k - t));
-			}
-		} else {
-			throw new Error('Smoothing method \'' + type + '\' not supported.');
-		}
-	},
-
-	getPrevious: function() {
-		var segments = this._path && this._path._segments;
-		return segments && (segments[this._index - 1]
-				|| this._path._closed && segments[segments.length - 1]) || null;
-	},
-
-	isFirst: function() {
-		return this._index === 0;
-	},
-
-	isLast: function() {
-		var path = this._path;
-		return path && this._index === path._segments.length - 1 || false;
-	},
-
-	reverse: function() {
-		var handleIn = this._handleIn,
-			handleOut = this._handleOut,
-			inX = handleIn._x,
-			inY = handleIn._y;
-		handleIn.set(handleOut._x, handleOut._y);
-		handleOut.set(inX, inY);
-	},
-
-	reversed: function() {
-		return new Segment(this._point, this._handleOut, this._handleIn);
-	},
-
-	remove: function() {
-		return this._path ? !!this._path.removeSegment(this._index) : false;
-	},
-
-	clone: function() {
-		return new Segment(this._point, this._handleIn, this._handleOut);
-	},
-
-	equals: function(segment) {
-		return segment === this || segment && this._class === segment._class
-				&& this._point.equals(segment._point)
-				&& this._handleIn.equals(segment._handleIn)
-				&& this._handleOut.equals(segment._handleOut)
-				|| false;
-	},
-
-	toString: function() {
-		var parts = [ 'point: ' + this._point ];
-		if (!this._handleIn.isZero())
-			parts.push('handleIn: ' + this._handleIn);
-		if (!this._handleOut.isZero())
-			parts.push('handleOut: ' + this._handleOut);
-		return '{ ' + parts.join(', ') + ' }';
-	},
-
-	transform: function(matrix) {
-		this._transformCoordinates(matrix, new Array(6), true);
-		this._changed();
-	},
-
-	interpolate: function(from, to, factor) {
-		var u = 1 - factor,
-			v = factor,
-			point1 = from._point,
-			point2 = to._point,
-			handleIn1 = from._handleIn,
-			handleIn2 = to._handleIn,
-			handleOut2 = to._handleOut,
-			handleOut1 = from._handleOut;
-		this._point.set(
-				u * point1._x + v * point2._x,
-				u * point1._y + v * point2._y, true);
-		this._handleIn.set(
-				u * handleIn1._x + v * handleIn2._x,
-				u * handleIn1._y + v * handleIn2._y, true);
-		this._handleOut.set(
-				u * handleOut1._x + v * handleOut2._x,
-				u * handleOut1._y + v * handleOut2._y, true);
-		this._changed();
-	},
-
-	_transformCoordinates: function(matrix, coords, change) {
-		var point = this._point,
-			handleIn = !change || !this._handleIn.isZero()
-					? this._handleIn : null,
-			handleOut = !change || !this._handleOut.isZero()
-					? this._handleOut : null,
-			x = point._x,
-			y = point._y,
-			i = 2;
-		coords[0] = x;
-		coords[1] = y;
-		if (handleIn) {
-			coords[i++] = handleIn._x + x;
-			coords[i++] = handleIn._y + y;
-		}
-		if (handleOut) {
-			coords[i++] = handleOut._x + x;
-			coords[i++] = handleOut._y + y;
-		}
-		if (matrix) {
-			matrix._transformCoordinates(coords, coords, i / 2);
-			x = coords[0];
-			y = coords[1];
-			if (change) {
-				point._x = x;
-				point._y = y;
-				i = 2;
-				if (handleIn) {
-					handleIn._x = coords[i++] - x;
-					handleIn._y = coords[i++] - y;
-				}
-				if (handleOut) {
-					handleOut._x = coords[i++] - x;
-					handleOut._y = coords[i++] - y;
-				}
-			} else {
-				if (!handleIn) {
-					coords[i++] = x;
-					coords[i++] = y;
-				}
-				if (!handleOut) {
-					coords[i++] = x;
-					coords[i++] = y;
-				}
-			}
-		}
-		return coords;
-	}
-});
-
-var SegmentPoint = Point.extend({
-	initialize: function SegmentPoint(point, owner, key) {
-		var x, y,
-			selected;
-		if (!point) {
-			x = y = 0;
-		} else if ((x = point[0]) !== undefined) {
-			y = point[1];
-		} else {
-			var pt = point;
-			if ((x = pt.x) === undefined) {
-				pt = Point.read(arguments);
-				x = pt.x;
-			}
-			y = pt.y;
-			selected = pt.selected;
-		}
-		this._x = x;
-		this._y = y;
-		this._owner = owner;
-		owner[key] = this;
-		if (selected)
-			this.setSelected(true);
-	},
-
-	set: function(x, y) {
-		this._x = x;
-		this._y = y;
-		this._owner._changed(this);
-		return this;
-	},
-
-	getX: function() {
-		return this._x;
-	},
-
-	setX: function(x) {
-		this._x = x;
-		this._owner._changed(this);
-	},
-
-	getY: function() {
-		return this._y;
-	},
-
-	setY: function(y) {
-		this._y = y;
-		this._owner._changed(this);
-	},
-
-	isZero: function() {
-		return Numerical.isZero(this._x) && Numerical.isZero(this._y);
-	},
-
-	isSelected: function() {
-		return !!(this._owner._selection & this._getSelection());
-	},
-
-	setSelected: function(selected) {
-		this._owner.changeSelection(this._getSelection(), selected);
-	},
-
-	_getSelection: function() {
-		var owner = this._owner;
-		return this === owner._point ? 1
-			: this === owner._handleIn ? 2
-			: this === owner._handleOut ? 4
-			: 0;
-	}
-});
-
-var Curve = Base.extend({
-	_class: 'Curve',
-
-	initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
-		var count = arguments.length,
-			seg1, seg2,
-			point1, point2,
-			handle1, handle2;
-		if (count === 3) {
-			this._path = arg0;
-			seg1 = arg1;
-			seg2 = arg2;
-		} else if (count === 0) {
-			seg1 = new Segment();
-			seg2 = new Segment();
-		} else if (count === 1) {
-			if ('segment1' in arg0) {
-				seg1 = new Segment(arg0.segment1);
-				seg2 = new Segment(arg0.segment2);
-			} else if ('point1' in arg0) {
-				point1 = arg0.point1;
-				handle1 = arg0.handle1;
-				handle2 = arg0.handle2;
-				point2 = arg0.point2;
-			} else if (Array.isArray(arg0)) {
-				point1 = [arg0[0], arg0[1]];
-				point2 = [arg0[6], arg0[7]];
-				handle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];
-				handle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];
-			}
-		} else if (count === 2) {
-			seg1 = new Segment(arg0);
-			seg2 = new Segment(arg1);
-		} else if (count === 4) {
-			point1 = arg0;
-			handle1 = arg1;
-			handle2 = arg2;
-			point2 = arg3;
-		} else if (count === 8) {
-			point1 = [arg0, arg1];
-			point2 = [arg6, arg7];
-			handle1 = [arg2 - arg0, arg3 - arg1];
-			handle2 = [arg4 - arg6, arg5 - arg7];
-		}
-		this._segment1 = seg1 || new Segment(point1, null, handle1);
-		this._segment2 = seg2 || new Segment(point2, handle2, null);
-	},
-
-	_serialize: function(options, dictionary) {
-		return Base.serialize(this.hasHandles()
-				? [this.getPoint1(), this.getHandle1(), this.getHandle2(),
-					this.getPoint2()]
-				: [this.getPoint1(), this.getPoint2()],
-				options, true, dictionary);
-	},
-
-	_changed: function() {
-		this._length = this._bounds = undefined;
-	},
-
-	clone: function() {
-		return new Curve(this._segment1, this._segment2);
-	},
-
-	toString: function() {
-		var parts = [ 'point1: ' + this._segment1._point ];
-		if (!this._segment1._handleOut.isZero())
-			parts.push('handle1: ' + this._segment1._handleOut);
-		if (!this._segment2._handleIn.isZero())
-			parts.push('handle2: ' + this._segment2._handleIn);
-		parts.push('point2: ' + this._segment2._point);
-		return '{ ' + parts.join(', ') + ' }';
-	},
-
-	remove: function() {
-		var removed = false;
-		if (this._path) {
-			var segment2 = this._segment2,
-				handleOut = segment2._handleOut;
-			removed = segment2.remove();
-			if (removed)
-				this._segment1._handleOut.set(handleOut.x, handleOut.y);
-		}
-		return removed;
-	},
-
-	getPoint1: function() {
-		return this._segment1._point;
-	},
-
-	setPoint1: function() {
-		var point = Point.read(arguments);
-		this._segment1._point.set(point.x, point.y);
-	},
-
-	getPoint2: function() {
-		return this._segment2._point;
-	},
-
-	setPoint2: function() {
-		var point = Point.read(arguments);
-		this._segment2._point.set(point.x, point.y);
-	},
-
-	getHandle1: function() {
-		return this._segment1._handleOut;
-	},
-
-	setHandle1: function() {
-		var point = Point.read(arguments);
-		this._segment1._handleOut.set(point.x, point.y);
-	},
-
-	getHandle2: function() {
-		return this._segment2._handleIn;
-	},
-
-	setHandle2: function() {
-		var point = Point.read(arguments);
-		this._segment2._handleIn.set(point.x, point.y);
-	},
-
-	getSegment1: function() {
-		return this._segment1;
-	},
-
-	getSegment2: function() {
-		return this._segment2;
-	},
-
-	getPath: function() {
-		return this._path;
-	},
-
-	getIndex: function() {
-		return this._segment1._index;
-	},
-
-	getNext: function() {
-		var curves = this._path && this._path._curves;
-		return curves && (curves[this._segment1._index + 1]
-				|| this._path._closed && curves[0]) || null;
-	},
-
-	getPrevious: function() {
-		var curves = this._path && this._path._curves;
-		return curves && (curves[this._segment1._index - 1]
-				|| this._path._closed && curves[curves.length - 1]) || null;
-	},
-
-	isFirst: function() {
-		return this._segment1._index === 0;
-	},
-
-	isLast: function() {
-		var path = this._path;
-		return path && this._segment1._index === path._curves.length - 1
-				|| false;
-	},
-
-	isSelected: function() {
-		return this.getPoint1().isSelected()
-				&& this.getHandle2().isSelected()
-				&& this.getHandle2().isSelected()
-				&& this.getPoint2().isSelected();
-	},
-
-	setSelected: function(selected) {
-		this.getPoint1().setSelected(selected);
-		this.getHandle1().setSelected(selected);
-		this.getHandle2().setSelected(selected);
-		this.getPoint2().setSelected(selected);
-	},
-
-	getValues: function(matrix) {
-		return Curve.getValues(this._segment1, this._segment2, matrix);
-	},
-
-	getPoints: function() {
-		var coords = this.getValues(),
-			points = [];
-		for (var i = 0; i < 8; i += 2)
-			points.push(new Point(coords[i], coords[i + 1]));
-		return points;
-	},
-
-	getLength: function() {
-		if (this._length == null)
-			this._length = Curve.getLength(this.getValues(), 0, 1);
-		return this._length;
-	},
-
-	getArea: function() {
-		return Curve.getArea(this.getValues());
-	},
-
-	getLine: function() {
-		return new Line(this._segment1._point, this._segment2._point);
-	},
-
-	getPart: function(from, to) {
-		return new Curve(Curve.getPart(this.getValues(), from, to));
-	},
-
-	getPartLength: function(from, to) {
-		return Curve.getLength(this.getValues(), from, to);
-	},
-
-	getIntersections: function(curve) {
-		return Curve._getIntersections(this.getValues(),
-				curve && curve !== this ? curve.getValues() : null,
-				this, curve, [], {});
-	},
-
-	divideAt: function(location) {
-		return this.divideAtTime(location && location.curve === this
-				? location.time : location);
-	},
-
-	divideAtTime: function(time, _setHandles) {
-		var tMin = 4e-7,
-			tMax = 1 - tMin,
-			res = null;
-		if (time >= tMin && time <= tMax) {
-			var parts = Curve.subdivide(this.getValues(), time),
-				left = parts[0],
-				right = parts[1],
-				setHandles = _setHandles || this.hasHandles(),
-				segment1 = this._segment1,
-				segment2 = this._segment2,
-				path = this._path;
-			if (setHandles) {
-				segment1._handleOut.set(left[2] - left[0], left[3] - left[1]);
-				segment2._handleIn.set(right[4] - right[6],right[5] - right[7]);
-			}
-			var x = left[6], y = left[7],
-				segment = new Segment(new Point(x, y),
-						setHandles && new Point(left[4] - x, left[5] - y),
-						setHandles && new Point(right[2] - x, right[3] - y));
-			if (path) {
-				path.insert(segment1._index + 1, segment);
-				res = this.getNext();
-			} else {
-				this._segment2 = segment;
-				this._changed();
-				res = new Curve(segment, segment2);
-			}
-		}
-		return res;
-	},
-
-	splitAt: function(location) {
-		return this._path ? this._path.splitAt(location) : null;
-	},
-
-	splitAtTime: function(t) {
-		return this.splitAt(this.getLocationAtTime(t));
-	},
-
-	divide: function(offset, isTime) {
-		return this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset
-				: this.getTimeAt(offset));
-	},
-
-	split: function(offset, isTime) {
-		return this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset
-				: this.getTimeAt(offset));
-	},
-
-	reversed: function() {
-		return new Curve(this._segment2.reversed(), this._segment1.reversed());
-	},
-
-	clearHandles: function() {
-		this._segment1._handleOut.set(0, 0);
-		this._segment2._handleIn.set(0, 0);
-	},
-
-statics: {
-	getValues: function(segment1, segment2, matrix) {
-		var p1 = segment1._point,
-			h1 = segment1._handleOut,
-			h2 = segment2._handleIn,
-			p2 = segment2._point,
-			values = [
-				p1._x, p1._y,
-				p1._x + h1._x, p1._y + h1._y,
-				p2._x + h2._x, p2._y + h2._y,
-				p2._x, p2._y
-			];
-		if (matrix)
-			matrix._transformCoordinates(values, values, 4);
-		return values;
-	},
-
-	subdivide: function(v, t) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7];
-		if (t === undefined)
-			t = 0.5;
-		var u = 1 - t,
-			p3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,
-			p4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,
-			p5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,
-			p6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,
-			p7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,
-			p8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;
-		return [
-			[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],
-			[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]
-		];
-	},
-
-	solveCubic: function (v, coord, val, roots, min, max) {
-		var p1 = v[coord],
-			c1 = v[coord + 2],
-			c2 = v[coord + 4],
-			p2 = v[coord + 6],
-			res = 0;
-		if (  !(p1 < val && p2 < val && c1 < val && c2 < val ||
-				p1 > val && p2 > val && c1 > val && c2 > val)) {
-			var c = 3 * (c1 - p1),
-				b = 3 * (c2 - c1) - c,
-				a = p2 - p1 - c - b;
-			res = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
-		}
-		return res;
-	},
-
-	getTimeOf: function(v, point) {
-		var p1 = new Point(v[0], v[1]),
-			p2 = new Point(v[6], v[7]),
-			epsilon = 1e-12,
-			t = point.isClose(p1, epsilon) ? 0
-			  : point.isClose(p2, epsilon) ? 1
-			  : null;
-		if (t !== null)
-			return t;
-		var coords = [point.x, point.y],
-			roots = [],
-			geomEpsilon = 2e-7;
-		for (var c = 0; c < 2; c++) {
-			var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);
-			for (var i = 0; i < count; i++) {
-				t = roots[i];
-				if (point.isClose(Curve.getPoint(v, t), geomEpsilon))
-					return t;
-			}
-		}
-		return point.isClose(p1, geomEpsilon) ? 0
-			 : point.isClose(p2, geomEpsilon) ? 1
-			 : null;
-	},
-
-	getNearestTime: function(v, point) {
-		if (Curve.isStraight(v)) {
-			var p1x = v[0], p1y = v[1],
-				p2x = v[6], p2y = v[7],
-				vx = p2x - p1x, vy = p2y - p1y,
-				det = vx * vx + vy * vy;
-			if (det === 0)
-				return 0;
-			var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
-			return u < 1e-12 ? 0
-				 : u > 0.999999999999 ? 1
-				 : Curve.getTimeOf(v,
-					new Point(p1x + u * vx, p1y + u * vy));
-		}
-
-		var count = 100,
-			minDist = Infinity,
-			minT = 0;
-
-		function refine(t) {
-			if (t >= 0 && t <= 1) {
-				var dist = point.getDistance(Curve.getPoint(v, t), true);
-				if (dist < minDist) {
-					minDist = dist;
-					minT = t;
-					return true;
-				}
-			}
-		}
-
-		for (var i = 0; i <= count; i++)
-			refine(i / count);
-
-		var step = 1 / (count * 2);
-		while (step > 4e-7) {
-			if (!refine(minT - step) && !refine(minT + step))
-				step /= 2;
-		}
-		return minT;
-	},
-
-	getPart: function(v, from, to) {
-		var flip = from > to;
-		if (flip) {
-			var tmp = from;
-			from = to;
-			to = tmp;
-		}
-		if (from > 0)
-			v = Curve.subdivide(v, from)[1];
-		if (to < 1)
-			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
-		return flip
-				? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]
-				: v;
-	},
-
-	isFlatEnough: function(v, flatness) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7],
-			ux = 3 * c1x - 2 * p1x - p2x,
-			uy = 3 * c1y - 2 * p1y - p2y,
-			vx = 3 * c2x - 2 * p2x - p1x,
-			vy = 3 * c2y - 2 * p2y - p1y;
-		return Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)
-				<= 16 * flatness * flatness;
-	},
-
-	getArea: function(v) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7];
-		return 3 * ((p2y - p1y) * (c1x + c2x) - (p2x - p1x) * (c1y + c2y)
-				+ c1y * (p1x - c2x) - c1x * (p1y - c2y)
-				+ p2y * (c2x + p1x / 3) - p2x * (c2y + p1y / 3)) / 20;
-	},
-
-	getBounds: function(v) {
-		var min = v.slice(0, 2),
-			max = min.slice(),
-			roots = [0, 0];
-		for (var i = 0; i < 2; i++)
-			Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
-					i, 0, min, max, roots);
-		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
-	},
-
-	_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
-		function add(value, padding) {
-			var left = value - padding,
-				right = value + padding;
-			if (left < min[coord])
-				min[coord] = left;
-			if (right > max[coord])
-				max[coord] = right;
-		}
-
-		padding /= 2;
-		var minPad = min[coord] - padding,
-			maxPad = max[coord] + padding;
-		if (    v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||
-				v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
-			if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {
-				add(v0, padding);
-				add(v3, padding);
-			} else {
-				var a = 3 * (v1 - v2) - v0 + v3,
-					b = 2 * (v0 + v2) - 4 * v1,
-					c = v1 - v0,
-					count = Numerical.solveQuadratic(a, b, c, roots),
-					tMin = 4e-7,
-					tMax = 1 - tMin;
-				add(v3, 0);
-				for (var i = 0; i < count; i++) {
-					var t = roots[i],
-						u = 1 - t;
-					if (tMin < t && t < tMax)
-						add(u * u * u * v0
-							+ 3 * u * u * t * v1
-							+ 3 * u * t * t * v2
-							+ t * t * t * v3,
-							padding);
-				}
-			}
-		}
-	}
-}}, Base.each(
-	['getBounds', 'getStrokeBounds', 'getHandleBounds'],
-	function(name) {
-		this[name] = function() {
-			if (!this._bounds)
-				this._bounds = {};
-			var bounds = this._bounds[name];
-			if (!bounds) {
-				bounds = this._bounds[name] = Path[name](
-						[this._segment1, this._segment2], false, this._path);
-			}
-			return bounds.clone();
-		};
-	},
-{
-
-}), Base.each({
-	isStraight: function(l, h1, h2) {
-		if (h1.isZero() && h2.isZero()) {
-			return true;
-		} else {
-			var v = l.getVector(),
-				epsilon = 2e-7;
-			if (v.isZero()) {
-				return false;
-			} else if (l.getDistance(h1) < epsilon
-					&& l.getDistance(h2) < epsilon) {
-				var div = v.dot(v),
-					p1 = v.dot(h1) / div,
-					p2 = v.dot(h2) / div;
-				return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
-			}
-		}
-		return false;
-	},
-
-	isLinear: function(l, h1, h2) {
-		var third = l.getVector().divide(3);
-		return h1.equals(third) && h2.negate().equals(third);
-	}
-}, function(test, name) {
-	this[name] = function() {
-		var seg1 = this._segment1,
-			seg2 = this._segment2;
-		return test(new Line(seg1._point, seg2._point),
-				seg1._handleOut, seg2._handleIn);
-	};
-
-	this.statics[name] = function(v) {
-		var p1x = v[0], p1y = v[1],
-			p2x = v[6], p2y = v[7];
-		return test(new Line(p1x, p1y, p2x, p2y),
-				new Point(v[2] - p1x, v[3] - p1y),
-				new Point(v[4] - p2x, v[5] - p2y));
-	};
-}, {
-	statics: {},
-
-	hasHandles: function() {
-		return !this._segment1._handleOut.isZero()
-				|| !this._segment2._handleIn.isZero();
-	},
-
-	isCollinear: function(curve) {
-		return curve && this.isStraight() && curve.isStraight()
-				&& this.getLine().isCollinear(curve.getLine());
-	},
-
-	isHorizontal: function() {
-		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)
-				< 1e-7;
-	},
-
-	isVertical: function() {
-		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)
-				< 1e-7;
-	}
-}), {
-	beans: false,
-
-	getLocationAt: function(offset, _isTime) {
-		return this.getLocationAtTime(
-				_isTime ? offset : this.getTimeAt(offset));
-	},
-
-	getLocationAtTime: function(t) {
-		return t != null && t >= 0 && t <= 1
-				? new CurveLocation(this, t)
-				: null;
-	},
-
-	getTimeAt: function(offset, start) {
-		return Curve.getTimeAt(this.getValues(), offset, start);
-	},
-
-	getParameterAt: '#getTimeAt',
-
-	getOffsetAtTime: function(t) {
-		return this.getPartLength(0, t);
-	},
-
-	getLocationOf: function() {
-		return this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));
-	},
-
-	getOffsetOf: function() {
-		var loc = this.getLocationOf.apply(this, arguments);
-		return loc ? loc.getOffset() : null;
-	},
-
-	getTimeOf: function() {
-		return Curve.getTimeOf(this.getValues(), Point.read(arguments));
-	},
-
-	getParameterOf: '#getTimeOf',
-
-	getNearestLocation: function() {
-		var point = Point.read(arguments),
-			values = this.getValues(),
-			t = Curve.getNearestTime(values, point),
-			pt = Curve.getPoint(values, t);
-		return new CurveLocation(this, t, pt, null, point.getDistance(pt));
-	},
-
-	getNearestPoint: function() {
-		var loc = this.getNearestLocation.apply(this, arguments);
-		return loc ? loc.getPoint() : loc;
-	}
-
-},
-new function() {
-	var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
-		'getWeightedNormal', 'getCurvature'];
-	return Base.each(methods,
-		function(name) {
-			this[name + 'At'] = function(location, _isTime) {
-				var values = this.getValues();
-				return Curve[name](values, _isTime ? location
-						: Curve.getTimeAt(values, location));
-			};
-
-			this[name + 'AtTime'] = function(time) {
-				return Curve[name](this.getValues(), time);
-			};
-		}, {
-			statics: {
-				_evaluateMethods: methods
-			}
-		}
-	);
-},
-new function() {
-
-	function getLengthIntegrand(v) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7],
-
-			ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
-			bx = 6 * (p1x + c2x) - 12 * c1x,
-			cx = 3 * (c1x - p1x),
-
-			ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
-			by = 6 * (p1y + c2y) - 12 * c1y,
-			cy = 3 * (c1y - p1y);
-
-		return function(t) {
-			var dx = (ax * t + bx) * t + cx,
-				dy = (ay * t + by) * t + cy;
-			return Math.sqrt(dx * dx + dy * dy);
-		};
-	}
-
-	function getIterations(a, b) {
-		return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
-	}
-
-	function evaluate(v, t, type, normalized) {
-		if (t == null || t < 0 || t > 1)
-			return null;
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7],
-			isZero = Numerical.isZero;
-		if (isZero(c1x - p1x) && isZero(c1y - p1y)) {
-			c1x = p1x;
-			c1y = p1y;
-		}
-		if (isZero(c2x - p2x) && isZero(c2y - p2y)) {
-			c2x = p2x;
-			c2y = p2y;
-		}
-		var cx = 3 * (c1x - p1x),
-			bx = 3 * (c2x - c1x) - cx,
-			ax = p2x - p1x - cx - bx,
-			cy = 3 * (c1y - p1y),
-			by = 3 * (c2y - c1y) - cy,
-			ay = p2y - p1y - cy - by,
-			x, y;
-		if (type === 0) {
-			x = t === 0 ? p1x : t === 1 ? p2x
-					: ((ax * t + bx) * t + cx) * t + p1x;
-			y = t === 0 ? p1y : t === 1 ? p2y
-					: ((ay * t + by) * t + cy) * t + p1y;
-		} else {
-			var tMin = 4e-7,
-				tMax = 1 - tMin;
-			if (t < tMin) {
-				x = cx;
-				y = cy;
-			} else if (t > tMax) {
-				x = 3 * (p2x - c2x);
-				y = 3 * (p2y - c2y);
-			} else {
-				x = (3 * ax * t + 2 * bx) * t + cx;
-				y = (3 * ay * t + 2 * by) * t + cy;
-			}
-			if (normalized) {
-				if (x === 0 && y === 0 && (t < tMin || t > tMax)) {
-					x = c2x - c1x;
-					y = c2y - c1y;
-				}
-				var len = Math.sqrt(x * x + y * y);
-				if (len) {
-					x /= len;
-					y /= len;
-				}
-			}
-			if (type === 3) {
-				var x2 = 6 * ax * t + 2 * bx,
-					y2 = 6 * ay * t + 2 * by,
-					d = Math.pow(x * x + y * y, 3 / 2);
-				x = d !== 0 ? (x * y2 - y * x2) / d : 0;
-				y = 0;
-			}
-		}
-		return type === 2 ? new Point(y, -x) : new Point(x, y);
-	}
-
-	return { statics: {
-
-		getLength: function(v, a, b, ds) {
-			if (a === undefined)
-				a = 0;
-			if (b === undefined)
-				b = 1;
-			if (Curve.isStraight(v)) {
-				var c = v;
-				if (b < 1) {
-					c = Curve.subdivide(c, b)[0];
-					a /= b;
-				}
-				if (a > 0) {
-					c = Curve.subdivide(c, a)[1];
-				}
-				var dx = c[6] - c[0],
-					dy = c[7] - c[1];
-				return Math.sqrt(dx * dx + dy * dy);
-			}
-			return Numerical.integrate(ds || getLengthIntegrand(v), a, b,
-					getIterations(a, b));
-		},
-
-		getTimeAt: function(v, offset, start) {
-			if (start === undefined)
-				start = offset < 0 ? 1 : 0;
-			if (offset === 0)
-				return start;
-			var abs = Math.abs,
-				epsilon = 1e-12,
-				forward = offset > 0,
-				a = forward ? start : 0,
-				b = forward ? 1 : start,
-				ds = getLengthIntegrand(v),
-				rangeLength = Curve.getLength(v, a, b, ds),
-				diff = abs(offset) - rangeLength;
-			if (abs(diff) < epsilon) {
-				return forward ? b : a;
-			} else if (diff > epsilon) {
-				return null;
-			}
-			var guess = offset / rangeLength,
-				length = 0;
-			function f(t) {
-				length += Numerical.integrate(ds, start, t,
-						getIterations(start, t));
-				start = t;
-				return length - offset;
-			}
-			return Numerical.findRoot(f, ds, start + guess, a, b, 32,
-					1e-12);
-		},
-
-		getPoint: function(v, t) {
-			return evaluate(v, t, 0, false);
-		},
-
-		getTangent: function(v, t) {
-			return evaluate(v, t, 1, true);
-		},
-
-		getWeightedTangent: function(v, t) {
-			return evaluate(v, t, 1, false);
-		},
-
-		getNormal: function(v, t) {
-			return evaluate(v, t, 2, true);
-		},
-
-		getWeightedNormal: function(v, t) {
-			return evaluate(v, t, 2, false);
-		},
-
-		getCurvature: function(v, t) {
-			return evaluate(v, t, 3, false).x;
-		}
-	}};
-},
-new function() {
-
-	function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
-			overlap) {
-		var excludeStart = !overlap && param.excludeStart,
-			excludeEnd = !overlap && param.excludeEnd,
-			tMin = 4e-7,
-			tMax = 1 - tMin;
-		if (t1 == null)
-			t1 = Curve.getTimeOf(v1, p1);
-		if (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&
-			t1 <= (excludeEnd ? tMax : 1)) {
-			if (t2 == null)
-				t2 = Curve.getTimeOf(v2, p2);
-			if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
-				t2 <= (excludeStart ? tMax : 1)) {
-				var renormalize = param.renormalize;
-				if (renormalize) {
-					var res = renormalize(t1, t2);
-					t1 = res[0];
-					t2 = res[1];
-				}
-				var loc1 = new CurveLocation(c1, t1,
-						p1 || Curve.getPoint(v1, t1), overlap),
-					loc2 = new CurveLocation(c2, t2,
-						p2 || Curve.getPoint(v2, t2), overlap),
-					flip = loc1.getPath() === loc2.getPath()
-						&& loc1.getIndex() > loc2.getIndex(),
-					loc = flip ? loc2 : loc1,
-					include = param.include;
-				loc1._intersection = loc2;
-				loc2._intersection = loc1;
-				if (!include || include(loc)) {
-					CurveLocation.insert(locations, loc, true);
-				}
-			}
-		}
-	}
-
-	function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,
-			uMin, uMax, flip, recursion, calls) {
-		if (++recursion >= 48 || ++calls > 4096)
-			return calls;
-		var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
-			getSignedDistance = Line.getSignedDistance,
-			d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),
-			d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),
-			factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
-			dMin = factor * Math.min(0, d1, d2),
-			dMax = factor * Math.max(0, d1, d2),
-			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
-			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
-			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
-			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
-			hull = getConvexHull(dp0, dp1, dp2, dp3),
-			top = hull[0],
-			bottom = hull[1],
-			tMinClip,
-			tMaxClip;
-		if (d1 === 0 && d2 === 0
-				&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0
-			|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null
-			|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),
-				dMin, dMax)) == null)
-			return calls;
-		var tMinNew = tMin + (tMax - tMin) * tMinClip,
-			tMaxNew = tMin + (tMax - tMin) * tMaxClip;
-		if (Math.max(uMax - uMin, tMaxNew - tMinNew)
-				< 1e-9) {
-			var t = (tMinNew + tMaxNew) / 2,
-				u = (uMin + uMax) / 2;
-			v1 = c1.getValues();
-			v2 = c2.getValues();
-			addLocation(locations, param,
-					flip ? v2 : v1, flip ? c2 : c1, flip ? u : t, null,
-					flip ? v1 : v2, flip ? c1 : c2, flip ? t : u, null);
-		} else {
-			v1 = Curve.getPart(v1, tMinClip, tMaxClip);
-			if (tMaxClip - tMinClip > 0.8) {
-				if (tMaxNew - tMinNew > uMax - uMin) {
-					var parts = Curve.subdivide(v1, 0.5),
-						t = (tMinNew + tMaxNew) / 2;
-					calls = addCurveIntersections(
-							v2, parts[0], c2, c1, locations, param,
-							uMin, uMax, tMinNew, t, !flip, recursion, calls);
-					calls = addCurveIntersections(
-							v2, parts[1], c2, c1, locations, param,
-							uMin, uMax, t, tMaxNew, !flip, recursion, calls);
-				} else {
-					var parts = Curve.subdivide(v2, 0.5),
-						u = (uMin + uMax) / 2;
-					calls = addCurveIntersections(
-							parts[0], v1, c2, c1, locations, param,
-							uMin, u, tMinNew, tMaxNew, !flip, recursion, calls);
-					calls = addCurveIntersections(
-							parts[1], v1, c2, c1, locations, param,
-							u, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
-				}
-			} else {
-				calls = addCurveIntersections(
-						v2, v1, c2, c1, locations, param,
-						uMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
-			}
-		}
-		return calls;
-	}
-
-	function getConvexHull(dq0, dq1, dq2, dq3) {
-		var p0 = [ 0, dq0 ],
-			p1 = [ 1 / 3, dq1 ],
-			p2 = [ 2 / 3, dq2 ],
-			p3 = [ 1, dq3 ],
-			dist1 = dq1 - (2 * dq0 + dq3) / 3,
-			dist2 = dq2 - (dq0 + 2 * dq3) / 3,
-			hull;
-		if (dist1 * dist2 < 0) {
-			hull = [[p0, p1, p3], [p0, p2, p3]];
-		} else {
-			var distRatio = dist1 / dist2;
-			hull = [
-				distRatio >= 2 ? [p0, p1, p3]
-				: distRatio <= 0.5 ? [p0, p2, p3]
-				: [p0, p1, p2, p3],
-				[p0, p3]
-			];
-		}
-		return (dist1 || dist2) < 0 ? hull.reverse() : hull;
-	}
-
-	function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
-		if (hullTop[0][1] < dMin) {
-			return clipConvexHullPart(hullTop, true, dMin);
-		} else if (hullBottom[0][1] > dMax) {
-			return clipConvexHullPart(hullBottom, false, dMax);
-		} else {
-			return hullTop[0][0];
-		}
-	}
-
-	function clipConvexHullPart(part, top, threshold) {
-		var px = part[0][0],
-			py = part[0][1];
-		for (var i = 1, l = part.length; i < l; i++) {
-			var qx = part[i][0],
-				qy = part[i][1];
-			if (top ? qy >= threshold : qy <= threshold) {
-				return qy === threshold ? qx
-						: px + (threshold - py) * (qx - px) / (qy - py);
-			}
-			px = qx;
-			py = qy;
-		}
-		return null;
-	}
-
-	function addCurveLineIntersections(v1, v2, c1, c2, locations, param) {
-		var flip = Curve.isStraight(v1),
-			vc = flip ? v2 : v1,
-			vl = flip ? v1 : v2,
-			lx1 = vl[0], ly1 = vl[1],
-			lx2 = vl[6], ly2 = vl[7],
-			ldx = lx2 - lx1,
-			ldy = ly2 - ly1,
-			angle = Math.atan2(-ldy, ldx),
-			sin = Math.sin(angle),
-			cos = Math.cos(angle),
-			rvc = [];
-		for(var i = 0; i < 8; i += 2) {
-			var x = vc[i] - lx1,
-				y = vc[i + 1] - ly1;
-			rvc.push(
-				x * cos - y * sin,
-				x * sin + y * cos);
-		}
-		var roots = [],
-			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
-		for (var i = 0; i < count; i++) {
-			var tc = roots[i],
-				pc = Curve.getPoint(vc, tc),
-				tl = Curve.getTimeOf(vl, pc);
-			if (tl !== null) {
-				var pl = Curve.getPoint(vl, tl),
-					t1 = flip ? tl : tc,
-					t2 = flip ? tc : tl;
-				if (!param.excludeEnd || t2 > Numerical.CURVETIME_EPSILON) {
-					addLocation(locations, param,
-							v1, c1, t1, flip ? pl : pc,
-							v2, c2, t2, flip ? pc : pl);
-				}
-			}
-		}
-	}
-
-	function addLineIntersection(v1, v2, c1, c2, locations, param) {
-		var pt = Line.intersect(
-				v1[0], v1[1], v1[6], v1[7],
-				v2[0], v2[1], v2[6], v2[7]);
-		if (pt) {
-			addLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);
-		}
-	}
-
-	return { statics: {
-		_getIntersections: function(v1, v2, c1, c2, locations, param) {
-			if (!v2) {
-				return Curve._getSelfIntersection(v1, c1, locations, param);
-			}
-			var epsilon = 2e-7,
-				c1p1x = v1[0], c1p1y = v1[1],
-				c1p2x = v1[6], c1p2y = v1[7],
-				c2p1x = v2[0], c2p1y = v2[1],
-				c2p2x = v2[6], c2p2y = v2[7],
-				c1s1x = (3 * v1[2] + c1p1x) / 4,
-				c1s1y = (3 * v1[3] + c1p1y) / 4,
-				c1s2x = (3 * v1[4] + c1p2x) / 4,
-				c1s2y = (3 * v1[5] + c1p2y) / 4,
-				c2s1x = (3 * v2[2] + c2p1x) / 4,
-				c2s1y = (3 * v2[3] + c2p1y) / 4,
-				c2s2x = (3 * v2[4] + c2p2x) / 4,
-				c2s2y = (3 * v2[5] + c2p2y) / 4,
-				min = Math.min,
-				max = Math.max;
-			if (!(  max(c1p1x, c1s1x, c1s2x, c1p2x) + epsilon >
-					min(c2p1x, c2s1x, c2s2x, c2p2x) &&
-					min(c1p1x, c1s1x, c1s2x, c1p2x) - epsilon <
-					max(c2p1x, c2s1x, c2s2x, c2p2x) &&
-					max(c1p1y, c1s1y, c1s2y, c1p2y) + epsilon >
-					min(c2p1y, c2s1y, c2s2y, c2p2y) &&
-					min(c1p1y, c1s1y, c1s2y, c1p2y) - epsilon <
-					max(c2p1y, c2s1y, c2s2y, c2p2y)))
-				return locations;
-			var overlaps = Curve.getOverlaps(v1, v2);
-			if (overlaps) {
-				for (var i = 0; i < 2; i++) {
-					var overlap = overlaps[i];
-					addLocation(locations, param,
-						v1, c1, overlap[0], null,
-						v2, c2, overlap[1], null, true);
-				}
-				return locations;
-			}
-
-			var straight1 = Curve.isStraight(v1),
-				straight2 = Curve.isStraight(v2),
-				straight = straight1 && straight2,
-				before = locations.length;
-			(straight
-				? addLineIntersection
-				: straight1 || straight2
-					? addCurveLineIntersections
-					: addCurveIntersections)(
-						v1, v2, c1, c2, locations, param,
-						0, 1, 0, 1, 0, 0, 0);
-			if (straight && locations.length > before)
-				return locations;
-			var c1p1 = new Point(c1p1x, c1p1y),
-				c1p2 = new Point(c1p2x, c1p2y),
-				c2p1 = new Point(c2p1x, c2p1y),
-				c2p2 = new Point(c2p2x, c2p2y);
-			if (c1p1.isClose(c2p1, epsilon))
-				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);
-			if (!param.excludeStart && c1p1.isClose(c2p2, epsilon))
-				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);
-			if (!param.excludeEnd && c1p2.isClose(c2p1, epsilon))
-				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);
-			if (c1p2.isClose(c2p2, epsilon))
-				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);
-			return locations;
-		},
-
-		_getSelfIntersection: function(v1, c1, locations, param) {
-			var p1x = v1[0], p1y = v1[1],
-				h1x = v1[2], h1y = v1[3],
-				h2x = v1[4], h2y = v1[5],
-				p2x = v1[6], p2y = v1[7];
-			var line = new Line(p1x, p1y, p2x, p2y, false),
-				side1 = line.getSide(new Point(h1x, h1y), true),
-				side2 = line.getSide(new Point(h2x, h2y), true);
-			if (side1 === side2) {
-				var edgeSum = (p1x - h2x) * (h1y - p2y)
-							+ (h1x - p2x) * (h2y - p1y);
-				if (edgeSum * side1 > 0)
-					return locations;
-			}
-			var ax = p2x - 3 * h2x + 3 * h1x - p1x,
-				bx = h2x - 2 * h1x + p1x,
-				cx = h1x - p1x,
-				ay = p2y - 3 * h2y + 3 * h1y - p1y,
-				by = h2y - 2 * h1y + p1y,
-				cy = h1y - p1y,
-				ac = ay * cx - ax * cy,
-				ab = ay * bx - ax * by,
-				bc = by * cx - bx * cy;
-			if (ac * ac - 4 * ab * bc < 0) {
-				var roots = [],
-					tSplit,
-					count = Numerical.solveCubic(
-							ax * ax  + ay * ay,
-							3 * (ax * bx + ay * by),
-							2 * (bx * bx + by * by) + ax * cx + ay * cy,
-							bx * cx + by * cy,
-							roots, 0, 1);
-				if (count > 0) {
-					for (var i = 0, maxCurvature = 0; i < count; i++) {
-						var curvature = Math.abs(
-								c1.getCurvatureAtTime(roots[i]));
-						if (curvature > maxCurvature) {
-							maxCurvature = curvature;
-							tSplit = roots[i];
-						}
-					}
-					var parts = Curve.subdivide(v1, tSplit);
-					param.excludeEnd = true;
-					param.renormalize = function(t1, t2) {
-						return [t1 * tSplit, t2 * (1 - tSplit) + tSplit];
-					};
-					Curve._getIntersections(parts[0], parts[1], c1, c1,
-							locations, param);
-				}
-			}
-			return locations;
-		},
-
-		getOverlaps: function(v1, v2) {
-			var abs = Math.abs,
-				timeEpsilon = 4e-7,
-				geomEpsilon = 2e-7,
-				straight1 = Curve.isStraight(v1),
-				straight2 = Curve.isStraight(v2),
-				straightBoth = straight1 && straight2;
-
-			function getSquaredLineLength(v) {
-				var x = v[6] - v[0],
-					y = v[7] - v[1];
-				return x * x + y * y;
-			}
-
-			var flip = getSquaredLineLength(v1) < getSquaredLineLength(v2),
-				l1 = flip ? v2 : v1,
-				l2 = flip ? v1 : v2,
-				line = new Line(l1[0], l1[1], l1[6], l1[7]);
-			if (line.getDistance(new Point(l2[0], l2[1])) < geomEpsilon &&
-				line.getDistance(new Point(l2[6], l2[7])) < geomEpsilon) {
-				if (!straightBoth &&
-					line.getDistance(new Point(l1[2], l1[3])) < geomEpsilon &&
-					line.getDistance(new Point(l1[4], l1[5])) < geomEpsilon &&
-					line.getDistance(new Point(l2[2], l2[3])) < geomEpsilon &&
-					line.getDistance(new Point(l2[4], l2[5])) < geomEpsilon) {
-					straight1 = straight2 = straightBoth = true;
-				}
-			} else if (straightBoth) {
-				return null;
-			}
-			if (straight1 ^ straight2) {
-				return null;
-			}
-
-			var v = [v1, v2],
-				pairs = [];
-			for (var i = 0, t1 = 0;
-					i < 2 && pairs.length < 2;
-					i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
-				var t2 = Curve.getTimeOf(v[i ^ 1], new Point(
-						v[i][t1 === 0 ? 0 : 6],
-						v[i][t1 === 0 ? 1 : 7]));
-				if (t2 != null) {
-					var pair = i === 0 ? [t1, t2] : [t2, t1];
-					if (pairs.length === 0 ||
-						abs(pair[0] - pairs[0][0]) > timeEpsilon &&
-						abs(pair[1] - pairs[0][1]) > timeEpsilon)
-						pairs.push(pair);
-				}
-				if (i === 1 && pairs.length === 0)
-					break;
-			}
-			if (pairs.length !== 2) {
-				pairs = null;
-			} else if (!straightBoth) {
-				var o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),
-					o2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);
-				if (abs(o2[2] - o1[2]) > geomEpsilon ||
-					abs(o2[3] - o1[3]) > geomEpsilon ||
-					abs(o2[4] - o1[4]) > geomEpsilon ||
-					abs(o2[5] - o1[5]) > geomEpsilon)
-					pairs = null;
-			}
-			return pairs;
-		}
-	}};
-});
-
-var CurveLocation = Base.extend({
-	_class: 'CurveLocation',
-	beans: true,
-
-	initialize: function CurveLocation(curve, time, point, _overlap, _distance) {
-		if (time > 0.9999996) {
-			var next = curve.getNext();
-			if (next) {
-				time = 0;
-				curve = next;
-			}
-		}
-		this._setCurve(curve);
-		this._time = time;
-		this._point = point || curve.getPointAtTime(time);
-		this._overlap = _overlap;
-		this._distance = _distance;
-		this._intersection = this._next = this._previous = null;
-	},
-
-	_setCurve: function(curve) {
-		var path = curve._path;
-		this._path = path;
-		this._version = path ? path._version : 0;
-		this._curve = curve;
-		this._segment = null;
-		this._segment1 = curve._segment1;
-		this._segment2 = curve._segment2;
-	},
-
-	_setSegment: function(segment) {
-		this._setCurve(segment.getCurve());
-		this._segment = segment;
-		this._time = segment === this._segment1 ? 0 : 1;
-		this._point = segment._point.clone();
-	},
-
-	getSegment: function() {
-		var curve = this.getCurve(),
-			segment = this._segment;
-		if (!segment) {
-			var time = this.getTime();
-			if (time === 0) {
-				segment = curve._segment1;
-			} else if (time === 1) {
-				segment = curve._segment2;
-			} else if (time != null) {
-				segment = curve.getPartLength(0, time)
-					< curve.getPartLength(time, 1)
-						? curve._segment1
-						: curve._segment2;
-			}
-			this._segment = segment;
-		}
-		return segment;
-	},
-
-	getCurve: function() {
-		var path = this._path,
-			that = this;
-		if (path && path._version !== this._version) {
-			this._time = this._curve = this._offset = null;
-		}
-
-		function trySegment(segment) {
-			var curve = segment && segment.getCurve();
-			if (curve && (that._time = curve.getTimeOf(that._point))
-					!= null) {
-				that._setCurve(curve);
-				that._segment = segment;
-				return curve;
-			}
-		}
-
-		return this._curve
-			|| trySegment(this._segment)
-			|| trySegment(this._segment1)
-			|| trySegment(this._segment2.getPrevious());
-	},
-
-	getPath: function() {
-		var curve = this.getCurve();
-		return curve && curve._path;
-	},
-
-	getIndex: function() {
-		var curve = this.getCurve();
-		return curve && curve.getIndex();
-	},
-
-	getTime: function() {
-		var curve = this.getCurve(),
-			time = this._time;
-		return curve && time == null
-			? this._time = curve.getTimeOf(this._point)
-			: time;
-	},
-
-	getParameter: '#getTime',
-
-	getPoint: function() {
-		return this._point;
-	},
-
-	getOffset: function() {
-		var offset = this._offset;
-		if (offset == null) {
-			offset = 0;
-			var path = this.getPath(),
-				index = this.getIndex();
-			if (path && index != null) {
-				var curves = path.getCurves();
-				for (var i = 0; i < index; i++)
-					offset += curves[i].getLength();
-			}
-			this._offset = offset += this.getCurveOffset();
-		}
-		return offset;
-	},
-
-	getCurveOffset: function() {
-		var curve = this.getCurve(),
-			time = this.getTime();
-		return time != null && curve && curve.getPartLength(0, time);
-	},
-
-	getIntersection: function() {
-		return this._intersection;
-	},
-
-	getDistance: function() {
-		return this._distance;
-	},
-
-	divide: function() {
-		var curve = this.getCurve(),
-			res = null;
-		if (curve) {
-			res = curve.divideAtTime(this.getTime());
-			if (res)
-				this._setSegment(res._segment1);
-		}
-		return res;
-	},
-
-	split: function() {
-		var curve = this.getCurve();
-		return curve ? curve.splitAtTime(this.getTime()) : null;
-	},
-
-	equals: function(loc, _ignoreOther) {
-		var res = this === loc,
-			epsilon = 2e-7;
-		if (!res && loc instanceof CurveLocation
-				&& this.getPath() === loc.getPath()
-				&& this.getPoint().isClose(loc.getPoint(), epsilon)) {
-			var c1 = this.getCurve(),
-				c2 = loc.getCurve(),
-				abs = Math.abs,
-				diff = abs(
-					((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
-							+ this.getTime()) -
-					((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
-							+ loc.getTime()));
-			res = (diff < 4e-7
-				|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon
-					|| abs(this.getPath().getLength() - diff) < epsilon))
-				&& (_ignoreOther
-					|| (!this._intersection && !loc._intersection
-						|| this._intersection && this._intersection.equals(
-								loc._intersection, true)));
-		}
-		return res;
-	},
-
-	toString: function() {
-		var parts = [],
-			point = this.getPoint(),
-			f = Formatter.instance;
-		if (point)
-			parts.push('point: ' + point);
-		var index = this.getIndex();
-		if (index != null)
-			parts.push('index: ' + index);
-		var time = this.getTime();
-		if (time != null)
-			parts.push('time: ' + f.number(time));
-		if (this._distance != null)
-			parts.push('distance: ' + f.number(this._distance));
-		return '{ ' + parts.join(', ') + ' }';
-	},
-
-	isTouching: function() {
-		var inter = this._intersection;
-		if (inter && this.getTangent().isCollinear(inter.getTangent())) {
-			var curve1 = this.getCurve(),
-				curve2 = inter.getCurve();
-			return !(curve1.isStraight() && curve2.isStraight()
-					&& curve1.getLine().intersect(curve2.getLine()));
-		}
-		return false;
-	},
-
-	isCrossing: function() {
-		var inter = this._intersection;
-		if (!inter)
-			return false;
-		var t1 = this.getTime(),
-			t2 = inter.getTime(),
-			tMin = 4e-7,
-			tMax = 1 - tMin,
-			t1Inside = t1 > tMin && t1 < tMax,
-			t2Inside = t2 > tMin && t2 < tMax;
-		if (t1Inside && t2Inside)
-			return !this.isTouching();
-		var c2 = this.getCurve(),
-			c1 = t1 <= tMin ? c2.getPrevious() : c2,
-			c4 = inter.getCurve(),
-			c3 = t2 <= tMin ? c4.getPrevious() : c4;
-		if (t1 >= tMax)
-			c2 = c2.getNext();
-		if (t2 >= tMax)
-			c4 = c4.getNext();
-		if (!c1 || !c2 || !c3 || !c4)
-			return false;
-
-		function isInRange(angle, min, max) {
-			return min < max
-					? angle > min && angle < max
-					: angle > min || angle < max;
-		}
-
-		var lenghts = [];
-		if (!t1Inside)
-			lenghts.push(c1.getLength(), c2.getLength());
-		if (!t2Inside)
-			lenghts.push(c3.getLength(), c4.getLength());
-		var pt = this.getPoint(),
-			offset = Math.min.apply(Math, lenghts) / 64,
-			v2 = t1Inside ? c2.getTangentAtTime(t1)
-					: c2.getPointAt(offset).subtract(pt),
-			v1 = t1Inside ? v2.negate()
-					: c1.getPointAt(-offset).subtract(pt),
-			v4 = t2Inside ? c4.getTangentAtTime(t2)
-					: c4.getPointAt(offset).subtract(pt),
-			v3 = t2Inside ? v4.negate()
-					: c3.getPointAt(-offset).subtract(pt),
-			a1 = v1.getAngle(),
-			a2 = v2.getAngle(),
-			a3 = v3.getAngle(),
-			a4 = v4.getAngle();
-		return !!(t1Inside
-				? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&
-				  (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))
-				: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&
-				  (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));
-	},
-
-	hasOverlap: function() {
-		return !!this._overlap;
-	}
-}, Base.each(Curve._evaluateMethods, function(name) {
-	var get = name + 'At';
-	this[name] = function() {
-		var curve = this.getCurve(),
-			time = this.getTime();
-		return time != null && curve && curve[get](time, true);
-	};
-}, {
-	preserve: true
-}),
-new function() {
-
-	function insert(locations, loc, merge) {
-		var length = locations.length,
-			l = 0,
-			r = length - 1;
-
-		function search(index, dir) {
-			for (var i = index + dir; i >= -1 && i <= length; i += dir) {
-				var loc2 = locations[((i % length) + length) % length];
-				if (!loc.getPoint().isClose(loc2.getPoint(),
-						2e-7))
-					break;
-				if (loc.equals(loc2))
-					return loc2;
-			}
-			return null;
-		}
-
-		while (l <= r) {
-			var m = (l + r) >>> 1,
-				loc2 = locations[m],
-				found;
-			if (merge && (found = loc.equals(loc2) ? loc2
-					: (search(m, -1) || search(m, 1)))) {
-				if (loc._overlap) {
-					found._overlap = found._intersection._overlap = true;
-				}
-				return found;
-			}
-		var path1 = loc.getPath(),
-			path2 = loc2.getPath(),
-			diff = path1 === path2
-				? (loc.getIndex() + loc.getTime())
-				- (loc2.getIndex() + loc2.getTime())
-				: path1._id - path2._id;
-			if (diff < 0) {
-				r = m - 1;
-			} else {
-				l = m + 1;
-			}
-		}
-		locations.splice(l, 0, loc);
-		return loc;
-	}
-
-	return { statics: {
-		insert: insert,
-
-		expand: function(locations) {
-			var expanded = locations.slice();
-			for (var i = locations.length - 1; i >= 0; i--) {
-				insert(expanded, locations[i]._intersection, false);
-			}
-			return expanded;
-		}
-	}};
-});
-
-var PathItem = Item.extend({
-	_class: 'PathItem',
-	_selectBounds: false,
-	_canScaleStroke: true,
-
-	initialize: function PathItem() {
-	},
-
-	statics: {
-		create: function(pathData) {
-			var ctor = (pathData && pathData.match(/m/gi) || []).length > 1
-					|| /z\s*\S+/i.test(pathData) ? CompoundPath : Path;
-			return new ctor(pathData);
-		}
-	},
-
-	_asPathItem: function() {
-		return this;
-	},
-
-	setPathData: function(data) {
-
-		var parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),
-			coords,
-			relative = false,
-			previous,
-			control,
-			current = new Point(),
-			start = new Point();
-
-		function getCoord(index, coord) {
-			var val = +coords[index];
-			if (relative)
-				val += current[coord];
-			return val;
-		}
-
-		function getPoint(index) {
-			return new Point(
-				getCoord(index, 'x'),
-				getCoord(index + 1, 'y')
-			);
-		}
-
-		this.clear();
-
-		for (var i = 0, l = parts && parts.length; i < l; i++) {
-			var part = parts[i],
-				command = part[0],
-				lower = command.toLowerCase();
-			coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
-			var length = coords && coords.length;
-			relative = command === lower;
-			if (previous === 'z' && !/[mz]/.test(lower))
-				this.moveTo(current = start);
-			switch (lower) {
-			case 'm':
-			case 'l':
-				var move = lower === 'm';
-				for (var j = 0; j < length; j += 2)
-					this[j === 0 && move ? 'moveTo' : 'lineTo'](
-							current = getPoint(j));
-				control = current;
-				if (move)
-					start = current;
-				break;
-			case 'h':
-			case 'v':
-				var coord = lower === 'h' ? 'x' : 'y';
-				for (var j = 0; j < length; j++) {
-					current[coord] = getCoord(j, coord);
-					this.lineTo(current);
-				}
-				control = current;
-				break;
-			case 'c':
-				for (var j = 0; j < length; j += 6) {
-					this.cubicCurveTo(
-							getPoint(j),
-							control = getPoint(j + 2),
-							current = getPoint(j + 4));
-				}
-				break;
-			case 's':
-				for (var j = 0; j < length; j += 4) {
-					this.cubicCurveTo(
-							/[cs]/.test(previous)
-									? current.multiply(2).subtract(control)
-									: current,
-							control = getPoint(j),
-							current = getPoint(j + 2));
-					previous = lower;
-				}
-				break;
-			case 'q':
-				for (var j = 0; j < length; j += 4) {
-					this.quadraticCurveTo(
-							control = getPoint(j),
-							current = getPoint(j + 2));
-				}
-				break;
-			case 't':
-				for (var j = 0; j < length; j += 2) {
-					this.quadraticCurveTo(
-							control = (/[qt]/.test(previous)
-									? current.multiply(2).subtract(control)
-									: current),
-							current = getPoint(j));
-					previous = lower;
-				}
-				break;
-			case 'a':
-				for (var j = 0; j < length; j += 7) {
-					this.arcTo(current = getPoint(j + 5),
-							new Size(+coords[j], +coords[j + 1]),
-							+coords[j + 2], +coords[j + 4], +coords[j + 3]);
-				}
-				break;
-			case 'z':
-				this.closePath(1e-12);
-				break;
-			}
-			previous = lower;
-		}
-	},
-
-	_canComposite: function() {
-		return !(this.hasFill() && this.hasStroke());
-	},
-
-	_contains: function(point) {
-		var winding = point.isInside(
-				this.getBounds({ internal: true, handle: true }))
-					&& this._getWinding(point);
-		return !!(this.getFillRule() === 'evenodd' ? winding & 1 : winding);
-	},
-
-	getIntersections: function(path, include, _matrix, _returnFirst) {
-		var self = this === path || !path,
-			matrix1 = this._matrix._orNullIfIdentity(),
-			matrix2 = self ? matrix1
-				: (_matrix || path._matrix)._orNullIfIdentity();
-		if (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
-			return [];
-		var curves1 = this.getCurves(),
-			curves2 = self ? curves1 : path.getCurves(),
-			length1 = curves1.length,
-			length2 = self ? length1 : curves2.length,
-			values2 = [],
-			arrays = [],
-			locations,
-			path;
-		for (var i = 0; i < length2; i++)
-			values2[i] = curves2[i].getValues(matrix2);
-		for (var i = 0; i < length1; i++) {
-			var curve1 = curves1[i],
-				values1 = self ? values2[i] : curve1.getValues(matrix1),
-				path1 = curve1.getPath();
-			if (path1 !== path) {
-				path = path1;
-				locations = [];
-				arrays.push(locations);
-			}
-			if (self) {
-				Curve._getSelfIntersection(values1, curve1, locations, {
-					include: include,
-					excludeStart: length1 === 1 &&
-							curve1.getPoint1().equals(curve1.getPoint2())
-				});
-			}
-			for (var j = self ? i + 1 : 0; j < length2; j++) {
-				if (_returnFirst && locations.length)
-					return locations;
-				var curve2 = curves2[j];
-				Curve._getIntersections(
-					values1, values2[j], curve1, curve2, locations,
-					{
-						include: include,
-						excludeStart: self && curve1.getPrevious() === curve2,
-						excludeEnd: self && curve1.getNext() === curve2
-					}
-				);
-			}
-		}
-		locations = [];
-		for (var i = 0, l = arrays.length; i < l; i++) {
-			locations.push.apply(locations, arrays[i]);
-		}
-		return locations;
-	},
-
-	getCrossings: function(path) {
-		return this.getIntersections(path, function(inter) {
-			return inter._overlap || inter.isCrossing();
-		});
-	},
-
-	getNearestLocation: function() {
-		var point = Point.read(arguments),
-			curves = this.getCurves(),
-			minDist = Infinity,
-			minLoc = null;
-		for (var i = 0, l = curves.length; i < l; i++) {
-			var loc = curves[i].getNearestLocation(point);
-			if (loc._distance < minDist) {
-				minDist = loc._distance;
-				minLoc = loc;
-			}
-		}
-		return minLoc;
-	},
-
-	getNearestPoint: function() {
-		var loc = this.getNearestLocation.apply(this, arguments);
-		return loc ? loc.getPoint() : loc;
-	},
-
-	interpolate: function(from, to, factor) {
-		var isPath = !this._children,
-			name = isPath ? '_segments' : '_children',
-			itemsFrom = from[name],
-			itemsTo = to[name],
-			items = this[name];
-		if (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {
-			throw new Error('Invalid operands in interpolate() call: ' +
-					from + ', ' + to);
-		}
-		var current = items.length,
-			length = itemsTo.length;
-		if (current < length) {
-			var ctor = isPath ? Segment : Path;
-			for (var i = current; i < length; i++) {
-				this.add(new ctor());
-			}
-		} else if (current > length) {
-			this[isPath ? 'removeSegments' : 'removeChildren'](length, current);
-		}
-		for (var i = 0; i < length; i++) {
-			items[i].interpolate(itemsFrom[i], itemsTo[i], factor);
-		}
-		if (isPath) {
-			this.setClosed(from._closed);
-			this._changed(9);
-		}
-	},
-
-});
-
-var Path = PathItem.extend({
-	_class: 'Path',
-	_serializeFields: {
-		segments: [],
-		closed: false
-	},
-
-	initialize: function Path(arg) {
-		this._closed = false;
-		this._segments = [];
-		this._version = 0;
-		var segments = Array.isArray(arg)
-			? typeof arg[0] === 'object'
-				? arg
-				: arguments
-			: arg && (arg.size === undefined && (arg.x !== undefined
-					|| arg.point !== undefined))
-				? arguments
-				: null;
-		if (segments && segments.length > 0) {
-			this.setSegments(segments);
-		} else {
-			this._curves = undefined;
-			this._segmentSelection = 0;
-			if (!segments && typeof arg === 'string') {
-				this.setPathData(arg);
-				arg = null;
-			}
-		}
-		this._initialize(!segments && arg);
-	},
-
-	_equals: function(item) {
-		return this._closed === item._closed
-				&& Base.equals(this._segments, item._segments);
-	},
-
-	copyContent: function(source) {
-		this.setSegments(source._segments);
-		this._closed = source._closed;
-		var clockwise = source._clockwise;
-		if (clockwise !== undefined)
-			this._clockwise = clockwise;
-	},
-
-	_changed: function _changed(flags) {
-		_changed.base.call(this, flags);
-		if (flags & 8) {
-			this._length = this._area = this._clockwise = this._monoCurves =
-					undefined;
-			if (flags & 16) {
-				this._version++;
-			} else if (this._curves) {
-			   for (var i = 0, l = this._curves.length; i < l; i++)
-					this._curves[i]._changed();
-			}
-		} else if (flags & 32) {
-			this._bounds = undefined;
-		}
-	},
-
-	getStyle: function() {
-		var parent = this._parent;
-		return (parent instanceof CompoundPath ? parent : this)._style;
-	},
-
-	getSegments: function() {
-		return this._segments;
-	},
-
-	setSegments: function(segments) {
-		var fullySelected = this.isFullySelected();
-		this._segments.length = 0;
-		this._segmentSelection = 0;
-		this._curves = undefined;
-		if (segments && segments.length > 0)
-			this._add(Segment.readAll(segments));
-		if (fullySelected)
-			this.setFullySelected(true);
-	},
-
-	getFirstSegment: function() {
-		return this._segments[0];
-	},
-
-	getLastSegment: function() {
-		return this._segments[this._segments.length - 1];
-	},
-
-	getCurves: function() {
-		var curves = this._curves,
-			segments = this._segments;
-		if (!curves) {
-			var length = this._countCurves();
-			curves = this._curves = new Array(length);
-			for (var i = 0; i < length; i++)
-				curves[i] = new Curve(this, segments[i],
-					segments[i + 1] || segments[0]);
-		}
-		return curves;
-	},
-
-	getFirstCurve: function() {
-		return this.getCurves()[0];
-	},
-
-	getLastCurve: function() {
-		var curves = this.getCurves();
-		return curves[curves.length - 1];
-	},
-
-	isClosed: function() {
-		return this._closed;
-	},
-
-	setClosed: function(closed) {
-		if (this._closed != (closed = !!closed)) {
-			this._closed = closed;
-			if (this._curves) {
-				var length = this._curves.length = this._countCurves();
-				if (closed)
-					this._curves[length - 1] = new Curve(this,
-						this._segments[length - 1], this._segments[0]);
-			}
-			this._changed(25);
-		}
-	}
-}, {
-	beans: true,
-
-	getPathData: function(_matrix, _precision) {
-		var segments = this._segments,
-			length = segments.length,
-			f = new Formatter(_precision),
-			coords = new Array(6),
-			first = true,
-			curX, curY,
-			prevX, prevY,
-			inX, inY,
-			outX, outY,
-			parts = [];
-
-		function addSegment(segment, skipLine) {
-			segment._transformCoordinates(_matrix, coords);
-			curX = coords[0];
-			curY = coords[1];
-			if (first) {
-				parts.push('M' + f.pair(curX, curY));
-				first = false;
-			} else {
-				inX = coords[2];
-				inY = coords[3];
-				if (inX === curX && inY === curY
-						&& outX === prevX && outY === prevY) {
-					if (!skipLine)
-						parts.push('l' + f.pair(curX - prevX, curY - prevY));
-				} else {
-					parts.push('c' + f.pair(outX - prevX, outY - prevY)
-							+ ' ' + f.pair(inX - prevX, inY - prevY)
-							+ ' ' + f.pair(curX - prevX, curY - prevY));
-				}
-			}
-			prevX = curX;
-			prevY = curY;
-			outX = coords[4];
-			outY = coords[5];
-		}
-
-		if (length === 0)
-			return '';
-
-		for (var i = 0; i < length; i++)
-			addSegment(segments[i]);
-		if (this._closed && length > 0) {
-			addSegment(segments[0], true);
-			parts.push('z');
-		}
-		return parts.join('');
-	},
-
-	isEmpty: function() {
-		return this._segments.length === 0;
-	},
-
-	_transformContent: function(matrix) {
-		var segments = this._segments,
-			coords = new Array(6);
-		for (var i = 0, l = segments.length; i < l; i++)
-			segments[i]._transformCoordinates(matrix, coords, true);
-		return true;
-	},
-
-	_add: function(segs, index) {
-		var segments = this._segments,
-			curves = this._curves,
-			amount = segs.length,
-			append = index == null,
-			index = append ? segments.length : index;
-		for (var i = 0; i < amount; i++) {
-			var segment = segs[i];
-			if (segment._path)
-				segment = segs[i] = segment.clone();
-			segment._path = this;
-			segment._index = index + i;
-			if (segment._selection)
-				this._updateSelection(segment, 0, segment._selection);
-		}
-		if (append) {
-			segments.push.apply(segments, segs);
-		} else {
-			segments.splice.apply(segments, [index, 0].concat(segs));
-			for (var i = index + amount, l = segments.length; i < l; i++)
-				segments[i]._index = i;
-		}
-		if (curves) {
-			var total = this._countCurves(),
-				start = index > 0 && index + amount - 1 === total ? index - 1
-					: index,
-				insert = start,
-				end = Math.min(start + amount, total);
-			if (segs._curves) {
-				curves.splice.apply(curves, [start, 0].concat(segs._curves));
-				insert += segs._curves.length;
-			}
-			for (var i = insert; i < end; i++)
-				curves.splice(i, 0, new Curve(this, null, null));
-			this._adjustCurves(start, end);
-		}
-		this._changed(25);
-		return segs;
-	},
-
-	_adjustCurves: function(start, end) {
-		var segments = this._segments,
-			curves = this._curves,
-			curve;
-		for (var i = start; i < end; i++) {
-			curve = curves[i];
-			curve._path = this;
-			curve._segment1 = segments[i];
-			curve._segment2 = segments[i + 1] || segments[0];
-			curve._changed();
-		}
-		if (curve = curves[this._closed && start === 0 ? segments.length - 1
-				: start - 1]) {
-			curve._segment2 = segments[start] || segments[0];
-			curve._changed();
-		}
-		if (curve = curves[end]) {
-			curve._segment1 = segments[end];
-			curve._changed();
-		}
-	},
-
-	_countCurves: function() {
-		var length = this._segments.length;
-		return !this._closed && length > 0 ? length - 1 : length;
-	},
-
-	add: function(segment1 ) {
-		return arguments.length > 1 && typeof segment1 !== 'number'
-			? this._add(Segment.readAll(arguments))
-			: this._add([ Segment.read(arguments) ])[0];
-	},
-
-	insert: function(index, segment1 ) {
-		return arguments.length > 2 && typeof segment1 !== 'number'
-			? this._add(Segment.readAll(arguments, 1), index)
-			: this._add([ Segment.read(arguments, 1) ], index)[0];
-	},
-
-	addSegment: function() {
-		return this._add([ Segment.read(arguments) ])[0];
-	},
-
-	insertSegment: function(index ) {
-		return this._add([ Segment.read(arguments, 1) ], index)[0];
-	},
-
-	addSegments: function(segments) {
-		return this._add(Segment.readAll(segments));
-	},
-
-	insertSegments: function(index, segments) {
-		return this._add(Segment.readAll(segments), index);
-	},
-
-	removeSegment: function(index) {
-		return this.removeSegments(index, index + 1)[0] || null;
-	},
-
-	removeSegments: function(start, end, _includeCurves) {
-		start = start || 0;
-		end = Base.pick(end, this._segments.length);
-		var segments = this._segments,
-			curves = this._curves,
-			count = segments.length,
-			removed = segments.splice(start, end - start),
-			amount = removed.length;
-		if (!amount)
-			return removed;
-		for (var i = 0; i < amount; i++) {
-			var segment = removed[i];
-			if (segment._selection)
-				this._updateSelection(segment, segment._selection, 0);
-			segment._index = segment._path = null;
-		}
-		for (var i = start, l = segments.length; i < l; i++)
-			segments[i]._index = i;
-		if (curves) {
-			var index = start > 0 && end === count + (this._closed ? 1 : 0)
-					? start - 1
-					: start,
-				curves = curves.splice(index, amount);
-			for (var i = curves.length - 1; i >= 0; i--)
-				curves[i]._path = null;
-			if (_includeCurves)
-				removed._curves = curves.slice(1);
-			this._adjustCurves(index, index);
-		}
-		this._changed(25);
-		return removed;
-	},
-
-	clear: '#removeSegments',
-
-	hasHandles: function() {
-		var segments = this._segments;
-		for (var i = 0, l = segments.length; i < l; i++) {
-			if (segments[i].hasHandles())
-				return true;
-		}
-		return false;
-	},
-
-	clearHandles: function() {
-		var segments = this._segments;
-		for (var i = 0, l = segments.length; i < l; i++)
-			segments[i].clearHandles();
-	},
-
-	getLength: function() {
-		if (this._length == null) {
-			var curves = this.getCurves(),
-				length = 0;
-			for (var i = 0, l = curves.length; i < l; i++)
-				length += curves[i].getLength();
-			this._length = length;
-		}
-		return this._length;
-	},
-
-	getArea: function(_closed) {
-		var cached = _closed === undefined,
-			area = this._area;
-		if (!cached || area == null) {
-			var segments = this._segments,
-				count = segments.length,
-				closed = cached ? this._closed : _closed,
-				last = count - 1;
-			area = 0;
-			for (var i = 0, l = closed ? count : last; i < l; i++) {
-				area += Curve.getArea(Curve.getValues(
-						segments[i], segments[i < last ? i + 1 : 0]));
-			}
-			if (cached)
-				this._area = area;
-		}
-		return area;
-	},
-
-	isClockwise: function() {
-		if (this._clockwise !== undefined)
-			return this._clockwise;
-		return this.getArea() >= 0;
-	},
-
-	setClockwise: function(clockwise) {
-		if (this.isClockwise() != (clockwise = !!clockwise))
-			this.reverse();
-		this._clockwise = clockwise;
-	},
-
-	isFullySelected: function() {
-		var length = this._segments.length;
-		return this.isSelected() && length > 0 && this._segmentSelection
-				=== length * 7;
-	},
-
-	setFullySelected: function(selected) {
-		if (selected)
-			this._selectSegments(true);
-		this.setSelected(selected);
-	},
-
-	setSelection: function setSelection(selection) {
-		if (!(selection & 1))
-			this._selectSegments(false);
-		setSelection.base.call(this, selection);
-	},
-
-	_selectSegments: function(selected) {
-		var segments = this._segments,
-			length = segments.length,
-			selection = selected ? 7 : 0;
-		this._segmentSelection = selection * length;
-		for (var i = 0; i < length; i++)
-			segments[i]._selection = selection;
-	},
-
-	_updateSelection: function(segment, oldSelection, newSelection) {
-		segment._selection = newSelection;
-		var selection = this._segmentSelection += newSelection - oldSelection;
-		if (selection > 0)
-			this.setSelected(true);
-	},
-
-	splitAt: function(location) {
-		var loc = typeof location === 'number'
-				? this.getLocationAt(location) : location,
-			index = loc && loc.index,
-			time = loc && loc.time,
-			tMin = 4e-7,
-			tMax = 1 - tMin;
-		if (time >= tMax) {
-			index++;
-			time = 0;
-		}
-		var curves = this.getCurves();
-		if (index >= 0 && index < curves.length) {
-			if (time >= tMin) {
-				curves[index++].divideAtTime(time);
-			}
-			var segs = this.removeSegments(index, this._segments.length, true),
-				path;
-			if (this._closed) {
-				this.setClosed(false);
-				path = this;
-			} else {
-				path = new Path(Item.NO_INSERT);
-				path.insertAbove(this, true);
-				path.copyAttributes(this);
-			}
-			path._add(segs, 0);
-			this.addSegment(segs[0]);
-			return path;
-		}
-		return null;
-	},
-
-	split: function(index, time) {
-		var curve,
-			location = time === undefined ? index
-				: (curve = this.getCurves()[index])
-					&& curve.getLocationAtTime(time);
-		return location != null ? this.splitAt(location) : null;
-	},
-
-	join: function(path, tolerance) {
-		var epsilon = tolerance || 0;
-		if (path && path !== this) {
-			var segments = path._segments,
-				last1 = this.getLastSegment(),
-				last2 = path.getLastSegment();
-			if (!last2)
-				return this;
-			if (last1 && last1._point.isClose(last2._point, epsilon))
-				path.reverse();
-			var first2 = path.getFirstSegment();
-			if (last1 && last1._point.isClose(first2._point, epsilon)) {
-				last1.setHandleOut(first2._handleOut);
-				this._add(segments.slice(1));
-			} else {
-				var first1 = this.getFirstSegment();
-				if (first1 && first1._point.isClose(first2._point, epsilon))
-					path.reverse();
-				last2 = path.getLastSegment();
-				if (first1 && first1._point.isClose(last2._point, epsilon)) {
-					first1.setHandleIn(last2._handleIn);
-					this._add(segments.slice(0, segments.length - 1), 0);
-				} else {
-					this._add(segments.slice());
-				}
-			}
-			if (path._closed)
-				this._add([segments[0]]);
-			path.remove();
-		}
-		var first = this.getFirstSegment(),
-			last = this.getLastSegment();
-		if (first !== last && first._point.isClose(last._point, epsilon)) {
-			first.setHandleIn(last._handleIn);
-			last.remove();
-			this.setClosed(true);
-		}
-		return this;
-	},
-
-	reduce: function(options) {
-		var curves = this.getCurves(),
-			simplify = options && options.simplify,
-			tolerance = simplify ? 2e-7 : 0;
-		for (var i = curves.length - 1; i >= 0; i--) {
-			var curve = curves[i];
-			if (!curve.hasHandles() && (curve.getLength() < tolerance
-					|| simplify && curve.isCollinear(curve.getNext())))
-				curve.remove();
-		}
-		return this;
-	},
-
-	reverse: function() {
-		this._segments.reverse();
-		for (var i = 0, l = this._segments.length; i < l; i++) {
-			var segment = this._segments[i];
-			var handleIn = segment._handleIn;
-			segment._handleIn = segment._handleOut;
-			segment._handleOut = handleIn;
-			segment._index = i;
-		}
-		this._curves = null;
-		if (this._clockwise !== undefined)
-			this._clockwise = !this._clockwise;
-		this._changed(9);
-	},
-
-	flatten: function(flatness) {
-		var iterator = new PathIterator(this, flatness || 0.25, 256, true),
-			parts = iterator.parts,
-			length = parts.length,
-			segments = [];
-		for (var i = 0; i < length; i++) {
-			segments.push(new Segment(parts[i].curve.slice(0, 2)));
-		}
-		if (!this._closed && length > 0) {
-			segments.push(new Segment(parts[length - 1].curve.slice(6)));
-		}
-		this.setSegments(segments);
-	},
-
-	simplify: function(tolerance) {
-		var segments = new PathFitter(this).fit(tolerance || 2.5);
-		if (segments)
-			this.setSegments(segments);
-		return !!segments;
-	},
-
-	smooth: function(options) {
-		var that = this,
-			opts = options || {},
-			type = opts.type || 'asymmetric',
-			segments = this._segments,
-			length = segments.length,
-			closed = this._closed;
-
-		function getIndex(value, _default) {
-			var index = value && value.index;
-			if (index != null) {
-				var path = value.path;
-				if (path && path !== that)
-					throw new Error(value._class + ' ' + index + ' of ' + path
-							+ ' is not part of ' + that);
-				if (_default && value instanceof Curve)
-					index++;
-			} else {
-				index = typeof value === 'number' ? value : _default;
-			}
-			return Math.min(index < 0 && closed
-					? index % length
-					: index < 0 ? index + length : index, length - 1);
-		}
-
-		var loop = closed && opts.from === undefined && opts.to === undefined,
-			from = getIndex(opts.from, 0),
-			to = getIndex(opts.to, length - 1);
-
-		if (from > to) {
-			if (closed) {
-				from -= length;
-			} else {
-				var tmp = from;
-				from = to;
-				to = tmp;
-			}
-		}
-		if (/^(?:asymmetric|continuous)$/.test(type)) {
-			var asymmetric = type === 'asymmetric',
-				min = Math.min,
-				amount = to - from + 1,
-				n = amount - 1,
-				padding = loop ? min(amount, 4) : 1,
-				paddingLeft = padding,
-				paddingRight = padding,
-				knots = [];
-			if (!closed) {
-				paddingLeft = min(1, from);
-				paddingRight = min(1, length - to - 1);
-			}
-			n += paddingLeft + paddingRight;
-			if (n <= 1)
-				return;
-			for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
-				knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
-			}
-
-			var x = knots[0]._x + 2 * knots[1]._x,
-				y = knots[0]._y + 2 * knots[1]._y,
-				f = 2,
-				n_1 = n - 1,
-				rx = [x],
-				ry = [y],
-				rf = [f],
-				px = [],
-				py = [];
-			for (var i = 1; i < n; i++) {
-				var internal = i < n_1,
-					a = internal ? 1 : asymmetric ? 1 : 2,
-					b = internal ? 4 : asymmetric ? 2 : 7,
-					u = internal ? 4 : asymmetric ? 3 : 8,
-					v = internal ? 2 : asymmetric ? 0 : 1,
-					m = a / f;
-				f = rf[i] = b - m;
-				x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
-				y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
-			}
-
-			px[n_1] = rx[n_1] / rf[n_1];
-			py[n_1] = ry[n_1] / rf[n_1];
-			for (var i = n - 2; i >= 0; i--) {
-				px[i] = (rx[i] - px[i + 1]) / rf[i];
-				py[i] = (ry[i] - py[i + 1]) / rf[i];
-			}
-			px[n] = (3 * knots[n]._x - px[n_1]) / 2;
-			py[n] = (3 * knots[n]._y - py[n_1]) / 2;
-
-			for (var i = paddingLeft, max = n - paddingRight, j = from;
-					i <= max; i++, j++) {
-				var segment = segments[j < 0 ? j + length : j],
-					pt = segment._point,
-					hx = px[i] - pt._x,
-					hy = py[i] - pt._y;
-				if (loop || i < max)
-					segment.setHandleOut(hx, hy);
-				if (loop || i > paddingLeft)
-					segment.setHandleIn(-hx, -hy);
-			}
-		} else {
-			for (var i = from; i <= to; i++) {
-				segments[i < 0 ? i + length : i].smooth(opts,
-						!loop && i === from, !loop && i === to);
-			}
-		}
-	},
-
-	toShape: function(insert) {
-		if (!this._closed)
-			return null;
-
-		var segments = this._segments,
-			type,
-			size,
-			radius,
-			topCenter;
-
-		function isCollinear(i, j) {
-			var seg1 = segments[i],
-				seg2 = seg1.getNext(),
-				seg3 = segments[j],
-				seg4 = seg3.getNext();
-			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
-					&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
-					&& seg2._point.subtract(seg1._point).isCollinear(
-						seg4._point.subtract(seg3._point));
-		}
-
-		function isOrthogonal(i) {
-			var seg2 = segments[i],
-				seg1 = seg2.getPrevious(),
-				seg3 = seg2.getNext();
-			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
-					&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
-					&& seg2._point.subtract(seg1._point).isOrthogonal(
-						seg3._point.subtract(seg2._point));
-		}
-
-		function isArc(i) {
-			var seg1 = segments[i],
-				seg2 = seg1.getNext(),
-				handle1 = seg1._handleOut,
-				handle2 = seg2._handleIn,
-				kappa = 0.5522847498307936;
-			if (handle1.isOrthogonal(handle2)) {
-				var pt1 = seg1._point,
-					pt2 = seg2._point,
-					corner = new Line(pt1, handle1, true).intersect(
-							new Line(pt2, handle2, true), true);
-				return corner && Numerical.isZero(handle1.getLength() /
-						corner.subtract(pt1).getLength() - kappa)
-					&& Numerical.isZero(handle2.getLength() /
-						corner.subtract(pt2).getLength() - kappa);
-			}
-			return false;
-		}
-
-		function getDistance(i, j) {
-			return segments[i]._point.getDistance(segments[j]._point);
-		}
-
-		if (!this.hasHandles() && segments.length === 4
-				&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {
-			type = Shape.Rectangle;
-			size = new Size(getDistance(0, 3), getDistance(0, 1));
-			topCenter = segments[1]._point.add(segments[2]._point).divide(2);
-		} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
-				&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {
-			type = Shape.Rectangle;
-			size = new Size(getDistance(1, 6), getDistance(0, 3));
-			radius = size.subtract(new Size(getDistance(0, 7),
-					getDistance(1, 2))).divide(2);
-			topCenter = segments[3]._point.add(segments[4]._point).divide(2);
-		} else if (segments.length === 4
-				&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
-			if (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {
-				type = Shape.Circle;
-				radius = getDistance(0, 2) / 2;
-			} else {
-				type = Shape.Ellipse;
-				radius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);
-			}
-			topCenter = segments[1]._point;
-		}
-
-		if (type) {
-			var center = this.getPosition(true),
-				shape = new type({
-					center: center,
-					size: size,
-					radius: radius,
-					insert: false
-				});
-			shape.copyAttributes(this, true);
-			shape._matrix.prepend(this._matrix);
-			shape.rotate(topCenter.subtract(center).getAngle() + 90);
-			if (insert === undefined || insert)
-				shape.insertAbove(this);
-			return shape;
-		}
-		return null;
-	},
-
-	toPath: '#clone',
-
-	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
-		var that = this,
-			style = this.getStyle(),
-			segments = this._segments,
-			numSegments = segments.length,
-			closed = this._closed,
-			tolerancePadding = options._tolerancePadding,
-			strokePadding = tolerancePadding,
-			join, cap, miterLimit,
-			area, loc, res,
-			hitStroke = options.stroke && style.hasStroke(),
-			hitFill = options.fill && style.hasFill(),
-			hitCurves = options.curves,
-			strokeRadius = hitStroke
-					? style.getStrokeWidth() / 2
-					: hitFill && options.tolerance > 0 || hitCurves
-						? 0 : null;
-		if (strokeRadius !== null) {
-			if (strokeRadius > 0) {
-				join = style.getStrokeJoin();
-				cap = style.getStrokeCap();
-				miterLimit = strokeRadius * style.getMiterLimit();
-				strokePadding = strokePadding.add(
-					Path._getStrokePadding(strokeRadius, strokeMatrix));
-			} else {
-				join = cap = 'round';
-			}
-		}
-
-		function isCloseEnough(pt, padding) {
-			return point.subtract(pt).divide(padding).length <= 1;
-		}
-
-		function checkSegmentPoint(seg, pt, name) {
-			if (!options.selected || pt.isSelected()) {
-				var anchor = seg._point;
-				if (pt !== anchor)
-					pt = pt.add(anchor);
-				if (isCloseEnough(pt, strokePadding)) {
-					return new HitResult(name, that, {
-						segment: seg,
-						point: pt
-					});
-				}
-			}
-		}
-
-		function checkSegmentPoints(seg, ends) {
-			return (ends || options.segments)
-				&& checkSegmentPoint(seg, seg._point, 'segment')
-				|| (!ends && options.handles) && (
-					checkSegmentPoint(seg, seg._handleIn, 'handle-in') ||
-					checkSegmentPoint(seg, seg._handleOut, 'handle-out'));
-		}
-
-		function addToArea(point) {
-			area.add(point);
-		}
-
-		function checkSegmentStroke(segment) {
-			if (join !== 'round' || cap !== 'round') {
-				area = new Path({ internal: true, closed: true });
-				if (closed || segment._index > 0
-						&& segment._index < numSegments - 1) {
-					if (join !== 'round' && (segment._handleIn.isZero()
-							|| segment._handleOut.isZero()))
-						Path._addBevelJoin(segment, join, strokeRadius,
-							   miterLimit, null, strokeMatrix, addToArea, true);
-				} else if (cap !== 'round') {
-					Path._addSquareCap(segment, cap, strokeRadius, null,
-							strokeMatrix, addToArea, true);
-				}
-				if (!area.isEmpty()) {
-					var loc;
-					return area.contains(point)
-						|| (loc = area.getNearestLocation(point))
-							&& isCloseEnough(loc.getPoint(), tolerancePadding);
-				}
-			}
-			return isCloseEnough(segment._point, strokePadding);
-		}
-
-		if (options.ends && !options.segments && !closed) {
-			if (res = checkSegmentPoints(segments[0], true)
-					|| checkSegmentPoints(segments[numSegments - 1], true))
-				return res;
-		} else if (options.segments || options.handles) {
-			for (var i = 0; i < numSegments; i++)
-				if (res = checkSegmentPoints(segments[i]))
-					return res;
-		}
-		if (strokeRadius !== null) {
-			loc = this.getNearestLocation(point);
-			if (loc) {
-				var time = loc.getTime();
-				if (time === 0 || time === 1 && numSegments > 1) {
-					if (!checkSegmentStroke(loc.getSegment()))
-						loc = null;
-				} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
-					loc = null;
-				}
-			}
-			if (!loc && join === 'miter' && numSegments > 1) {
-				for (var i = 0; i < numSegments; i++) {
-					var segment = segments[i];
-					if (point.getDistance(segment._point) <= miterLimit
-							&& checkSegmentStroke(segment)) {
-						loc = segment.getLocation();
-						break;
-					}
-				}
-			}
-		}
-		return !loc && hitFill && this._contains(point)
-				|| loc && !hitStroke && !hitCurves
-					? new HitResult('fill', this)
-					: loc
-						? new HitResult(hitStroke ? 'stroke' : 'curve', this, {
-							location: loc,
-							point: loc.getPoint()
-						})
-						: null;
-	}
-
-}, Base.each(Curve._evaluateMethods,
-	function(name) {
-		this[name + 'At'] = function(offset) {
-			var loc = this.getLocationAt(offset);
-			return loc && loc[name]();
-		};
-	},
-{
-	beans: false,
-
-	getLocationOf: function() {
-		var point = Point.read(arguments),
-			curves = this.getCurves();
-		for (var i = 0, l = curves.length; i < l; i++) {
-			var loc = curves[i].getLocationOf(point);
-			if (loc)
-				return loc;
-		}
-		return null;
-	},
-
-	getOffsetOf: function() {
-		var loc = this.getLocationOf.apply(this, arguments);
-		return loc ? loc.getOffset() : null;
-	},
-
-	getLocationAt: function(offset) {
-		var curves = this.getCurves(),
-			length = 0;
-		for (var i = 0, l = curves.length; i < l; i++) {
-			var start = length,
-				curve = curves[i];
-			length += curve.getLength();
-			if (length > offset) {
-				return curve.getLocationAt(offset - start);
-			}
-		}
-		if (curves.length > 0 && offset <= this.getLength())
-			return new CurveLocation(curves[curves.length - 1], 1);
-		return null;
-	}
-
-}),
-new function() {
-
-	function drawHandles(ctx, segments, matrix, size) {
-		var half = size / 2,
-			coords = new Array(6),
-			pX, pY;
-
-		function drawHandle(index) {
-			var hX = coords[index],
-				hY = coords[index + 1];
-			if (pX != hX || pY != hY) {
-				ctx.beginPath();
-				ctx.moveTo(pX, pY);
-				ctx.lineTo(hX, hY);
-				ctx.stroke();
-				ctx.beginPath();
-				ctx.arc(hX, hY, half, 0, Math.PI * 2, true);
-				ctx.fill();
-			}
-		}
-
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var segment = segments[i],
-				selection = segment._selection;
-			segment._transformCoordinates(matrix, coords);
-			pX = coords[0];
-			pY = coords[1];
-			if (selection & 2)
-				drawHandle(2);
-			if (selection & 4)
-				drawHandle(4);
-			ctx.fillRect(pX - half, pY - half, size, size);
-			if (!(selection & 1)) {
-				var fillStyle = ctx.fillStyle;
-				ctx.fillStyle = '#ffffff';
-				ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);
-				ctx.fillStyle = fillStyle;
-			}
-		}
-	}
-
-	function drawSegments(ctx, path, matrix) {
-		var segments = path._segments,
-			length = segments.length,
-			coords = new Array(6),
-			first = true,
-			curX, curY,
-			prevX, prevY,
-			inX, inY,
-			outX, outY;
-
-		function drawSegment(segment) {
-			if (matrix) {
-				segment._transformCoordinates(matrix, coords);
-				curX = coords[0];
-				curY = coords[1];
-			} else {
-				var point = segment._point;
-				curX = point._x;
-				curY = point._y;
-			}
-			if (first) {
-				ctx.moveTo(curX, curY);
-				first = false;
-			} else {
-				if (matrix) {
-					inX = coords[2];
-					inY = coords[3];
-				} else {
-					var handle = segment._handleIn;
-					inX = curX + handle._x;
-					inY = curY + handle._y;
-				}
-				if (inX === curX && inY === curY
-						&& outX === prevX && outY === prevY) {
-					ctx.lineTo(curX, curY);
-				} else {
-					ctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);
-				}
-			}
-			prevX = curX;
-			prevY = curY;
-			if (matrix) {
-				outX = coords[4];
-				outY = coords[5];
-			} else {
-				var handle = segment._handleOut;
-				outX = prevX + handle._x;
-				outY = prevY + handle._y;
-			}
-		}
-
-		for (var i = 0; i < length; i++)
-			drawSegment(segments[i]);
-		if (path._closed && length > 0)
-			drawSegment(segments[0]);
-	}
-
-	return {
-		_draw: function(ctx, param, viewMatrix, strokeMatrix) {
-			var dontStart = param.dontStart,
-				dontPaint = param.dontFinish || param.clip,
-				style = this.getStyle(),
-				hasFill = style.hasFill(),
-				hasStroke = style.hasStroke(),
-				dashArray = style.getDashArray(),
-				dashLength = !paper.support.nativeDash && hasStroke
-						&& dashArray && dashArray.length;
-
-			if (!dontStart)
-				ctx.beginPath();
-
-			if (hasFill || hasStroke && !dashLength || dontPaint) {
-				drawSegments(ctx, this, strokeMatrix);
-				if (this._closed)
-					ctx.closePath();
-			}
-
-			function getOffset(i) {
-				return dashArray[((i % dashLength) + dashLength) % dashLength];
-			}
-
-			if (!dontPaint && (hasFill || hasStroke)) {
-				this._setStyles(ctx, param, viewMatrix);
-				if (hasFill) {
-					ctx.fill(style.getFillRule());
-					ctx.shadowColor = 'rgba(0,0,0,0)';
-				}
-				if (hasStroke) {
-					if (dashLength) {
-						if (!dontStart)
-							ctx.beginPath();
-						var iterator = new PathIterator(this, 0.25, 32, false,
-								strokeMatrix),
-							length = iterator.length,
-							from = -style.getDashOffset(), to,
-							i = 0;
-						from = from % length;
-						while (from > 0) {
-							from -= getOffset(i--) + getOffset(i--);
-						}
-						while (from < length) {
-							to = from + getOffset(i++);
-							if (from > 0 || to > 0)
-								iterator.drawPart(ctx,
-										Math.max(from, 0), Math.max(to, 0));
-							from = to + getOffset(i++);
-						}
-					}
-					ctx.stroke();
-				}
-			}
-		},
-
-		_drawSelected: function(ctx, matrix) {
-			ctx.beginPath();
-			drawSegments(ctx, this, matrix);
-			ctx.stroke();
-			drawHandles(ctx, this._segments, matrix, paper.settings.handleSize);
-		}
-	};
-},
-new function() {
-	function getCurrentSegment(that) {
-		var segments = that._segments;
-		if (segments.length === 0)
-			throw new Error('Use a moveTo() command first');
-		return segments[segments.length - 1];
-	}
-
-	return {
-		moveTo: function() {
-			var segments = this._segments;
-			if (segments.length === 1)
-				this.removeSegment(0);
-			if (!segments.length)
-				this._add([ new Segment(Point.read(arguments)) ]);
-		},
-
-		moveBy: function() {
-			throw new Error('moveBy() is unsupported on Path items.');
-		},
-
-		lineTo: function() {
-			this._add([ new Segment(Point.read(arguments)) ]);
-		},
-
-		cubicCurveTo: function() {
-			var handle1 = Point.read(arguments),
-				handle2 = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this);
-			current.setHandleOut(handle1.subtract(current._point));
-			this._add([ new Segment(to, handle2.subtract(to)) ]);
-		},
-
-		quadraticCurveTo: function() {
-			var handle = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.cubicCurveTo(
-				handle.add(current.subtract(handle).multiply(1 / 3)),
-				handle.add(to.subtract(handle).multiply(1 / 3)),
-				to
-			);
-		},
-
-		curveTo: function() {
-			var through = Point.read(arguments),
-				to = Point.read(arguments),
-				t = Base.pick(Base.read(arguments), 0.5),
-				t1 = 1 - t,
-				current = getCurrentSegment(this)._point,
-				handle = through.subtract(current.multiply(t1 * t1))
-					.subtract(to.multiply(t * t)).divide(2 * t * t1);
-			if (handle.isNaN())
-				throw new Error(
-					'Cannot put a curve through points with parameter = ' + t);
-			this.quadraticCurveTo(handle, to);
-		},
-
-		arcTo: function() {
-			var current = getCurrentSegment(this),
-				from = current._point,
-				to = Point.read(arguments),
-				through,
-				peek = Base.peek(arguments),
-				clockwise = Base.pick(peek, true),
-				center, extent, vector, matrix;
-			if (typeof clockwise === 'boolean') {
-				var middle = from.add(to).divide(2),
-				through = middle.add(middle.subtract(from).rotate(
-						clockwise ? -90 : 90));
-			} else if (Base.remain(arguments) <= 2) {
-				through = to;
-				to = Point.read(arguments);
-			} else {
-				var radius = Size.read(arguments),
-					isZero = Numerical.isZero;
-				if (isZero(radius.width) || isZero(radius.height))
-					return this.lineTo(to);
-				var rotation = Base.read(arguments),
-					clockwise = !!Base.read(arguments),
-					large = !!Base.read(arguments),
-					middle = from.add(to).divide(2),
-					pt = from.subtract(middle).rotate(-rotation),
-					x = pt.x,
-					y = pt.y,
-					abs = Math.abs,
-					rx = abs(radius.width),
-					ry = abs(radius.height),
-					rxSq = rx * rx,
-					rySq = ry * ry,
-					xSq = x * x,
-					ySq = y * y;
-				var factor = Math.sqrt(xSq / rxSq + ySq / rySq);
-				if (factor > 1) {
-					rx *= factor;
-					ry *= factor;
-					rxSq = rx * rx;
-					rySq = ry * ry;
-				}
-				factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
-						(rxSq * ySq + rySq * xSq);
-				if (abs(factor) < 1e-12)
-					factor = 0;
-				if (factor < 0)
-					throw new Error(
-							'Cannot create an arc with the given arguments');
-				center = new Point(rx * y / ry, -ry * x / rx)
-						.multiply((large === clockwise ? -1 : 1)
-							* Math.sqrt(factor))
-						.rotate(rotation).add(middle);
-				matrix = new Matrix().translate(center).rotate(rotation)
-						.scale(rx, ry);
-				vector = matrix._inverseTransform(from);
-				extent = vector.getDirectedAngle(matrix._inverseTransform(to));
-				if (!clockwise && extent > 0)
-					extent -= 360;
-				else if (clockwise && extent < 0)
-					extent += 360;
-			}
-			if (through) {
-				var l1 = new Line(from.add(through).divide(2),
-							through.subtract(from).rotate(90), true),
-					l2 = new Line(through.add(to).divide(2),
-							to.subtract(through).rotate(90), true),
-					line = new Line(from, to),
-					throughSide = line.getSide(through);
-				center = l1.intersect(l2, true);
-				if (!center) {
-					if (!throughSide)
-						return this.lineTo(to);
-					throw new Error(
-							'Cannot create an arc with the given arguments');
-				}
-				vector = from.subtract(center);
-				extent = vector.getDirectedAngle(to.subtract(center));
-				var centerSide = line.getSide(center);
-				if (centerSide === 0) {
-					extent = throughSide * Math.abs(extent);
-				} else if (throughSide === centerSide) {
-					extent += extent < 0 ? 360 : -360;
-				}
-			}
-			var ext = Math.abs(extent),
-				count = ext >= 360 ? 4 : Math.ceil(ext / 90),
-				inc = extent / count,
-				half = inc * Math.PI / 360,
-				z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),
-				segments = [];
-			for (var i = 0; i <= count; i++) {
-				var pt = to,
-					out = null;
-				if (i < count) {
-					out = vector.rotate(90).multiply(z);
-					if (matrix) {
-						pt = matrix._transformPoint(vector);
-						out = matrix._transformPoint(vector.add(out))
-								.subtract(pt);
-					} else {
-						pt = center.add(vector);
-					}
-				}
-				if (i === 0) {
-					current.setHandleOut(out);
-				} else {
-					var _in = vector.rotate(-90).multiply(z);
-					if (matrix) {
-						_in = matrix._transformPoint(vector.add(_in))
-								.subtract(pt);
-					}
-					segments.push(new Segment(pt, _in, out));
-				}
-				vector = vector.rotate(inc);
-			}
-			this._add(segments);
-		},
-
-		lineBy: function() {
-			var to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.lineTo(current.add(to));
-		},
-
-		curveBy: function() {
-			var through = Point.read(arguments),
-				to = Point.read(arguments),
-				parameter = Base.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.curveTo(current.add(through), current.add(to), parameter);
-		},
-
-		cubicCurveBy: function() {
-			var handle1 = Point.read(arguments),
-				handle2 = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.cubicCurveTo(current.add(handle1), current.add(handle2),
-					current.add(to));
-		},
-
-		quadraticCurveBy: function() {
-			var handle = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.quadraticCurveTo(current.add(handle), current.add(to));
-		},
-
-		arcBy: function() {
-			var current = getCurrentSegment(this)._point,
-				point = current.add(Point.read(arguments)),
-				clockwise = Base.pick(Base.peek(arguments), true);
-			if (typeof clockwise === 'boolean') {
-				this.arcTo(point, clockwise);
-			} else {
-				this.arcTo(point, current.add(Point.read(arguments)));
-			}
-		},
-
-		closePath: function(tolerance) {
-			this.setClosed(true);
-			this.join(this, tolerance);
-		}
-	};
-}, {
-
-	_getBounds: function(matrix, options) {
-		var method = options.handle
-				? 'getHandleBounds'
-				: options.stroke
-				? 'getStrokeBounds'
-				: 'getBounds';
-		return Path[method](this._segments, this._closed, this, matrix, options);
-	},
-
-statics: {
-	getBounds: function(segments, closed, path, matrix, options, strokePadding) {
-		var first = segments[0];
-		if (!first)
-			return new Rectangle();
-		var coords = new Array(6),
-			prevCoords = first._transformCoordinates(matrix, new Array(6)),
-			min = prevCoords.slice(0, 2),
-			max = min.slice(),
-			roots = new Array(2);
-
-		function processSegment(segment) {
-			segment._transformCoordinates(matrix, coords);
-			for (var i = 0; i < 2; i++) {
-				Curve._addBounds(
-					prevCoords[i],
-					prevCoords[i + 4],
-					coords[i + 2],
-					coords[i],
-					i, strokePadding ? strokePadding[i] : 0, min, max, roots);
-			}
-			var tmp = prevCoords;
-			prevCoords = coords;
-			coords = tmp;
-		}
-
-		for (var i = 1, l = segments.length; i < l; i++)
-			processSegment(segments[i]);
-		if (closed)
-			processSegment(first);
-		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
-	},
-
-	getStrokeBounds: function(segments, closed, path, matrix, options) {
-		var style = path.getStyle(),
-			stroke = style.hasStroke(),
-			strokeWidth = style.getStrokeWidth(),
-			strokeMatrix = stroke && path._getStrokeMatrix(matrix, options),
-			strokePadding = stroke && Path._getStrokePadding(strokeWidth,
-				strokeMatrix),
-			bounds = Path.getBounds(segments, closed, path, matrix, options,
-				strokePadding);
-		if (!stroke)
-			return bounds;
-		var strokeRadius = strokeWidth / 2,
-			join = style.getStrokeJoin(),
-			cap = style.getStrokeCap(),
-			miterLimit = strokeRadius * style.getMiterLimit(),
-			joinBounds = new Rectangle(new Size(strokePadding));
-
-		function addPoint(point) {
-			bounds = bounds.include(point);
-		}
-
-		function addRound(segment) {
-			bounds = bounds.unite(
-					joinBounds.setCenter(segment._point.transform(matrix)));
-		}
-
-		function addJoin(segment, join) {
-			var handleIn = segment._handleIn,
-				handleOut = segment._handleOut;
-			if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
-					&& handleIn.isCollinear(handleOut)) {
-				addRound(segment);
-			} else {
-				Path._addBevelJoin(segment, join, strokeRadius, miterLimit,
-						matrix, strokeMatrix, addPoint);
-			}
-		}
-
-		function addCap(segment, cap) {
-			if (cap === 'round') {
-				addRound(segment);
-			} else {
-				Path._addSquareCap(segment, cap, strokeRadius, matrix,
-						strokeMatrix, addPoint);
-			}
-		}
-
-		var length = segments.length - (closed ? 0 : 1);
-		for (var i = 1; i < length; i++)
-			addJoin(segments[i], join);
-		if (closed) {
-			addJoin(segments[0], join);
-		} else if (length > 0) {
-			addCap(segments[0], cap);
-			addCap(segments[segments.length - 1], cap);
-		}
-		return bounds;
-	},
-
-	_getStrokePadding: function(radius, matrix) {
-		if (!matrix)
-			return [radius, radius];
-		var hor = new Point(radius, 0).transform(matrix),
-			ver = new Point(0, radius).transform(matrix),
-			phi = hor.getAngleInRadians(),
-			a = hor.getLength(),
-			b = ver.getLength();
-		var sin = Math.sin(phi),
-			cos = Math.cos(phi),
-			tan = Math.tan(phi),
-			tx = Math.atan2(b * tan, a),
-			ty = Math.atan2(b, tan * a);
-		return [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),
-				Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];
-	},
-
-	_addBevelJoin: function(segment, join, radius, miterLimit, matrix,
-			strokeMatrix, addPoint, isArea) {
-		var curve2 = segment.getCurve(),
-			curve1 = curve2.getPrevious(),
-			point = curve2.getPointAtTime(0),
-			normal1 = curve1.getNormalAtTime(1),
-			normal2 = curve2.getNormalAtTime(0),
-			step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
-		normal1.setLength(step);
-		normal2.setLength(step);
-		if (matrix)
-			matrix._transformPoint(point, point);
-		if (strokeMatrix) {
-			strokeMatrix._transformPoint(normal1, normal1);
-			strokeMatrix._transformPoint(normal2, normal2);
-		}
-		if (isArea) {
-			addPoint(point);
-			addPoint(point.add(normal1));
-		}
-		if (join === 'miter') {
-			var corner = new Line(point.add(normal1),
-					new Point(-normal1.y, normal1.x), true
-				).intersect(new Line(point.add(normal2),
-					new Point(-normal2.y, normal2.x), true
-				), true);
-			if (corner && point.getDistance(corner) <= miterLimit) {
-				addPoint(corner);
-				if (!isArea)
-					return;
-			}
-		}
-		if (!isArea)
-			addPoint(point.add(normal1));
-		addPoint(point.add(normal2));
-	},
-
-	_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,
-			addPoint, isArea) {
-		var point = segment._point,
-			loc = segment.getLocation(),
-			normal = loc.getNormal().multiply(radius);
-		if (matrix)
-			matrix._transformPoint(point, point);
-		if (strokeMatrix)
-			strokeMatrix._transformPoint(normal, normal);
-		if (isArea) {
-			addPoint(point.subtract(normal));
-			addPoint(point.add(normal));
-		}
-		if (cap === 'square') {
-			point = point.add(normal.rotate(
-					loc.getTime() === 0 ? -90 : 90));
-		}
-		addPoint(point.add(normal));
-		addPoint(point.subtract(normal));
-	},
-
-	getHandleBounds: function(segments, closed, path, matrix, options) {
-		var style = path.getStyle(),
-			stroke = options.stroke && style.hasStroke(),
-			strokePadding,
-			joinPadding;
-		if (stroke) {
-			var strokeMatrix = path._getStrokeMatrix(matrix, options),
-				strokeRadius = style.getStrokeWidth() / 2,
-				joinRadius = strokeRadius;
-			if (style.getStrokeJoin() === 'miter')
-				joinRadius = strokeRadius * style.getMiterLimit();
-			if (style.getStrokeCap() === 'square')
-				joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
-			strokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);
-			joinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);
-		}
-		var coords = new Array(6),
-			x1 = Infinity,
-			x2 = -x1,
-			y1 = x1,
-			y2 = x2;
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var segment = segments[i];
-			segment._transformCoordinates(matrix, coords);
-			for (var j = 0; j < 6; j += 2) {
-				var padding = j === 0 ? joinPadding : strokePadding,
-					paddingX = padding ? padding[0] : 0,
-					paddingY = padding ? padding[1] : 0,
-					x = coords[j],
-					y = coords[j + 1],
-					xn = x - paddingX,
-					xx = x + paddingX,
-					yn = y - paddingY,
-					yx = y + paddingY;
-				if (xn < x1) x1 = xn;
-				if (xx > x2) x2 = xx;
-				if (yn < y1) y1 = yn;
-				if (yx > y2) y2 = yx;
-			}
-		}
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	}
-}});
-
-Path.inject({ statics: new function() {
-
-	var kappa = 0.5522847498307936,
-		ellipseSegments = [
-			new Segment([-1, 0], [0, kappa ], [0, -kappa]),
-			new Segment([0, -1], [-kappa, 0], [kappa, 0 ]),
-			new Segment([1, 0], [0, -kappa], [0, kappa ]),
-			new Segment([0, 1], [kappa, 0 ], [-kappa, 0])
-		];
-
-	function createPath(segments, closed, args) {
-		var props = Base.getNamed(args),
-			path = new Path(props && props.insert === false && Item.NO_INSERT);
-		path._add(segments);
-		path._closed = closed;
-		return path.set(props);
-	}
-
-	function createEllipse(center, radius, args) {
-		var segments = new Array(4);
-		for (var i = 0; i < 4; i++) {
-			var segment = ellipseSegments[i];
-			segments[i] = new Segment(
-				segment._point.multiply(radius).add(center),
-				segment._handleIn.multiply(radius),
-				segment._handleOut.multiply(radius)
-			);
-		}
-		return createPath(segments, true, args);
-	}
-
-	return {
-		Line: function() {
-			return createPath([
-				new Segment(Point.readNamed(arguments, 'from')),
-				new Segment(Point.readNamed(arguments, 'to'))
-			], false, arguments);
-		},
-
-		Circle: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				radius = Base.readNamed(arguments, 'radius');
-			return createEllipse(center, new Size(radius), arguments);
-		},
-
-		Rectangle: function() {
-			var rect = Rectangle.readNamed(arguments, 'rectangle'),
-				radius = Size.readNamed(arguments, 'radius', 0,
-						{ readNull: true }),
-				bl = rect.getBottomLeft(true),
-				tl = rect.getTopLeft(true),
-				tr = rect.getTopRight(true),
-				br = rect.getBottomRight(true),
-				segments;
-			if (!radius || radius.isZero()) {
-				segments = [
-					new Segment(bl),
-					new Segment(tl),
-					new Segment(tr),
-					new Segment(br)
-				];
-			} else {
-				radius = Size.min(radius, rect.getSize(true).divide(2));
-				var rx = radius.width,
-					ry = radius.height,
-					hx = rx * kappa,
-					hy = ry * kappa;
-				segments = [
-					new Segment(bl.add(rx, 0), null, [-hx, 0]),
-					new Segment(bl.subtract(0, ry), [0, hy]),
-					new Segment(tl.add(0, ry), null, [0, -hy]),
-					new Segment(tl.add(rx, 0), [-hx, 0], null),
-					new Segment(tr.subtract(rx, 0), null, [hx, 0]),
-					new Segment(tr.add(0, ry), [0, -hy], null),
-					new Segment(br.subtract(0, ry), null, [0, hy]),
-					new Segment(br.subtract(rx, 0), [hx, 0])
-				];
-			}
-			return createPath(segments, true, arguments);
-		},
-
-		RoundRectangle: '#Rectangle',
-
-		Ellipse: function() {
-			var ellipse = Shape._readEllipse(arguments);
-			return createEllipse(ellipse.center, ellipse.radius, arguments);
-		},
-
-		Oval: '#Ellipse',
-
-		Arc: function() {
-			var from = Point.readNamed(arguments, 'from'),
-				through = Point.readNamed(arguments, 'through'),
-				to = Point.readNamed(arguments, 'to'),
-				props = Base.getNamed(arguments),
-				path = new Path(props && props.insert === false
-						&& Item.NO_INSERT);
-			path.moveTo(from);
-			path.arcTo(through, to);
-			return path.set(props);
-		},
-
-		RegularPolygon: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				sides = Base.readNamed(arguments, 'sides'),
-				radius = Base.readNamed(arguments, 'radius'),
-				step = 360 / sides,
-				three = sides % 3 === 0,
-				vector = new Point(0, three ? -radius : radius),
-				offset = three ? -1 : 0.5,
-				segments = new Array(sides);
-			for (var i = 0; i < sides; i++)
-				segments[i] = new Segment(center.add(
-					vector.rotate((i + offset) * step)));
-			return createPath(segments, true, arguments);
-		},
-
-		Star: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				points = Base.readNamed(arguments, 'points') * 2,
-				radius1 = Base.readNamed(arguments, 'radius1'),
-				radius2 = Base.readNamed(arguments, 'radius2'),
-				step = 360 / points,
-				vector = new Point(0, -1),
-				segments = new Array(points);
-			for (var i = 0; i < points; i++)
-				segments[i] = new Segment(center.add(vector.rotate(step * i)
-						.multiply(i % 2 ? radius2 : radius1)));
-			return createPath(segments, true, arguments);
-		}
-	};
-}});
-
-var CompoundPath = PathItem.extend({
-	_class: 'CompoundPath',
-	_serializeFields: {
-		children: []
-	},
-
-	initialize: function CompoundPath(arg) {
-		this._children = [];
-		this._namedChildren = {};
-		if (!this._initialize(arg)) {
-			if (typeof arg === 'string') {
-				this.setPathData(arg);
-			} else {
-				this.addChildren(Array.isArray(arg) ? arg : arguments);
-			}
-		}
-	},
-
-	insertChildren: function insertChildren(index, items, _preserve) {
-		for (var i = items.length - 1; i >= 0; i--) {
-			var item = items[i];
-			if (item instanceof CompoundPath) {
-				items = items.slice();
-				items.splice.apply(items, [i, 1].concat(item.removeChildren()));
-				item.remove();
-			}
-		}
-		items = insertChildren.base.call(this, index, items, _preserve, Path);
-		for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
-			var item = items[i];
-			if (item._clockwise === undefined)
-				item.setClockwise(item._index === 0);
-		}
-		return items;
-	},
-
-	reduce: function reduce(options) {
-		var children = this._children;
-		for (var i = children.length - 1; i >= 0; i--) {
-			var path = children[i].reduce(options);
-			if (path.isEmpty())
-				path.remove();
-		}
-		if (children.length === 0) {
-			var path = new Path(Item.NO_INSERT);
-			path.copyAttributes(this);
-			path.insertAbove(this);
-			this.remove();
-			return path;
-		}
-		return reduce.base.call(this);
-	},
-
-	isClockwise: function() {
-		var child = this.getFirstChild();
-		return child && child.isClockwise();
-	},
-
-	setClockwise: function(clockwise) {
-		if (this.isClockwise() ^ !!clockwise)
-			this.reverse();
-	},
-
-	getFirstSegment: function() {
-		var first = this.getFirstChild();
-		return first && first.getFirstSegment();
-	},
-
-	getLastSegment: function() {
-		var last = this.getLastChild();
-		return last && last.getLastSegment();
-	},
-
-	getCurves: function() {
-		var children = this._children,
-			curves = [];
-		for (var i = 0, l = children.length; i < l; i++)
-			curves.push.apply(curves, children[i].getCurves());
-		return curves;
-	},
-
-	getFirstCurve: function() {
-		var first = this.getFirstChild();
-		return first && first.getFirstCurve();
-	},
-
-	getLastCurve: function() {
-		var last = this.getLastChild();
-		return last && last.getFirstCurve();
-	},
-
-	getArea: function() {
-		var children = this._children,
-			area = 0;
-		for (var i = 0, l = children.length; i < l; i++)
-			area += children[i].getArea();
-		return area;
-	}
-}, {
-	beans: true,
-
-	getPathData: function(_matrix, _precision) {
-		var children = this._children,
-			paths = [];
-		for (var i = 0, l = children.length; i < l; i++) {
-			var child = children[i],
-				mx = child._matrix;
-			paths.push(child.getPathData(_matrix && !mx.isIdentity()
-					? _matrix.appended(mx) : _matrix, _precision));
-		}
-		return paths.join(' ');
-	}
-}, {
-	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
-		return _hitTestChildren.base.call(this, point,
-				options.class === Path || options.type === 'path' ? options
-					: Base.set({}, options, { fill: false }),
-				viewMatrix);
-	},
-
-	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
-		var children = this._children;
-		if (children.length === 0)
-			return;
-
-		param = param.extend({ dontStart: true, dontFinish: true });
-		ctx.beginPath();
-		for (var i = 0, l = children.length; i < l; i++)
-			children[i].draw(ctx, param, strokeMatrix);
-
-		if (!param.clip) {
-			this._setStyles(ctx, param, viewMatrix);
-			var style = this._style;
-			if (style.hasFill()) {
-				ctx.fill(style.getFillRule());
-				ctx.shadowColor = 'rgba(0,0,0,0)';
-			}
-			if (style.hasStroke())
-				ctx.stroke();
-		}
-	},
-
-	_drawSelected: function(ctx, matrix, selectionItems) {
-		var children = this._children;
-		for (var i = 0, l = children.length; i < l; i++) {
-			var child = children[i],
-				mx = child._matrix;
-			if (!selectionItems[child._id]) {
-				child._drawSelected(ctx, mx.isIdentity() ? matrix
-						: matrix.appended(mx));
-			}
-		}
-	}
-},
-new function() {
-	function getCurrentPath(that, check) {
-		var children = that._children;
-		if (check && children.length === 0)
-			throw new Error('Use a moveTo() command first');
-		return children[children.length - 1];
-	}
-
-	return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
-			'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
-			'arcBy'],
-		function(key) {
-			this[key] = function() {
-				var path = getCurrentPath(this, true);
-				path[key].apply(path, arguments);
-			};
-		}, {
-			moveTo: function() {
-				var current = getCurrentPath(this),
-					path = current && current.isEmpty() ? current
-							: new Path(Item.NO_INSERT);
-				if (path !== current)
-					this.addChild(path);
-				path.moveTo.apply(path, arguments);
-			},
-
-			moveBy: function() {
-				var current = getCurrentPath(this, true),
-					last = current && current.getLastSegment(),
-					point = Point.read(arguments);
-				this.moveTo(last ? point.add(last._point) : point);
-			},
-
-			closePath: function(tolerance) {
-				getCurrentPath(this, true).closePath(tolerance);
-			}
-		}
-	);
-}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
-	this[key] = function(param) {
-		var children = this._children,
-			res;
-		for (var i = 0, l = children.length; i < l; i++) {
-			res = children[i][key](param) || res;
-		}
-		return res;
-	};
-}, {}));
-
-PathItem.inject(new function() {
-	var operators = {
-		unite:     { 1: true },
-		intersect: { 2: true },
-		subtract:  { 1: true },
-		exclude:   { 1: true }
-	};
-
-	function preparePath(path, resolve) {
-		var res = path.clone(false).reduce({ simplify: true })
-				.transform(null, true, true);
-		return resolve ? res.resolveCrossings() : res;
-	}
-
-	function createResult(ctor, paths, reduce, path1, path2) {
-		var result = new ctor(Item.NO_INSERT);
-		result.addChildren(paths, true);
-		if (reduce)
-			result = result.reduce({ simplify: true });
-		result.insertAbove(path2 && path1.isSibling(path2)
-				&& path1.getIndex() < path2.getIndex() ? path2 : path1);
-		result.copyAttributes(path1, true);
-		return result;
-	}
-
-	function computeBoolean(path1, path2, operation) {
-		var operator = operators[operation];
-		operator[operation] = true;
-		if (!path1._children && !path1._closed)
-			return computeOpenBoolean(path1, path2, operator);
-		var _path1 = preparePath(path1, true),
-			_path2 = path2 && path1 !== path2 && preparePath(path2, true);
-		if (_path2 && (operator.subtract || operator.exclude)
-				^ (_path2.isClockwise() ^ _path1.isClockwise()))
-			_path2.reverse();
-		var crossings = divideLocations(
-				CurveLocation.expand(_path1.getCrossings(_path2))),
-			segments = [],
-			monoCurves = [];
-
-		function collect(paths) {
-			for (var i = 0, l = paths.length; i < l; i++) {
-				var path = paths[i];
-				segments.push.apply(segments, path._segments);
-				monoCurves.push.apply(monoCurves, path._getMonoCurves());
-				path._overlapsOnly = path._validOverlapsOnly = true;
-			}
-		}
-
-		collect(_path1._children || [_path1]);
-		if (_path2)
-			collect(_path2._children || [_path2]);
-		for (var i = 0, l = crossings.length; i < l; i++) {
-			propagateWinding(crossings[i]._segment, _path1, _path2, monoCurves,
-					operator);
-		}
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var segment = segments[i],
-				inter = segment._intersection;
-			if (segment._winding == null) {
-				propagateWinding(segment, _path1, _path2, monoCurves, operator);
-			}
-			if (!(inter && inter._overlap)) {
-				var path = segment._path;
-				path._overlapsOnly = false;
-				if (operator[segment._winding])
-					path._validOverlapsOnly = false;
-			}
-		}
-		return createResult(CompoundPath, tracePaths(segments, operator), true,
-					path1, path2);
-	}
-
-	function computeOpenBoolean(path1, path2, operator) {
-		if (!path2 || !path2._children && !path2._closed
-				|| !operator.subtract && !operator.intersect)
-			return null;
-		var _path1 = preparePath(path1, false),
-			_path2 = preparePath(path2, false),
-			crossings = _path1.getCrossings(_path2),
-			sub = operator.subtract,
-			paths = [];
-
-		function addPath(path) {
-			if (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {
-				paths.unshift(path);
-				return true;
-			}
-		}
-
-		for (var i = crossings.length - 1; i >= 0; i--) {
-			var path = crossings[i].split();
-			if (path) {
-				if (addPath(path))
-					path.getFirstSegment().setHandleIn(0, 0);
-				_path1.getLastSegment().setHandleOut(0, 0);
-			}
-		}
-		addPath(_path1);
-		return createResult(Group, paths, false, path1, path2);
-	}
-
-	function linkIntersections(from, to) {
-		var prev = from;
-		while (prev) {
-			if (prev === to)
-				return;
-			prev = prev._previous;
-		}
-		while (from._next && from._next !== to)
-			from = from._next;
-		if (!from._next) {
-			while (to._previous)
-				to = to._previous;
-			from._next = to;
-			to._previous = from;
-		}
-	}
-
-	function divideLocations(locations, include) {
-		var results = include && [],
-			tMin = 4e-7,
-			tMax = 1 - tMin,
-			noHandles = false,
-			clearCurves = [],
-			prevCurve,
-			prevTime;
-
-		for (var i = locations.length - 1; i >= 0; i--) {
-			var loc = locations[i];
-			if (include) {
-				if (!include(loc))
-					continue;
-				results.unshift(loc);
-			}
-			var curve = loc._curve,
-				time = loc._time,
-				origTime = time,
-				segment;
-			if (curve !== prevCurve) {
-				noHandles = !curve.hasHandles();
-			} else if (prevTime >= tMin && prevTime <= tMax ) {
-				time /= prevTime;
-			}
-			if (time < tMin) {
-				segment = curve._segment1;
-			} else if (time > tMax) {
-				segment = curve._segment2;
-			} else {
-				var newCurve = curve.divideAtTime(time, true);
-				if (noHandles)
-					clearCurves.push(curve, newCurve);
-				segment = newCurve._segment1;
-			}
-			loc._setSegment(segment);
-			var inter = segment._intersection,
-				dest = loc._intersection;
-			if (inter) {
-				linkIntersections(inter, dest);
-				var other = inter;
-				while (other) {
-					linkIntersections(other._intersection, inter);
-					other = other._next;
-				}
-			} else {
-				segment._intersection = dest;
-			}
-			prevCurve = curve;
-			prevTime = origTime;
-		}
-		for (var i = 0, l = clearCurves.length; i < l; i++) {
-			clearCurves[i].clearHandles();
-		}
-		return results || locations;
-	}
-
-	function getWinding(point, curves, horizontal) {
-		var epsilon = 2e-7,
-			px = point.x,
-			py = point.y,
-			windLeft = 0,
-			windRight = 0,
-			length = curves.length,
-			roots = [],
-			abs = Math.abs;
-		if (horizontal) {
-			var yTop = -Infinity,
-				yBottom = Infinity,
-				yBefore = py - epsilon,
-				yAfter = py + epsilon;
-			for (var i = 0; i < length; i++) {
-				var values = curves[i].values,
-					count = Curve.solveCubic(values, 0, px, roots, 0, 1);
-				for (var j = count - 1; j >= 0; j--) {
-					var y = Curve.getPoint(values, roots[j]).y;
-					if (y < yBefore && y > yTop) {
-						yTop = y;
-					} else if (y > yAfter && y < yBottom) {
-						yBottom = y;
-					}
-				}
-			}
-			yTop = (yTop + py) / 2;
-			yBottom = (yBottom + py) / 2;
-			if (yTop > -Infinity)
-				windLeft = getWinding(new Point(px, yTop), curves).winding;
-			if (yBottom < Infinity)
-				windRight = getWinding(new Point(px, yBottom), curves).winding;
-		} else {
-			var xBefore = px - epsilon,
-				xAfter = px + epsilon,
-				prevWinding,
-				prevXEnd,
-				windLeftOnCurve = 0,
-				windRightOnCurve = 0,
-				isOnCurve = false;
-			for (var i = 0; i < length; i++) {
-				var curve = curves[i],
-					winding = curve.winding,
-					values = curve.values,
-					yStart = values[1],
-					yEnd = values[7];
-				if (curve.last) {
-					prevWinding = curve.last.winding;
-					prevXEnd = curve.last.values[6];
-					isOnCurve = false;
-				}
-				if (py >= yStart && py <= yEnd || py >= yEnd && py <= yStart) {
-					if (winding) {
-						var x = py === yStart ? values[0]
-							: py === yEnd ? values[6]
-							: Curve.solveCubic(values, 1, py, roots, 0, 1) === 1
-							? Curve.getPoint(values, roots[0]).x
-							: null;
-						if (x != null) {
-							if (x >= xBefore && x <= xAfter) {
-								isOnCurve = true;
-							} else if (
-								(py !== yStart || winding !== prevWinding)
-								&& !(py === yStart
-									&& (px - x) * (px - prevXEnd) < 0)) {
-								if (x < xBefore) {
-									windLeft += winding;
-								} else if (x > xAfter) {
-									windRight += winding;
-								}
-							}
-						}
-						prevWinding = winding;
-						prevXEnd = values[6];
-					} else if ((px - values[0]) * (px - values[6]) <= 0) {
-						isOnCurve = true;
-					}
-				}
-				if (isOnCurve && (i >= length - 1 || curves[i + 1].last)) {
-					windLeftOnCurve += 1;
-					windRightOnCurve -= 1;
-				}
-			}
-			if (windLeft === 0 && windRight === 0) {
-				windLeft = windLeftOnCurve;
-				windRight = windRightOnCurve;
-			}
-		}
-		return {
-			winding: Math.max(abs(windLeft), abs(windRight)),
-			contour: !windLeft ^ !windRight
-		};
-	}
-
-	function propagateWinding(segment, path1, path2, monoCurves, operator) {
-		var chain = [],
-			start = segment,
-			totalLength = 0,
-			winding;
-		do {
-			var curve = segment.getCurve(),
-				length = curve.getLength();
-			chain.push({ segment: segment, curve: curve, length: length });
-			totalLength += length;
-			segment = segment.getNext();
-		} while (segment && !segment._intersection && segment !== start);
-		var length = totalLength / 2;
-		for (var j = 0, l = chain.length; j < l; j++) {
-			var entry = chain[j],
-				curveLength = entry.length;
-			if (length <= curveLength) {
-				var curve = entry.curve,
-					path = curve._path,
-					parent = path._parent,
-					t = curve.getTimeAt(length),
-					pt = curve.getPointAtTime(t),
-					hor = Math.abs(curve.getTangentAtTime(t).y)
-							< 1e-7;
-				if (parent instanceof CompoundPath)
-					path = parent;
-				winding = !(operator.subtract && path2 && (
-						path === path1 &&  path2._getWinding(pt, hor) ||
-						path === path2 && !path1._getWinding(pt, hor)))
-							? getWinding(pt, monoCurves, hor)
-							: { winding: 0 };
-				 break;
-			}
-			length -= curveLength;
-		}
-		for (var j = chain.length - 1; j >= 0; j--) {
-			var seg = chain[j].segment;
-			seg._winding = winding.winding;
-			seg._contour = winding.contour;
-		}
-	}
-
-	function tracePaths(segments, operator) {
-		var paths = [],
-			start,
-			otherStart;
-
-		function isValid(seg, excludeContour) {
-			return !!(seg && !seg._visited && (!operator
-					|| operator[seg._winding]
-					|| !excludeContour && operator.unite && seg._contour));
-		}
-
-		function isStart(seg) {
-			return seg === start || seg === otherStart;
-		}
-
-		function findBestIntersection(inter, exclude) {
-			if (!inter._next)
-				return inter;
-			while (inter) {
-				var seg = inter._segment,
-					nextSeg = seg.getNext(),
-					nextInter = nextSeg && nextSeg._intersection;
-				if (seg !== exclude && (isStart(seg) || isStart(nextSeg)
-					|| !seg._visited && !nextSeg._visited
-					&& (!operator || isValid(seg) && (isValid(nextSeg)
-						|| nextInter && isValid(nextInter._segment)))
-					))
-					return inter;
-				inter = inter._next;
-			}
-			return null;
-		}
-
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var path = null,
-				finished = false,
-				seg = segments[i],
-				inter = seg._intersection,
-				handleIn;
-			if (!seg._visited && seg._path._overlapsOnly) {
-				var path1 = seg._path,
-					path2 = inter._segment._path,
-					segments1 = path1._segments,
-					segments2 = path2._segments;
-				if (Base.equals(segments1, segments2)) {
-					if ((operator.unite || operator.intersect)
-							&& path1.getArea()) {
-						paths.push(path1.clone(false));
-					}
-					for (var j = 0, k = segments1.length; j < k; j++) {
-						segments1[j]._visited = segments2[j]._visited = true;
-					}
-				}
-			}
-			if (!isValid(seg, true)
-					|| !seg._path._validOverlapsOnly && inter && inter._overlap)
-				continue;
-			start = otherStart = null;
-			while (true) {
-				inter = inter && findBestIntersection(inter, seg) || inter;
-				var other = inter && inter._segment;
-				if (isStart(seg)) {
-					finished = true;
-				} else if (other) {
-					if (isStart(other)) {
-						finished = true;
-						seg = other;
-					} else if (isValid(other, isValid(seg, true))) {
-						if (operator
-								&& (operator.intersect || operator.subtract)) {
-							seg._visited = true;
-						}
-						seg = other;
-					}
-				}
-				if (finished || seg._visited) {
-					seg._visited = true;
-					break;
-				}
-				if (seg._path._validOverlapsOnly && !isValid(seg))
-					break;
-				if (!path) {
-					path = new Path(Item.NO_INSERT);
-					start = seg;
-					otherStart = other;
-				}
-				var next = seg.getNext();
-				path.add(new Segment(seg._point, handleIn,
-						next && seg._handleOut));
-				seg._visited = true;
-				seg = next || seg._path.getFirstSegment();
-				handleIn = next && next._handleIn;
-				inter = seg._intersection;
-			}
-			if (finished) {
-				path.firstSegment.setHandleIn(handleIn);
-				path.setClosed(true);
-			} else if (path) {
-				var area = path.getArea(true);
-				if (Math.abs(area) >= 2e-7) {
-					console.error('Boolean operation resulted in open path',
-							'segments =', path._segments.length,
-							'length =', path.getLength(),
-							'area=', area);
-				}
-				path = null;
-			}
-			if (path && (path._segments.length > 8
-					|| !Numerical.isZero(path.getArea()))) {
-				paths.push(path);
-				path = null;
-			}
-		}
-		return paths;
-	}
-
-	return {
-		_getWinding: function(point, horizontal) {
-			return getWinding(point, this._getMonoCurves(), horizontal).winding;
-		},
-
-		unite: function(path) {
-			return computeBoolean(this, path, 'unite');
-		},
-
-		intersect: function(path) {
-			return computeBoolean(this, path, 'intersect');
-		},
-
-		subtract: function(path) {
-			return computeBoolean(this, path, 'subtract');
-		},
-
-		exclude: function(path) {
-			return computeBoolean(this, path, 'exclude');
-		},
-
-		divide: function(path) {
-			return createResult(Group, [this.subtract(path),
-					this.intersect(path)], true, this, path);
-		},
-
-		resolveCrossings: function() {
-			var children = this._children,
-				paths = children || [this];
-
-			function hasOverlap(seg) {
-				var inter = seg && seg._intersection;
-				return inter && inter._overlap;
-			}
-
-			var hasOverlaps = false,
-				hasCrossings = false,
-				intersections = this.getIntersections(null, function(inter) {
-					return inter._overlap && (hasOverlaps = true)
-							|| inter.isCrossing() && (hasCrossings = true);
-				});
-			intersections = CurveLocation.expand(intersections);
-			if (hasOverlaps) {
-				var overlaps = divideLocations(intersections, function(inter) {
-					return inter._overlap;
-				});
-				for (var i = overlaps.length - 1; i >= 0; i--) {
-					var seg = overlaps[i]._segment,
-						prev = seg.getPrevious(),
-						next = seg.getNext();
-					if (seg._path && hasOverlap(prev) && hasOverlap(next)) {
-						seg.remove();
-						prev._handleOut.set(0, 0);
-						next._handleIn.set(0, 0);
-						var curve = prev.getCurve();
-						if (curve.isStraight() && curve.getLength() === 0)
-							prev.remove();
-					}
-				}
-			}
-			if (hasCrossings) {
-				divideLocations(intersections, hasOverlaps && function(inter) {
-					var curve1 = inter.getCurve(),
-						curve2 = inter._intersection._curve,
-						seg = inter._segment;
-					if (curve1 && curve2 && curve1._path && curve2._path) {
-						return true;
-					} else if (seg) {
-						seg._intersection = null;
-					}
-				});
-				paths = tracePaths(Base.each(paths, function(path) {
-					this.push.apply(this, path._segments);
-				}, []));
-			}
-			var length = paths.length,
-				item;
-			if (length > 1) {
-				paths = paths.slice().sort(function (a, b) {
-					return b.getBounds().getArea() - a.getBounds().getArea();
-				});
-				var first = paths[0],
-					items = [first],
-					excluded = {},
-					isNonZero = this.getFillRule() === 'nonzero',
-					windings = isNonZero && Base.each(paths, function(path) {
-						this.push(path.isClockwise() ? 1 : -1);
-					}, []);
-				for (var i = 1; i < length; i++) {
-					var path = paths[i],
-						point = path.getInteriorPoint(),
-						isContained = false,
-						container = null,
-						exclude = false;
-					for (var j = i - 1; j >= 0 && !container; j--) {
-						if (paths[j].contains(point)) {
-							if (isNonZero && !isContained) {
-								windings[i] += windings[j];
-								if (windings[i] && windings[j]) {
-									exclude = excluded[i] = true;
-									break;
-								}
-							}
-							isContained = true;
-							container = !excluded[j] && paths[j];
-						}
-					}
-					if (!exclude) {
-						path.setClockwise(container ? !container.isClockwise()
-								: first.isClockwise());
-						items.push(path);
-					}
-				}
-				paths = items;
-				length = items.length;
-			}
-			if (length > 1 && children) {
-				if (paths !== children) {
-					this.setChildren(paths, true);
-				}
-				item = this;
-			} else if (length === 1 && !children) {
-				if (paths[0] !== this)
-					this.setSegments(paths[0].removeSegments());
-				item = this;
-			}
-			if (!item) {
-				item = new CompoundPath(Item.NO_INSERT);
-				item.addChildren(paths, true);
-				item = item.reduce();
-				item.copyAttributes(this);
-				this.replaceWith(item);
-			}
-			return item;
-		}
-	};
-});
-
-Path.inject({
-	_getMonoCurves: function() {
-		var monoCurves = this._monoCurves,
-			last;
-
-		function insertCurve(v) {
-			var y0 = v[1],
-				y1 = v[7],
-				winding = Math.abs((y0 - y1) / (v[0] - v[6]))
-						< 2e-7
-					? 0
-					: y0 > y1
-						? -1
-						: 1,
-				curve = { values: v, winding: winding };
-			monoCurves.push(curve);
-			if (winding)
-				last = curve;
-		}
-
-		function handleCurve(v) {
-			if (Curve.getLength(v) === 0)
-				return;
-			var y0 = v[1],
-				y1 = v[3],
-				y2 = v[5],
-				y3 = v[7];
-			if (Curve.isStraight(v)
-					|| y0 >= y1 === y1 >= y2 && y1 >= y2 === y2 >= y3) {
-				insertCurve(v);
-			} else {
-				var a = 3 * (y1 - y2) - y0 + y3,
-					b = 2 * (y0 + y2) - 4 * y1,
-					c = y1 - y0,
-					tMin = 4e-7,
-					tMax = 1 - tMin,
-					roots = [],
-					n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
-				if (n < 1) {
-					insertCurve(v);
-				} else {
-					roots.sort();
-					var t = roots[0],
-						parts = Curve.subdivide(v, t);
-					insertCurve(parts[0]);
-					if (n > 1) {
-						t = (roots[1] - t) / (1 - t);
-						parts = Curve.subdivide(parts[1], t);
-						insertCurve(parts[0]);
-					}
-					insertCurve(parts[1]);
-				}
-			}
-		}
-
-		if (!monoCurves) {
-			monoCurves = this._monoCurves = [];
-			var curves = this.getCurves(),
-				segments = this._segments;
-			for (var i = 0, l = curves.length; i < l; i++)
-				handleCurve(curves[i].getValues());
-			if (!this._closed && segments.length > 1) {
-				var p1 = segments[segments.length - 1]._point,
-					p2 = segments[0]._point,
-					p1x = p1._x, p1y = p1._y,
-					p2x = p2._x, p2y = p2._y;
-				handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
-			}
-			if (monoCurves.length > 0) {
-				monoCurves[0].last = last;
-			}
-		}
-		return monoCurves;
-	},
-
-	getInteriorPoint: function() {
-		var bounds = this.getBounds(),
-			point = bounds.getCenter(true);
-		if (!this.contains(point)) {
-			var curves = this._getMonoCurves(),
-				roots = [],
-				y = point.y,
-				intercepts = [];
-			for (var i = 0, l = curves.length; i < l; i++) {
-				var values = curves[i].values;
-				if (curves[i].winding === 1
-						&& y > values[1] && y <= values[7]
-						|| y >= values[7] && y < values[1]) {
-					var count = Curve.solveCubic(values, 1, y, roots, 0, 1);
-					for (var j = count - 1; j >= 0; j--) {
-						intercepts.push(Curve.getPoint(values, roots[j]).x);
-					}
-				}
-			}
-			intercepts.sort(function(a, b) { return a - b; });
-			point.x = (intercepts[0] + intercepts[1]) / 2;
-		}
-		return point;
-	}
-});
-
-CompoundPath.inject({
-	_getMonoCurves: function() {
-		var children = this._children,
-			monoCurves = [];
-		for (var i = 0, l = children.length; i < l; i++)
-			monoCurves.push.apply(monoCurves, children[i]._getMonoCurves());
-		return monoCurves;
-	}
-});
-
-var PathIterator = Base.extend({
-	_class: 'PathIterator',
-
-	initialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {
-		var curves = [],
-			parts = [],
-			length = 0,
-			minSpan = 1 / (maxRecursion || 32),
-			segments = path._segments,
-			segment1 = segments[0],
-			segment2;
-
-		function addCurve(segment1, segment2) {
-			var curve = Curve.getValues(segment1, segment2, matrix);
-			curves.push(curve);
-			computeParts(curve, segment1._index, 0, 1);
-		}
-
-		function computeParts(curve, index, t1, t2) {
-			if ((t2 - t1) > minSpan
-					&& !(ignoreStraight && Curve.isStraight(curve))
-					&& !Curve.isFlatEnough(curve, flatness || 0.25)) {
-				var halves = Curve.subdivide(curve, 0.5),
-					tMid = (t1 + t2) / 2;
-				computeParts(halves[0], index, t1, tMid);
-				computeParts(halves[1], index, tMid, t2);
-			} else {
-				var dx = curve[6] - curve[0],
-					dy = curve[7] - curve[1],
-					dist = Math.sqrt(dx * dx + dy * dy);
-				if (dist > 0) {
-					length += dist;
-					parts.push({
-						offset: length,
-						curve: curve,
-						index: index,
-						time: t2,
-					});
-				}
-			}
-		}
-
-		for (var i = 1, l = segments.length; i < l; i++) {
-			segment2 = segments[i];
-			addCurve(segment1, segment2);
-			segment1 = segment2;
-		}
-		if (path._closed)
-			addCurve(segment2, segments[0]);
-		this.curves = curves;
-		this.parts = parts;
-		this.length = length;
-		this.index = 0;
-	},
-
-	_get: function(offset) {
-		var i, j = this.index;
-		for (;;) {
-			i = j;
-			if (j === 0 || this.parts[--j].offset < offset)
-				break;
-		}
-		for (var l = this.parts.length; i < l; i++) {
-			var part = this.parts[i];
-			if (part.offset >= offset) {
-				this.index = i;
-				var prev = this.parts[i - 1];
-				var prevTime = prev && prev.index === part.index ? prev.time : 0,
-					prevOffset = prev ? prev.offset : 0;
-				return {
-					index: part.index,
-					time: prevTime + (part.time - prevTime)
-						* (offset - prevOffset) / (part.offset - prevOffset)
-				};
-			}
-		}
-		var part = this.parts[this.parts.length - 1];
-		return {
-			index: part.index,
-			time: 1
-		};
-	},
-
-	drawPart: function(ctx, from, to) {
-		var start = this._get(from),
-			end = this._get(to);
-		for (var i = start.index, l = end.index; i <= l; i++) {
-			var curve = Curve.getPart(this.curves[i],
-					i === start.index ? start.time : 0,
-					i === end.index ? end.time : 1);
-			if (i === start.index)
-				ctx.moveTo(curve[0], curve[1]);
-			ctx.bezierCurveTo.apply(ctx, curve.slice(2));
-		}
-	}
-}, Base.each(Curve._evaluateMethods,
-	function(name) {
-		this[name + 'At'] = function(offset) {
-			var param = this._get(offset);
-			return Curve[name](this.curves[param.index], param.time);
-		};
-	}, {})
-);
-
-var PathFitter = Base.extend({
-	initialize: function(path) {
-		var points = this.points = [],
-			segments = path._segments,
-			closed = path._closed;
-		for (var i = 0, prev, l = segments.length; i < l; i++) {
-			var point = segments[i].point;
-			if (!prev || !prev.equals(point)) {
-				points.push(prev = point.clone());
-			}
-		}
-		if (closed) {
-			points.unshift(points[points.length - 1]);
-			points.push(points[1]);
-		}
-		this.closed = closed;
-	},
-
-	fit: function(error) {
-		var points = this.points,
-			length = points.length,
-			segments = null;
-		if (length > 0) {
-			segments = [new Segment(points[0])];
-			if (length > 1) {
-				this.fitCubic(segments, error, 0, length - 1,
-						points[1].subtract(points[0]),
-						points[length - 2].subtract(points[length - 1]));
-				if (this.closed) {
-					segments.shift();
-					segments.pop();
-				}
-			}
-		}
-		return segments;
-	},
-
-	fitCubic: function(segments, error, first, last, tan1, tan2) {
-		var points = this.points;
-		if (last - first === 1) {
-			var pt1 = points[first],
-				pt2 = points[last],
-				dist = pt1.getDistance(pt2) / 3;
-			this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
-					pt2.add(tan2.normalize(dist)), pt2]);
-			return;
-		}
-		var uPrime = this.chordLengthParameterize(first, last),
-			maxError = Math.max(error, error * error),
-			split,
-			parametersInOrder = true;
-		for (var i = 0; i <= 4; i++) {
-			var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
-			var max = this.findMaxError(first, last, curve, uPrime);
-			if (max.error < error && parametersInOrder) {
-				this.addCurve(segments, curve);
-				return;
-			}
-			split = max.index;
-			if (max.error >= maxError)
-				break;
-			parametersInOrder = this.reparameterize(first, last, uPrime, curve);
-			maxError = max.error;
-		}
-		var tanCenter = points[split - 1].subtract(points[split + 1]);
-		this.fitCubic(segments, error, first, split, tan1, tanCenter);
-		this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
-	},
-
-	addCurve: function(segments, curve) {
-		var prev = segments[segments.length - 1];
-		prev.setHandleOut(curve[1].subtract(curve[0]));
-		segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
-	},
-
-	generateBezier: function(first, last, uPrime, tan1, tan2) {
-		var epsilon = 1e-12,
-			abs = Math.abs,
-			points = this.points,
-			pt1 = points[first],
-			pt2 = points[last],
-			C = [[0, 0], [0, 0]],
-			X = [0, 0];
-
-		for (var i = 0, l = last - first + 1; i < l; i++) {
-			var u = uPrime[i],
-				t = 1 - u,
-				b = 3 * u * t,
-				b0 = t * t * t,
-				b1 = b * t,
-				b2 = b * u,
-				b3 = u * u * u,
-				a1 = tan1.normalize(b1),
-				a2 = tan2.normalize(b2),
-				tmp = points[first + i]
-					.subtract(pt1.multiply(b0 + b1))
-					.subtract(pt2.multiply(b2 + b3));
-			C[0][0] += a1.dot(a1);
-			C[0][1] += a1.dot(a2);
-			C[1][0] = C[0][1];
-			C[1][1] += a2.dot(a2);
-			X[0] += a1.dot(tmp);
-			X[1] += a2.dot(tmp);
-		}
-
-		var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
-			alpha1, alpha2;
-		if (abs(detC0C1) > epsilon) {
-			var detC0X = C[0][0] * X[1]    - C[1][0] * X[0],
-				detXC1 = X[0]    * C[1][1] - X[1]    * C[0][1];
-			alpha1 = detXC1 / detC0C1;
-			alpha2 = detC0X / detC0C1;
-		} else {
-			var c0 = C[0][0] + C[0][1],
-				c1 = C[1][0] + C[1][1];
-			if (abs(c0) > epsilon) {
-				alpha1 = alpha2 = X[0] / c0;
-			} else if (abs(c1) > epsilon) {
-				alpha1 = alpha2 = X[1] / c1;
-			} else {
-				alpha1 = alpha2 = 0;
-			}
-		}
-
-		var segLength = pt2.getDistance(pt1),
-			eps = epsilon * segLength,
-			handle1,
-			handle2;
-		if (alpha1 < eps || alpha2 < eps) {
-			alpha1 = alpha2 = segLength / 3;
-		} else {
-			var line = pt2.subtract(pt1);
-			handle1 = tan1.normalize(alpha1);
-			handle2 = tan2.normalize(alpha2);
-			if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
-				alpha1 = alpha2 = segLength / 3;
-				handle1 = handle2 = null;
-			}
-		}
-
-		return [pt1,
-				pt1.add(handle1 || tan1.normalize(alpha1)),
-				pt2.add(handle2 || tan2.normalize(alpha2)),
-				pt2];
-	},
-
-	reparameterize: function(first, last, u, curve) {
-		for (var i = first; i <= last; i++) {
-			u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
-		}
-		for (var i = 1, l = u.length; i < l; i++) {
-			if (u[i] <= u[i - 1])
-				return false;
-		}
-		return true;
-	},
-
-	findRoot: function(curve, point, u) {
-		var curve1 = [],
-			curve2 = [];
-		for (var i = 0; i <= 2; i++) {
-			curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);
-		}
-		for (var i = 0; i <= 1; i++) {
-			curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);
-		}
-		var pt = this.evaluate(3, curve, u),
-			pt1 = this.evaluate(2, curve1, u),
-			pt2 = this.evaluate(1, curve2, u),
-			diff = pt.subtract(point),
-			df = pt1.dot(pt1) + diff.dot(pt2);
-		if (Math.abs(df) < 1e-6)
-			return u;
-		return u - diff.dot(pt1) / df;
-	},
-
-	evaluate: function(degree, curve, t) {
-		var tmp = curve.slice();
-		for (var i = 1; i <= degree; i++) {
-			for (var j = 0; j <= degree - i; j++) {
-				tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));
-			}
-		}
-		return tmp[0];
-	},
-
-	chordLengthParameterize: function(first, last) {
-		var u = [0];
-		for (var i = first + 1; i <= last; i++) {
-			u[i - first] = u[i - first - 1]
-					+ this.points[i].getDistance(this.points[i - 1]);
-		}
-		for (var i = 1, m = last - first; i <= m; i++) {
-			u[i] /= u[m];
-		}
-		return u;
-	},
-
-	findMaxError: function(first, last, curve, u) {
-		var index = Math.floor((last - first + 1) / 2),
-			maxDist = 0;
-		for (var i = first + 1; i < last; i++) {
-			var P = this.evaluate(3, curve, u[i - first]);
-			var v = P.subtract(this.points[i]);
-			var dist = v.x * v.x + v.y * v.y;
-			if (dist >= maxDist) {
-				maxDist = dist;
-				index = i;
-			}
-		}
-		return {
-			error: maxDist,
-			index: index
-		};
-	}
-});
-
-var TextItem = Item.extend({
-	_class: 'TextItem',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_serializeFields: {
-		content: null
-	},
-	_boundsOptions: { stroke: false, handle: false },
-
-	initialize: function TextItem(arg) {
-		this._content = '';
-		this._lines = [];
-		var hasProps = arg && Base.isPlainObject(arg)
-				&& arg.x === undefined && arg.y === undefined;
-		this._initialize(hasProps && arg, !hasProps && Point.read(arguments));
-	},
-
-	_equals: function(item) {
-		return this._content === item._content;
-	},
-
-	copyContent: function(source) {
-		this.setContent(source._content);
-	},
-
-	getContent: function() {
-		return this._content;
-	},
-
-	setContent: function(content) {
-		this._content = '' + content;
-		this._lines = this._content.split(/\r\n|\n|\r/mg);
-		this._changed(265);
-	},
-
-	isEmpty: function() {
-		return !this._content;
-	},
-
-	getCharacterStyle: '#getStyle',
-	setCharacterStyle: '#setStyle',
-
-	getParagraphStyle: '#getStyle',
-	setParagraphStyle: '#setStyle'
-});
-
-var PointText = TextItem.extend({
-	_class: 'PointText',
-
-	initialize: function PointText() {
-		TextItem.apply(this, arguments);
-	},
-
-	getPoint: function() {
-		var point = this._matrix.getTranslation();
-		return new LinkedPoint(point.x, point.y, this, 'setPoint');
-	},
-
-	setPoint: function() {
-		var point = Point.read(arguments);
-		this.translate(point.subtract(this._matrix.getTranslation()));
-	},
-
-	_draw: function(ctx, param, viewMatrix) {
-		if (!this._content)
-			return;
-		this._setStyles(ctx, param, viewMatrix);
-		var lines = this._lines,
-			style = this._style,
-			hasFill = style.hasFill(),
-			hasStroke = style.hasStroke(),
-			leading = style.getLeading(),
-			shadowColor = ctx.shadowColor;
-		ctx.font = style.getFontStyle();
-		ctx.textAlign = style.getJustification();
-		for (var i = 0, l = lines.length; i < l; i++) {
-			ctx.shadowColor = shadowColor;
-			var line = lines[i];
-			if (hasFill) {
-				ctx.fillText(line, 0, 0);
-				ctx.shadowColor = 'rgba(0,0,0,0)';
-			}
-			if (hasStroke)
-				ctx.strokeText(line, 0, 0);
-			ctx.translate(0, leading);
-		}
-	},
-
-	_getBounds: function(matrix, options) {
-		var style = this._style,
-			lines = this._lines,
-			numLines = lines.length,
-			justification = style.getJustification(),
-			leading = style.getLeading(),
-			width = this.getView().getTextWidth(style.getFontStyle(), lines),
-			x = 0;
-		if (justification !== 'left')
-			x -= width / (justification === 'center' ? 2: 1);
-		var bounds = new Rectangle(x,
-					numLines ? - 0.75 * leading : 0,
-					width, numLines * leading);
-		return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
-	}
-});
-
-var Color = Base.extend(new function() {
-	var types = {
-		gray: ['gray'],
-		rgb: ['red', 'green', 'blue'],
-		hsb: ['hue', 'saturation', 'brightness'],
-		hsl: ['hue', 'saturation', 'lightness'],
-		gradient: ['gradient', 'origin', 'destination', 'highlight']
-	};
-
-	var componentParsers = {},
-		colorCache = {},
-		colorCtx;
-
-	function fromCSS(string) {
-		var match = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/),
-			components;
-		if (match) {
-			components = [0, 0, 0];
-			for (var i = 0; i < 3; i++) {
-				var value = match[i + 1];
-				components[i] = parseInt(value.length == 1
-						? value + value : value, 16) / 255;
-			}
-		} else if (match = string.match(/^rgba?\((.*)\)$/)) {
-			components = match[1].split(',');
-			for (var i = 0, l = components.length; i < l; i++) {
-				var value = +components[i];
-				components[i] = i < 3 ? value / 255 : value;
-			}
-		} else if (window) {
-			var cached = colorCache[string];
-			if (!cached) {
-				if (!colorCtx) {
-					colorCtx = CanvasProvider.getContext(1, 1);
-					colorCtx.globalCompositeOperation = 'copy';
-				}
-				colorCtx.fillStyle = 'rgba(0,0,0,0)';
-				colorCtx.fillStyle = string;
-				colorCtx.fillRect(0, 0, 1, 1);
-				var data = colorCtx.getImageData(0, 0, 1, 1).data;
-				cached = colorCache[string] = [
-					data[0] / 255,
-					data[1] / 255,
-					data[2] / 255
-				];
-			}
-			components = cached.slice();
-		} else {
-			components = [0, 0, 0];
-		}
-		return components;
-	}
-
-	var hsbIndices = [
-		[0, 3, 1],
-		[2, 0, 1],
-		[1, 0, 3],
-		[1, 2, 0],
-		[3, 1, 0],
-		[0, 1, 2]
-	];
-
-	var converters = {
-		'rgb-hsb': function(r, g, b) {
-			var max = Math.max(r, g, b),
-				min = Math.min(r, g, b),
-				delta = max - min,
-				h = delta === 0 ? 0
-					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
-						: max == g ? (b - r) / delta + 2
-						:            (r - g) / delta + 4) * 60;
-			return [h, max === 0 ? 0 : delta / max, max];
-		},
-
-		'hsb-rgb': function(h, s, b) {
-			h = (((h / 60) % 6) + 6) % 6;
-			var i = Math.floor(h),
-				f = h - i,
-				i = hsbIndices[i],
-				v = [
-					b,
-					b * (1 - s),
-					b * (1 - s * f),
-					b * (1 - s * (1 - f))
-				];
-			return [v[i[0]], v[i[1]], v[i[2]]];
-		},
-
-		'rgb-hsl': function(r, g, b) {
-			var max = Math.max(r, g, b),
-				min = Math.min(r, g, b),
-				delta = max - min,
-				achromatic = delta === 0,
-				h = achromatic ? 0
-					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
-						: max == g ? (b - r) / delta + 2
-						:            (r - g) / delta + 4) * 60,
-				l = (max + min) / 2,
-				s = achromatic ? 0 : l < 0.5
-						? delta / (max + min)
-						: delta / (2 - max - min);
-			return [h, s, l];
-		},
-
-		'hsl-rgb': function(h, s, l) {
-			h = (((h / 360) % 1) + 1) % 1;
-			if (s === 0)
-				return [l, l, l];
-			var t3s = [ h + 1 / 3, h, h - 1 / 3 ],
-				t2 = l < 0.5 ? l * (1 + s) : l + s - l * s,
-				t1 = 2 * l - t2,
-				c = [];
-			for (var i = 0; i < 3; i++) {
-				var t3 = t3s[i];
-				if (t3 < 0) t3 += 1;
-				if (t3 > 1) t3 -= 1;
-				c[i] = 6 * t3 < 1
-					? t1 + (t2 - t1) * 6 * t3
-					: 2 * t3 < 1
-						? t2
-						: 3 * t3 < 2
-							? t1 + (t2 - t1) * ((2 / 3) - t3) * 6
-							: t1;
-			}
-			return c;
-		},
-
-		'rgb-gray': function(r, g, b) {
-			return [r * 0.2989 + g * 0.587 + b * 0.114];
-		},
-
-		'gray-rgb': function(g) {
-			return [g, g, g];
-		},
-
-		'gray-hsb': function(g) {
-			return [0, 0, g];
-		},
-
-		'gray-hsl': function(g) {
-			return [0, 0, g];
-		},
-
-		'gradient-rgb': function() {
-			return [];
-		},
-
-		'rgb-gradient': function() {
-			return [];
-		}
-
-	};
-
-	return Base.each(types, function(properties, type) {
-		componentParsers[type] = [];
-		Base.each(properties, function(name, index) {
-			var part = Base.capitalize(name),
-				hasOverlap = /^(hue|saturation)$/.test(name),
-				parser = componentParsers[type][index] = name === 'gradient'
-					? function(value) {
-						var current = this._components[0];
-						value = Gradient.read(Array.isArray(value) ? value
-								: arguments, 0, { readNull: true });
-						if (current !== value) {
-							if (current)
-								current._removeOwner(this);
-							if (value)
-								value._addOwner(this);
-						}
-						return value;
-					}
-					: type === 'gradient'
-						? function() {
-							return Point.read(arguments, 0, {
-									readNull: name === 'highlight',
-									clone: true
-							});
-						}
-						: function(value) {
-							return value == null || isNaN(value) ? 0 : value;
-						};
-
-			this['get' + part] = function() {
-				return this._type === type
-					|| hasOverlap && /^hs[bl]$/.test(this._type)
-						? this._components[index]
-						: this._convert(type)[index];
-			};
-
-			this['set' + part] = function(value) {
-				if (this._type !== type
-						&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {
-					this._components = this._convert(type);
-					this._properties = types[type];
-					this._type = type;
-				}
-				this._components[index] = parser.call(this, value);
-				this._changed();
-			};
-		}, this);
-	}, {
-		_class: 'Color',
-		_readIndex: true,
-
-		initialize: function Color(arg) {
-			var slice = Array.prototype.slice,
-				args = arguments,
-				reading = this.__read,
-				read = 0,
-				type,
-				components,
-				alpha,
-				values;
-			if (Array.isArray(arg)) {
-				args = arg;
-				arg = args[0];
-			}
-			var argType = arg != null && typeof arg;
-			if (argType === 'string' && arg in types) {
-				type = arg;
-				arg = args[1];
-				if (Array.isArray(arg)) {
-					components = arg;
-					alpha = args[2];
-				} else {
-					if (reading)
-						read = 1;
-					args = slice.call(args, 1);
-					argType = typeof arg;
-				}
-			}
-			if (!components) {
-				values = argType === 'number'
-						? args
-						: argType === 'object' && arg.length != null
-							? arg
-							: null;
-				if (values) {
-					if (!type)
-						type = values.length >= 3
-								? 'rgb'
-								: 'gray';
-					var length = types[type].length;
-					alpha = values[length];
-					if (reading) {
-						read += values === arguments
-							? length + (alpha != null ? 1 : 0)
-							: 1;
-					}
-					if (values.length > length)
-						values = slice.call(values, 0, length);
-				} else if (argType === 'string') {
-					type = 'rgb';
-					components = fromCSS(arg);
-					if (components.length === 4) {
-						alpha = components[3];
-						components.length--;
-					}
-				} else if (argType === 'object') {
-					if (arg.constructor === Color) {
-						type = arg._type;
-						components = arg._components.slice();
-						alpha = arg._alpha;
-						if (type === 'gradient') {
-							for (var i = 1, l = components.length; i < l; i++) {
-								var point = components[i];
-								if (point)
-									components[i] = point.clone();
-							}
-						}
-					} else if (arg.constructor === Gradient) {
-						type = 'gradient';
-						values = args;
-					} else {
-						type = 'hue' in arg
-							? 'lightness' in arg
-								? 'hsl'
-								: 'hsb'
-							: 'gradient' in arg || 'stops' in arg
-									|| 'radial' in arg
-								? 'gradient'
-								: 'gray' in arg
-									? 'gray'
-									: 'rgb';
-						var properties = types[type],
-							parsers = componentParsers[type];
-						this._components = components = [];
-						for (var i = 0, l = properties.length; i < l; i++) {
-							var value = arg[properties[i]];
-							if (value == null && i === 0 && type === 'gradient'
-									&& 'stops' in arg) {
-								value = {
-									stops: arg.stops,
-									radial: arg.radial
-								};
-							}
-							value = parsers[i].call(this, value);
-							if (value != null)
-								components[i] = value;
-						}
-						alpha = arg.alpha;
-					}
-				}
-				if (reading && type)
-					read = 1;
-			}
-			this._type = type || 'rgb';
-			if (!components) {
-				this._components = components = [];
-				var parsers = componentParsers[this._type];
-				for (var i = 0, l = parsers.length; i < l; i++) {
-					var value = parsers[i].call(this, values && values[i]);
-					if (value != null)
-						components[i] = value;
-				}
-			}
-			this._components = components;
-			this._properties = types[this._type];
-			this._alpha = alpha;
-			if (reading)
-				this.__read = read;
-		},
-
-		_set: '#initialize',
-
-		_serialize: function(options, dictionary) {
-			var components = this.getComponents();
-			return Base.serialize(
-					/^(gray|rgb)$/.test(this._type)
-						? components
-						: [this._type].concat(components),
-					options, true, dictionary);
-		},
-
-		_changed: function() {
-			this._canvasStyle = null;
-			if (this._owner)
-				this._owner._changed(65);
-		},
-
-		_convert: function(type) {
-			var converter;
-			return this._type === type
-					? this._components.slice()
-					: (converter = converters[this._type + '-' + type])
-						? converter.apply(this, this._components)
-						: converters['rgb-' + type].apply(this,
-							converters[this._type + '-rgb'].apply(this,
-								this._components));
-		},
-
-		convert: function(type) {
-			return new Color(type, this._convert(type), this._alpha);
-		},
-
-		getType: function() {
-			return this._type;
-		},
-
-		setType: function(type) {
-			this._components = this._convert(type);
-			this._properties = types[type];
-			this._type = type;
-		},
-
-		getComponents: function() {
-			var components = this._components.slice();
-			if (this._alpha != null)
-				components.push(this._alpha);
-			return components;
-		},
-
-		getAlpha: function() {
-			return this._alpha != null ? this._alpha : 1;
-		},
-
-		setAlpha: function(alpha) {
-			this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);
-			this._changed();
-		},
-
-		hasAlpha: function() {
-			return this._alpha != null;
-		},
-
-		equals: function(color) {
-			var col = Base.isPlainValue(color, true)
-					? Color.read(arguments)
-					: color;
-			return col === this || col && this._class === col._class
-					&& this._type === col._type
-					&& this._alpha === col._alpha
-					&& Base.equals(this._components, col._components)
-					|| false;
-		},
-
-		toString: function() {
-			var properties = this._properties,
-				parts = [],
-				isGradient = this._type === 'gradient',
-				f = Formatter.instance;
-			for (var i = 0, l = properties.length; i < l; i++) {
-				var value = this._components[i];
-				if (value != null)
-					parts.push(properties[i] + ': '
-							+ (isGradient ? value : f.number(value)));
-			}
-			if (this._alpha != null)
-				parts.push('alpha: ' + f.number(this._alpha));
-			return '{ ' + parts.join(', ') + ' }';
-		},
-
-		toCSS: function(hex) {
-			var components = this._convert('rgb'),
-				alpha = hex || this._alpha == null ? 1 : this._alpha;
-			function convert(val) {
-				return Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);
-			}
-			components = [
-				convert(components[0]),
-				convert(components[1]),
-				convert(components[2])
-			];
-			if (alpha < 1)
-				components.push(alpha < 0 ? 0 : alpha);
-			return hex
-					? '#' + ((1 << 24) + (components[0] << 16)
-						+ (components[1] << 8)
-						+ components[2]).toString(16).slice(1)
-					: (components.length == 4 ? 'rgba(' : 'rgb(')
-						+ components.join(',') + ')';
-		},
-
-		toCanvasStyle: function(ctx) {
-			if (this._canvasStyle)
-				return this._canvasStyle;
-			if (this._type !== 'gradient')
-				return this._canvasStyle = this.toCSS();
-			var components = this._components,
-				gradient = components[0],
-				stops = gradient._stops,
-				origin = components[1],
-				destination = components[2],
-				canvasGradient;
-			if (gradient._radial) {
-				var radius = destination.getDistance(origin),
-					highlight = components[3];
-				if (highlight) {
-					var vector = highlight.subtract(origin);
-					if (vector.getLength() > radius)
-						highlight = origin.add(vector.normalize(radius - 0.1));
-				}
-				var start = highlight || origin;
-				canvasGradient = ctx.createRadialGradient(start.x, start.y,
-						0, origin.x, origin.y, radius);
-			} else {
-				canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
-						destination.x, destination.y);
-			}
-			for (var i = 0, l = stops.length; i < l; i++) {
-				var stop = stops[i];
-				canvasGradient.addColorStop(stop._offset || i / (l - 1),
-						stop._color.toCanvasStyle());
-			}
-			return this._canvasStyle = canvasGradient;
-		},
-
-		transform: function(matrix) {
-			if (this._type === 'gradient') {
-				var components = this._components;
-				for (var i = 1, l = components.length; i < l; i++) {
-					var point = components[i];
-					matrix._transformPoint(point, point, true);
-				}
-				this._changed();
-			}
-		},
-
-		statics: {
-			_types: types,
-
-			random: function() {
-				var random = Math.random;
-				return new Color(random(), random(), random());
-			}
-		}
-	});
-},
-new function() {
-	var operators = {
-		add: function(a, b) {
-			return a + b;
-		},
-
-		subtract: function(a, b) {
-			return a - b;
-		},
-
-		multiply: function(a, b) {
-			return a * b;
-		},
-
-		divide: function(a, b) {
-			return a / b;
-		}
-	};
-
-	return Base.each(operators, function(operator, name) {
-		this[name] = function(color) {
-			color = Color.read(arguments);
-			var type = this._type,
-				components1 = this._components,
-				components2 = color._convert(type);
-			for (var i = 0, l = components1.length; i < l; i++)
-				components2[i] = operator(components1[i], components2[i]);
-			return new Color(type, components2,
-					this._alpha != null
-							? operator(this._alpha, color.getAlpha())
-							: null);
-		};
-	}, {
-	});
-});
-
-var Gradient = Base.extend({
-	_class: 'Gradient',
-
-	initialize: function Gradient(stops, radial) {
-		this._id = UID.get();
-		if (stops && this._set(stops))
-			stops = radial = null;
-		if (!this._stops)
-			this.setStops(stops || ['white', 'black']);
-		if (this._radial == null) {
-			this.setRadial(typeof radial === 'string' && radial === 'radial'
-					|| radial || false);
-		}
-	},
-
-	_serialize: function(options, dictionary) {
-		return dictionary.add(this, function() {
-			return Base.serialize([this._stops, this._radial],
-					options, true, dictionary);
-		});
-	},
-
-	_changed: function() {
-		for (var i = 0, l = this._owners && this._owners.length; i < l; i++) {
-			this._owners[i]._changed();
-		}
-	},
-
-	_addOwner: function(color) {
-		if (!this._owners)
-			this._owners = [];
-		this._owners.push(color);
-	},
-
-	_removeOwner: function(color) {
-		var index = this._owners ? this._owners.indexOf(color) : -1;
-		if (index != -1) {
-			this._owners.splice(index, 1);
-			if (this._owners.length === 0)
-				this._owners = undefined;
-		}
-	},
-
-	clone: function() {
-		var stops = [];
-		for (var i = 0, l = this._stops.length; i < l; i++) {
-			stops[i] = this._stops[i].clone();
-		}
-		return new Gradient(stops, this._radial);
-	},
-
-	getStops: function() {
-		return this._stops;
-	},
-
-	setStops: function(stops) {
-		if (stops.length < 2) {
-			throw new Error(
-					'Gradient stop list needs to contain at least two stops.');
-		}
-		var _stops = this._stops;
-		if (_stops) {
-			for (var i = 0, l = _stops.length; i < l; i++)
-				_stops[i]._owner = undefined;
-		}
-		_stops = this._stops = GradientStop.readAll(stops, 0, { clone: true });
-		for (var i = 0, l = _stops.length; i < l; i++)
-			_stops[i]._owner = this;
-		this._changed();
-	},
-
-	getRadial: function() {
-		return this._radial;
-	},
-
-	setRadial: function(radial) {
-		this._radial = radial;
-		this._changed();
-	},
-
-	equals: function(gradient) {
-		if (gradient === this)
-			return true;
-		if (gradient && this._class === gradient._class) {
-			var stops1 = this._stops,
-				stops2 = gradient._stops,
-				length = stops1.length;
-			if (length === stops2.length) {
-				for (var i = 0; i < length; i++) {
-					if (!stops1[i].equals(stops2[i]))
-						return false;
-				}
-				return true;
-			}
-		}
-		return false;
-	}
-});
-
-var GradientStop = Base.extend({
-	_class: 'GradientStop',
-
-	initialize: function GradientStop(arg0, arg1) {
-		var color = arg0,
-			offset = arg1;
-		if (typeof arg0 === 'object' && arg1 === undefined) {
-			if (Array.isArray(arg0) && typeof arg0[0] !== 'number') {
-				color = arg0[0];
-				offset = arg0[1];
-			} else if ('color' in arg0 || 'offset' in arg0
-					|| 'rampPoint' in arg0) {
-				color = arg0.color;
-				offset = arg0.offset || arg0.rampPoint || 0;
-			}
-		}
-		this.setColor(color);
-		this.setOffset(offset);
-	},
-
-	clone: function() {
-		return new GradientStop(this._color.clone(), this._offset);
-	},
-
-	_serialize: function(options, dictionary) {
-		var color = this._color,
-			offset = this._offset;
-		return Base.serialize(offset == null ? [color] : [color, offset],
-				options, true, dictionary);
-	},
-
-	_changed: function() {
-		if (this._owner)
-			this._owner._changed(65);
-	},
-
-	getOffset: function() {
-		return this._offset;
-	},
-
-	setOffset: function(offset) {
-		this._offset = offset;
-		this._changed();
-	},
-
-	getRampPoint: '#getOffset',
-	setRampPoint: '#setOffset',
-
-	getColor: function() {
-		return this._color;
-	},
-
-	setColor: function() {
-		var color = Color.read(arguments, 0, { clone: true });
-		if (color)
-			color._owner = this;
-		this._color = color;
-		this._changed();
-	},
-
-	equals: function(stop) {
-		return stop === this || stop && this._class === stop._class
-				&& this._color.equals(stop._color)
-				&& this._offset == stop._offset
-				|| false;
-	}
-});
-
-var Style = Base.extend(new function() {
-	var itemDefaults = {
-		fillColor: null,
-		fillRule: 'nonzero',
-		strokeColor: null,
-		strokeWidth: 1,
-		strokeCap: 'butt',
-		strokeJoin: 'miter',
-		strokeScaling: true,
-		miterLimit: 10,
-		dashOffset: 0,
-		dashArray: [],
-		shadowColor: null,
-		shadowBlur: 0,
-		shadowOffset: new Point(),
-		selectedColor: null
-	},
-	groupDefaults = Base.set({}, itemDefaults, {
-		fontFamily: 'sans-serif',
-		fontWeight: 'normal',
-		fontSize: 12,
-		leading: null,
-		justification: 'left'
-	}),
-	textDefaults = Base.set({}, groupDefaults, {
-		fillColor: new Color()
-	}),
-	flags = {
-		strokeWidth: 97,
-		strokeCap: 97,
-		strokeJoin: 97,
-		strokeScaling: 105,
-		miterLimit: 97,
-		fontFamily: 9,
-		fontWeight: 9,
-		fontSize: 9,
-		font: 9,
-		leading: 9,
-		justification: 9
-	},
-	item = {
-		beans: true
-	},
-	fields = {
-		_class: 'Style',
-		beans: true,
-
-		initialize: function Style(style, owner, project) {
-			this._values = {};
-			this._owner = owner;
-			this._project = owner && owner._project || project || paper.project;
-			this._defaults = !owner || owner instanceof Group ? groupDefaults
-					: owner instanceof TextItem ? textDefaults
-					: itemDefaults;
-			if (style)
-				this.set(style);
-		}
-	};
-
-	Base.each(groupDefaults, function(value, key) {
-		var isColor = /Color$/.test(key),
-			isPoint = key === 'shadowOffset',
-			part = Base.capitalize(key),
-			flag = flags[key],
-			set = 'set' + part,
-			get = 'get' + part;
-
-		fields[set] = function(value) {
-			var owner = this._owner,
-				children = owner && owner._children;
-			if (children && children.length > 0
-					&& !(owner instanceof CompoundPath)) {
-				for (var i = 0, l = children.length; i < l; i++)
-					children[i]._style[set](value);
-			} else if (key in this._defaults) {
-				var old = this._values[key];
-				if (old !== value) {
-					if (isColor) {
-						if (old && old._owner !== undefined)
-							old._owner = undefined;
-						if (value && value.constructor === Color) {
-							if (value._owner)
-								value = value.clone();
-							value._owner = owner;
-						}
-					}
-					this._values[key] = value;
-					if (owner)
-						owner._changed(flag || 65);
-				}
-			}
-		};
-
-		fields[get] = function(_dontMerge) {
-			var owner = this._owner,
-				children = owner && owner._children,
-				value;
-			if (key in this._defaults && (!children || children.length === 0
-					|| _dontMerge || owner instanceof CompoundPath)) {
-				var value = this._values[key];
-				if (value === undefined) {
-					value = this._defaults[key];
-					if (value && value.clone)
-						value = value.clone();
-				} else {
-					var ctor = isColor ? Color : isPoint ? Point : null;
-					if (ctor && !(value && value.constructor === ctor)) {
-						this._values[key] = value = ctor.read([value], 0,
-								{ readNull: true, clone: true });
-						if (value && isColor)
-							value._owner = owner;
-					}
-				}
-			} else if (children) {
-				for (var i = 0, l = children.length; i < l; i++) {
-					var childValue = children[i]._style[get]();
-					if (i === 0) {
-						value = childValue;
-					} else if (!Base.equals(value, childValue)) {
-						return undefined;
-					}
-				}
-			}
-			return value;
-		};
-
-		item[get] = function(_dontMerge) {
-			return this._style[get](_dontMerge);
-		};
-
-		item[set] = function(value) {
-			this._style[set](value);
-		};
-	});
-
-	Base.each({
-		Font: 'FontFamily',
-		WindingRule: 'FillRule'
-	}, function(value, key) {
-		var get = 'get' + key,
-			set = 'set' + key;
-		fields[get] = item[get] = '#get' + value;
-		fields[set] = item[set] = '#set' + value;
-	});
-
-	Item.inject(item);
-	return fields;
-}, {
-	set: function(style) {
-		var isStyle = style instanceof Style,
-			values = isStyle ? style._values : style;
-		if (values) {
-			for (var key in values) {
-				if (key in this._defaults) {
-					var value = values[key];
-					this[key] = value && isStyle && value.clone
-							? value.clone() : value;
-				}
-			}
-		}
-	},
-
-	equals: function(style) {
-		return style === this || style && this._class === style._class
-				&& Base.equals(this._values, style._values)
-				|| false;
-	},
-
-	hasFill: function() {
-		var color = this.getFillColor();
-		return !!color && color.alpha > 0;
-	},
-
-	hasStroke: function() {
-		var color = this.getStrokeColor();
-		return !!color && color.alpha > 0 && this.getStrokeWidth() > 0;
-	},
-
-	hasShadow: function() {
-		var color = this.getShadowColor();
-		return !!color && color.alpha > 0 && (this.getShadowBlur() > 0
-				|| !this.getShadowOffset().isZero());
-	},
-
-	getView: function() {
-		return this._project._view;
-	},
-
-	getFontStyle: function() {
-		var fontSize = this.getFontSize();
-		return this.getFontWeight()
-				+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')
-				+ this.getFontFamily();
-	},
-
-	getFont: '#getFontFamily',
-	setFont: '#setFontFamily',
-
-	getLeading: function getLeading() {
-		var leading = getLeading.base.call(this),
-			fontSize = this.getFontSize();
-		if (/pt|em|%|px/.test(fontSize))
-			fontSize = this.getView().getPixelSize(fontSize);
-		return leading != null ? leading : fontSize * 1.2;
-	}
-
-});
-
-var DomElement = new function() {
-	function handlePrefix(el, name, set, value) {
-		var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],
-			suffix = name[0].toUpperCase() + name.substring(1);
-		for (var i = 0; i < 6; i++) {
-			var prefix = prefixes[i],
-				key = prefix ? prefix + suffix : name;
-			if (key in el) {
-				if (set) {
-					el[key] = value;
-				} else {
-					return el[key];
-				}
-				break;
-			}
-		}
-	}
-
-	return {
-		getStyles: function(el) {
-			var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
-				view = doc && doc.defaultView;
-			return view && view.getComputedStyle(el, '');
-		},
-
-		getBounds: function(el, viewport) {
-			var doc = el.ownerDocument,
-				body = doc.body,
-				html = doc.documentElement,
-				rect;
-			try {
-				rect = el.getBoundingClientRect();
-			} catch (e) {
-				rect = { left: 0, top: 0, width: 0, height: 0 };
-			}
-			var x = rect.left - (html.clientLeft || body.clientLeft || 0),
-				y = rect.top - (html.clientTop || body.clientTop || 0);
-			if (!viewport) {
-				var view = doc.defaultView;
-				x += view.pageXOffset || html.scrollLeft || body.scrollLeft;
-				y += view.pageYOffset || html.scrollTop || body.scrollTop;
-			}
-			return new Rectangle(x, y, rect.width, rect.height);
-		},
-
-		getViewportBounds: function(el) {
-			var doc = el.ownerDocument,
-				view = doc.defaultView,
-				html = doc.documentElement;
-			return new Rectangle(0, 0,
-				view.innerWidth || html.clientWidth,
-				view.innerHeight || html.clientHeight
-			);
-		},
-
-		getOffset: function(el, viewport) {
-			return DomElement.getBounds(el, viewport).getPoint();
-		},
-
-		getSize: function(el) {
-			return DomElement.getBounds(el, true).getSize();
-		},
-
-		isInvisible: function(el) {
-			return DomElement.getSize(el).equals(new Size(0, 0));
-		},
-
-		isInView: function(el) {
-			return !DomElement.isInvisible(el)
-					&& DomElement.getViewportBounds(el).intersects(
-						DomElement.getBounds(el, true));
-		},
-
-		isInserted: function(el) {
-			return document.body.contains(el);
-		},
-
-		getPrefixed: function(el, name) {
-			return el && handlePrefix(el, name);
-		},
-
-		setPrefixed: function(el, name, value) {
-			if (typeof name === 'object') {
-				for (var key in name)
-					handlePrefix(el, key, true, name[key]);
-			} else {
-				handlePrefix(el, name, true, value);
-			}
-		}
-	};
-};
-
-var DomEvent = {
-	add: function(el, events) {
-		if (el) {
-			for (var type in events) {
-				var func = events[type],
-					parts = type.split(/[\s,]+/g);
-				for (var i = 0, l = parts.length; i < l; i++)
-					el.addEventListener(parts[i], func, false);
-			}
-		}
-	},
-
-	remove: function(el, events) {
-		if (el) {
-			for (var type in events) {
-				var func = events[type],
-					parts = type.split(/[\s,]+/g);
-				for (var i = 0, l = parts.length; i < l; i++)
-					el.removeEventListener(parts[i], func, false);
-			}
-		}
-	},
-
-	getPoint: function(event) {
-		var pos = event.targetTouches
-				? event.targetTouches.length
-					? event.targetTouches[0]
-					: event.changedTouches[0]
-				: event;
-		return new Point(
-			pos.pageX || pos.clientX + document.documentElement.scrollLeft,
-			pos.pageY || pos.clientY + document.documentElement.scrollTop
-		);
-	},
-
-	getTarget: function(event) {
-		return event.target || event.srcElement;
-	},
-
-	getRelatedTarget: function(event) {
-		return event.relatedTarget || event.toElement;
-	},
-
-	getOffset: function(event, target) {
-		return DomEvent.getPoint(event).subtract(DomElement.getOffset(
-				target || DomEvent.getTarget(event)));
-	}
-};
-
-DomEvent.requestAnimationFrame = new function() {
-	var nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),
-		requested = false,
-		callbacks = [],
-		timer;
-
-	function handleCallbacks() {
-		var functions = callbacks;
-		callbacks = [];
-		for (var i = 0, l = functions.length; i < l; i++)
-			functions[i]();
-		requested = nativeRequest && callbacks.length;
-		if (requested)
-			nativeRequest(handleCallbacks);
-	}
-
-	return function(callback) {
-		callbacks.push(callback);
-		if (nativeRequest) {
-			if (!requested) {
-				nativeRequest(handleCallbacks);
-				requested = true;
-			}
-		} else if (!timer) {
-			timer = setInterval(handleCallbacks, 1000 / 60);
-		}
-	};
-};
-
-var View = Base.extend(Emitter, {
-	_class: 'View',
-
-	initialize: function View(project, element) {
-
-		function getSize(name) {
-			return element[name] || parseInt(element.getAttribute(name), 10);
-		}
-
-		function getCanvasSize() {
-			var size = DomElement.getSize(element);
-			return size.isNaN() || size.isZero()
-					? new Size(getSize('width'), getSize('height'))
-					: size;
-		}
-
-		var size;
-		if (window && element) {
-			this._id = element.getAttribute('id');
-			if (this._id == null)
-				element.setAttribute('id', this._id = 'view-' + View._id++);
-			DomEvent.add(element, this._viewEvents);
-			var none = 'none';
-			DomElement.setPrefixed(element.style, {
-				userDrag: none,
-				userSelect: none,
-				touchCallout: none,
-				contentZooming: none,
-				tapHighlightColor: 'rgba(0,0,0,0)'
-			});
-
-			if (PaperScope.hasAttribute(element, 'resize')) {
-				var that = this;
-				DomEvent.add(window, this._windowEvents = {
-					resize: function() {
-						that.setViewSize(getCanvasSize());
-					}
-				});
-			}
-
-			size = getCanvasSize();
-
-			if (PaperScope.hasAttribute(element, 'stats')
-					&& typeof Stats !== 'undefined') {
-				this._stats = new Stats();
-				var stats = this._stats.domElement,
-					style = stats.style,
-					offset = DomElement.getOffset(element);
-				style.position = 'absolute';
-				style.left = offset.x + 'px';
-				style.top = offset.y + 'px';
-				document.body.appendChild(stats);
-			}
-		} else {
-			size = new Size(element);
-			element = null;
-		}
-		this._project = project;
-		this._scope = project._scope;
-		this._element = element;
-		if (!this._pixelRatio)
-			this._pixelRatio = window && window.devicePixelRatio || 1;
-		this._setElementSize(size.width, size.height);
-		this._viewSize = size;
-		View._views.push(this);
-		View._viewsById[this._id] = this;
-		(this._matrix = new Matrix())._owner = this;
-		this._zoom = 1;
-		if (!View._focused)
-			View._focused = this;
-		this._frameItems = {};
-		this._frameItemCount = 0;
-		this._itemEvents = { native: {}, virtual: {} };
-		this._autoUpdate = !paper.agent.node;
-		this._needsUpdate = false;
-	},
-
-	remove: function() {
-		if (!this._project)
-			return false;
-		if (View._focused === this)
-			View._focused = null;
-		View._views.splice(View._views.indexOf(this), 1);
-		delete View._viewsById[this._id];
-		var project = this._project;
-		if (project._view === this)
-			project._view = null;
-		DomEvent.remove(this._element, this._viewEvents);
-		DomEvent.remove(window, this._windowEvents);
-		this._element = this._project = null;
-		this.off('frame');
-		this._animate = false;
-		this._frameItems = {};
-		return true;
-	},
-
-	_events: Base.each(
-		Item._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),
-		function(name) {
-			this[name] = {};
-		}, {
-			onFrame: {
-				install: function() {
-					this.play();
-				},
-
-				uninstall: function() {
-					this.pause();
-				}
-			}
-		}
-	),
-
-	_animate: false,
-	_time: 0,
-	_count: 0,
-
-	getAutoUpdate: function() {
-		return this._autoUpdate;
-	},
-
-	setAutoUpdate: function(autoUpdate) {
-		this._autoUpdate = autoUpdate;
-		if (autoUpdate)
-			this.requestUpdate();
-	},
-
-	update: function() {
-	},
-
-	draw: function() {
-		this.update();
-	},
-
-	requestUpdate: function() {
-		if (!this._requested) {
-			var that = this;
-			DomEvent.requestAnimationFrame(function() {
-				that._requested = false;
-				if (that._animate) {
-					that.requestUpdate();
-					var element = that._element;
-					if ((!DomElement.getPrefixed(document, 'hidden')
-							|| PaperScope.getAttribute(element, 'keepalive')
-								=== 'true') && DomElement.isInView(element)) {
-						that._handleFrame();
-					}
-				}
-				if (that._autoUpdate)
-					that.update();
-			});
-			this._requested = true;
-		}
-	},
-
-	play: function() {
-		this._animate = true;
-		this.requestUpdate();
-	},
-
-	pause: function() {
-		this._animate = false;
-	},
-
-	_handleFrame: function() {
-		paper = this._scope;
-		var now = Date.now() / 1000,
-			delta = this._last ? now - this._last : 0;
-		this._last = now;
-		this.emit('frame', new Base({
-			delta: delta,
-			time: this._time += delta,
-			count: this._count++
-		}));
-		if (this._stats)
-			this._stats.update();
-	},
-
-	_animateItem: function(item, animate) {
-		var items = this._frameItems;
-		if (animate) {
-			items[item._id] = {
-				item: item,
-				time: 0,
-				count: 0
-			};
-			if (++this._frameItemCount === 1)
-				this.on('frame', this._handleFrameItems);
-		} else {
-			delete items[item._id];
-			if (--this._frameItemCount === 0) {
-				this.off('frame', this._handleFrameItems);
-			}
-		}
-	},
-
-	_handleFrameItems: function(event) {
-		for (var i in this._frameItems) {
-			var entry = this._frameItems[i];
-			entry.item.emit('frame', new Base(event, {
-				time: entry.time += event.delta,
-				count: entry.count++
-			}));
-		}
-	},
-
-	_changed: function() {
-		this._project._changed(2049);
-		this._bounds = null;
-	},
-
-	getElement: function() {
-		return this._element;
-	},
-
-	getPixelRatio: function() {
-		return this._pixelRatio;
-	},
-
-	getResolution: function() {
-		return this._pixelRatio * 72;
-	},
-
-	getViewSize: function() {
-		var size = this._viewSize;
-		return new LinkedSize(size.width, size.height, this, 'setViewSize');
-	},
-
-	setViewSize: function() {
-		var size = Size.read(arguments),
-			width = size.width,
-			height = size.height,
-			delta = size.subtract(this._viewSize);
-		if (delta.isZero())
-			return;
-		this._setElementSize(width, height);
-		this._viewSize.set(width, height);
-		this.emit('resize', {
-			size: size,
-			delta: delta
-		});
-		this._changed();
-		if (this._autoUpdate)
-			this.requestUpdate();
-	},
-
-	_setElementSize: function(width, height) {
-		var element = this._element;
-		if (element) {
-			if (element.width !== width)
-				element.width = width;
-			if (element.height !== height)
-				element.height = height;
-		}
-	},
-
-	getBounds: function() {
-		if (!this._bounds)
-			this._bounds = this._matrix.inverted()._transformBounds(
-					new Rectangle(new Point(), this._viewSize));
-		return this._bounds;
-	},
-
-	getSize: function() {
-		return this.getBounds().getSize();
-	},
-
-	getCenter: function() {
-		return this.getBounds().getCenter();
-	},
-
-	setCenter: function() {
-		var center = Point.read(arguments);
-		this.translate(this.getCenter().subtract(center));
-	},
-
-	getZoom: function() {
-		return this._zoom;
-	},
-
-	setZoom: function(zoom) {
-		this.transform(new Matrix().scale(zoom / this._zoom,
-			this.getCenter()));
-		this._zoom = zoom;
-	},
-
-	getMatrix: function() {
-		return this._matrix;
-	},
-
-	setMatrix: function() {
-		var matrix = this._matrix;
-		matrix.initialize.apply(matrix, arguments);
-	},
-
-	isVisible: function() {
-		return DomElement.isInView(this._element);
-	},
-
-	isInserted: function() {
-		return DomElement.isInserted(this._element);
-	},
-
-	getPixelSize: function(size) {
-		var element = this._element,
-			pixels;
-		if (element) {
-			var parent = element.parentNode,
-				temp = document.createElement('div');
-			temp.style.fontSize = size;
-			parent.appendChild(temp);
-			pixels = parseFloat(DomElement.getStyles(temp).fontSize);
-			parent.removeChild(temp);
-		} else {
-			pixels = parseFloat(pixels);
-		}
-		return pixels;
-	},
-
-	getTextWidth: function(font, lines) {
-		return 0;
-	}
-}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
-	var rotate = key === 'rotate';
-	this[key] = function() {
-		var value = (rotate ? Base : Point).read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		return this.transform(new Matrix()[key](value,
-				center || this.getCenter(true)));
-	};
-}, {
-	translate: function() {
-		var mx = new Matrix();
-		return this.transform(mx.translate.apply(mx, arguments));
-	},
-
-	transform: function(matrix) {
-		this._matrix.append(matrix);
-	},
-
-	scrollBy: function() {
-		this.translate(Point.read(arguments).negate());
-	}
-}), {
-
-	projectToView: function() {
-		return this._matrix._transformPoint(Point.read(arguments));
-	},
-
-	viewToProject: function() {
-		return this._matrix._inverseTransform(Point.read(arguments));
-	},
-
-	getEventPoint: function(event) {
-		return this.viewToProject(DomEvent.getOffset(event, this._element));
-	},
-
-}, {
-	statics: {
-		_views: [],
-		_viewsById: {},
-		_id: 0,
-
-		create: function(project, element) {
-			if (document && typeof element === 'string')
-				element = document.getElementById(element);
-			var ctor = window ? CanvasView : View;
-			return new ctor(project, element);
-		}
-	}
-},
-new function() {
-	if (!window)
-		return;
-	var prevFocus,
-		tempFocus,
-		dragging = false,
-		mouseDown = false;
-
-	function getView(event) {
-		var target = DomEvent.getTarget(event);
-		return target.getAttribute && View._viewsById[
-				target.getAttribute('id')];
-	}
-
-	function updateFocus() {
-		var view = View._focused;
-		if (!view || !view.isVisible()) {
-			for (var i = 0, l = View._views.length; i < l; i++) {
-				if ((view = View._views[i]).isVisible()) {
-					View._focused = tempFocus = view;
-					break;
-				}
-			}
-		}
-	}
-
-	function handleMouseMove(view, event, point) {
-		view._handleMouseEvent('mousemove', event, point);
-	}
-
-	var navigator = window.navigator,
-		mousedown, mousemove, mouseup;
-	if (navigator.pointerEnabled || navigator.msPointerEnabled) {
-		mousedown = 'pointerdown MSPointerDown';
-		mousemove = 'pointermove MSPointerMove';
-		mouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';
-	} else {
-		mousedown = 'touchstart';
-		mousemove = 'touchmove';
-		mouseup = 'touchend touchcancel';
-		if (!('ontouchstart' in window && navigator.userAgent.match(
-				/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {
-			mousedown += ' mousedown';
-			mousemove += ' mousemove';
-			mouseup += ' mouseup';
-		}
-	}
-
-	var viewEvents = {},
-		docEvents = {
-			mouseout: function(event) {
-				var view = View._focused,
-					target = DomEvent.getRelatedTarget(event);
-				if (view && (!target || target.nodeName === 'HTML')) {
-					var offset = DomEvent.getOffset(event, view._element),
-						x = offset.x,
-						abs = Math.abs,
-						ax = abs(x),
-						max = 1 << 25,
-						diff = ax - max;
-					offset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;
-					handleMouseMove(view, event, view.viewToProject(offset));
-				}
-			},
-
-			scroll: updateFocus
-		};
-
-	viewEvents[mousedown] = function(event) {
-		var view = View._focused = getView(event);
-		if (!dragging) {
-			dragging = true;
-			view._handleMouseEvent('mousedown', event);
-		}
-	};
-
-	docEvents[mousemove] = function(event) {
-		var view = View._focused;
-		if (!mouseDown) {
-			var target = getView(event);
-			if (target) {
-				if (view !== target) {
-					if (view)
-						handleMouseMove(view, event);
-					if (!prevFocus)
-						prevFocus = view;
-					view = View._focused = tempFocus = target;
-				}
-			} else if (tempFocus && tempFocus === view) {
-				if (prevFocus && !prevFocus.isInserted())
-					prevFocus = null;
-				view = View._focused = prevFocus;
-				prevFocus = null;
-				updateFocus();
-			}
-		}
-		if (view)
-			handleMouseMove(view, event);
-	};
-
-	docEvents[mousedown] = function() {
-		mouseDown = true;
-	};
-
-	docEvents[mouseup] = function(event) {
-		var view = View._focused;
-		if (view && dragging)
-			view._handleMouseEvent('mouseup', event);
-		mouseDown = dragging = false;
-	};
-
-	DomEvent.add(document, docEvents);
-
-	DomEvent.add(window, {
-		load: updateFocus
-	});
-
-	var called = false,
-		prevented = false,
-		fallbacks = {
-			doubleclick: 'click',
-			mousedrag: 'mousemove'
-		},
-		wasInView = false,
-		overView,
-		downPoint,
-		lastPoint,
-		downItem,
-		overItem,
-		dragItem,
-		clickItem,
-		clickTime,
-		dblClick;
-
-	function emitMouseEvent(obj, target, type, event, point, prevPoint,
-			stopItem) {
-		var stopped = false,
-			mouseEvent;
-
-		function emit(obj, type) {
-			if (obj.responds(type)) {
-				if (!mouseEvent) {
-					mouseEvent = new MouseEvent(type, event, point,
-							target || obj,
-							prevPoint ? point.subtract(prevPoint) : null);
-				}
-				if (obj.emit(type, mouseEvent)) {
-					called = true;
-					if (mouseEvent.prevented)
-						prevented = true;
-					if (mouseEvent.stopped)
-						return stopped = true;
-				}
-			} else {
-				var fallback = fallbacks[type];
-				if (fallback)
-					return emit(obj, fallback);
-			}
-		}
-
-		while (obj && obj !== stopItem) {
-			if (emit(obj, type))
-				break;
-			obj = obj._parent;
-		}
-		return stopped;
-	}
-
-	function emitMouseEvents(view, hitItem, type, event, point, prevPoint) {
-		view._project.removeOn(type);
-		prevented = called = false;
-		return (dragItem && emitMouseEvent(dragItem, null, type, event,
-					point, prevPoint)
-			|| hitItem && hitItem !== dragItem
-				&& !hitItem.isDescendant(dragItem)
-				&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
-					point, prevPoint, dragItem)
-			|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
-					point, prevPoint));
-	}
-
-	var itemEventsMap = {
-		mousedown: {
-			mousedown: 1,
-			mousedrag: 1,
-			click: 1,
-			doubleclick: 1
-		},
-		mouseup: {
-			mouseup: 1,
-			mousedrag: 1,
-			click: 1,
-			doubleclick: 1
-		},
-		mousemove: {
-			mousedrag: 1,
-			mousemove: 1,
-			mouseenter: 1,
-			mouseleave: 1
-		}
-	};
-
-	return {
-		_viewEvents: viewEvents,
-
-		_handleMouseEvent: function(type, event, point) {
-			var itemEvents = this._itemEvents,
-				hitItems = itemEvents.native[type],
-				nativeMove = type === 'mousemove',
-				tool = this._scope.tool,
-				view = this;
-
-			function responds(type) {
-				return itemEvents.virtual[type] || view.responds(type)
-						|| tool && tool.responds(type);
-			}
-
-			if (nativeMove && dragging && responds('mousedrag'))
-				type = 'mousedrag';
-			if (!point)
-				point = this.getEventPoint(event);
-
-			var inView = this.getBounds().contains(point),
-				hit = hitItems && inView && view._project.hitTest(point, {
-					tolerance: 0,
-					fill: true,
-					stroke: true
-				}),
-				hitItem = hit && hit.item || null,
-				handle = false,
-				mouse = {};
-			mouse[type.substr(5)] = true;
-
-			if (hitItems && hitItem !== overItem) {
-				if (overItem) {
-					emitMouseEvent(overItem, null, 'mouseleave', event, point);
-				}
-				if (hitItem) {
-					emitMouseEvent(hitItem, null, 'mouseenter', event, point);
-				}
-				overItem = hitItem;
-			}
-			if (wasInView ^ inView) {
-				emitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',
-						event, point);
-				overView = inView ? this : null;
-				handle = true;
-			}
-			if ((inView || mouse.drag) && !point.equals(lastPoint)) {
-				emitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',
-						event, point, lastPoint);
-				handle = true;
-			}
-			wasInView = inView;
-			if (mouse.down && inView || mouse.up && downPoint) {
-				emitMouseEvents(this, hitItem, type, event, point, downPoint);
-				if (mouse.down) {
-					dblClick = hitItem === clickItem
-						&& (Date.now() - clickTime < 300);
-					downItem = clickItem = hitItem;
-					dragItem = !prevented && hitItem;
-					downPoint = point;
-				} else if (mouse.up) {
-					if (!prevented && hitItem === downItem) {
-						clickTime = Date.now();
-						emitMouseEvents(this, hitItem, dblClick ? 'doubleclick'
-								: 'click', event, point, downPoint);
-						dblClick = false;
-					}
-					downItem = dragItem = null;
-				}
-				wasInView = false;
-				handle = true;
-			}
-			lastPoint = point;
-			if (handle && tool) {
-				called = tool._handleMouseEvent(type, event, point, mouse)
-					|| called;
-			}
-
-			if (called && !mouse.move || mouse.down && responds('mouseup'))
-				event.preventDefault();
-		},
-
-		_handleKeyEvent: function(type, event, key, character) {
-			var scope = this._scope,
-				tool = scope.tool,
-				keyEvent;
-
-			function emit(obj) {
-				if (obj.responds(type)) {
-					paper = scope;
-					obj.emit(type, keyEvent = keyEvent
-							|| new KeyEvent(type, event, key, character));
-				}
-			}
-
-			if (this.isVisible()) {
-				emit(this);
-				if (tool && tool.responds(type))
-					emit(tool);
-			}
-		},
-
-		_countItemEvent: function(type, sign) {
-			var itemEvents = this._itemEvents,
-				native = itemEvents.native,
-				virtual = itemEvents.virtual;
-			for (var key in itemEventsMap) {
-				native[key] = (native[key] || 0)
-						+ (itemEventsMap[key][type] || 0) * sign;
-			}
-			virtual[type] = (virtual[type] || 0) + sign;
-		},
-
-		statics: {
-			updateFocus: updateFocus
-		}
-	};
-});
-
-var CanvasView = View.extend({
-	_class: 'CanvasView',
-
-	initialize: function CanvasView(project, canvas) {
-		if (!(canvas instanceof window.HTMLCanvasElement)) {
-			var size = Size.read(arguments, 1);
-			if (size.isZero())
-				throw new Error(
-						'Cannot create CanvasView with the provided argument: '
-						+ [].slice.call(arguments, 1));
-			canvas = CanvasProvider.getCanvas(size);
-		}
-		var ctx = this._context = canvas.getContext('2d');
-		ctx.save();
-		this._pixelRatio = 1;
-		if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {
-			var deviceRatio = window.devicePixelRatio || 1,
-				backingStoreRatio = DomElement.getPrefixed(ctx,
-						'backingStorePixelRatio') || 1;
-			this._pixelRatio = deviceRatio / backingStoreRatio;
-		}
-		View.call(this, project, canvas);
-		this._needsUpdate = true;
-	},
-
-	remove: function remove() {
-		this._context.restore();
-		return remove.base.call(this);
-	},
-
-	_setElementSize: function _setElementSize(width, height) {
-		var pixelRatio = this._pixelRatio;
-		_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);
-		if (pixelRatio !== 1) {
-			var element = this._element,
-				ctx = this._context;
-			if (!PaperScope.hasAttribute(element, 'resize')) {
-				var style = element.style;
-				style.width = width + 'px';
-				style.height = height + 'px';
-			}
-			ctx.restore();
-			ctx.save();
-			ctx.scale(pixelRatio, pixelRatio);
-		}
-	},
-
-	getPixelSize: function getPixelSize(size) {
-		var agent = paper.agent,
-			pixels;
-		if (agent && agent.firefox) {
-			pixels = getPixelSize.base.call(this, size);
-		} else {
-			var ctx = this._context,
-				prevFont = ctx.font;
-			ctx.font = size + ' serif';
-			pixels = parseFloat(ctx.font);
-			ctx.font = prevFont;
-		}
-		return pixels;
-	},
-
-	getTextWidth: function(font, lines) {
-		var ctx = this._context,
-			prevFont = ctx.font,
-			width = 0;
-		ctx.font = font;
-		for (var i = 0, l = lines.length; i < l; i++)
-			width = Math.max(width, ctx.measureText(lines[i]).width);
-		ctx.font = prevFont;
-		return width;
-	},
-
-	update: function() {
-		if (!this._needsUpdate)
-			return false;
-		var project = this._project,
-			ctx = this._context,
-			size = this._viewSize;
-		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
-		if (project)
-			project.draw(ctx, this._matrix, this._pixelRatio);
-		this._needsUpdate = false;
-		return true;
-	}
-});
-
-var Event = Base.extend({
-	_class: 'Event',
-
-	initialize: function Event(event) {
-		this.event = event;
-		this.type = event && event.type;
-	},
-
-	prevented: false,
-	stopped: false,
-
-	preventDefault: function() {
-		this.prevented = true;
-		this.event.preventDefault();
-	},
-
-	stopPropagation: function() {
-		this.stopped = true;
-		this.event.stopPropagation();
-	},
-
-	stop: function() {
-		this.stopPropagation();
-		this.preventDefault();
-	},
-
-	getTimeStamp: function() {
-		return this.event.timeStamp;
-	},
-
-	getModifiers: function() {
-		return Key.modifiers;
-	}
-});
-
-var KeyEvent = Event.extend({
-	_class: 'KeyEvent',
-
-	initialize: function KeyEvent(type, event, key, character) {
-		this.type = type;
-		this.event = event;
-		this.key = key;
-		this.character = character;
-	},
-
-	toString: function() {
-		return "{ type: '" + this.type
-				+ "', key: '" + this.key
-				+ "', character: '" + this.character
-				+ "', modifiers: " + this.getModifiers()
-				+ " }";
-	}
-});
-
-var Key = new function() {
-	var keyLookup = {
-			'\t': 'tab',
-			' ': 'space',
-			'\b': 'backspace',
-			'\x7f': 'delete',
-			'Spacebar': 'space',
-			'Del': 'delete',
-			'Win': 'meta',
-			'Esc': 'escape'
-		},
-
-		charLookup = {
-			'tab': '\t',
-			'space': ' ',
-			'enter': '\r'
-		},
-
-		keyMap = {},
-		charMap = {},
-		metaFixMap,
-		downKey,
-
-		modifiers = new Base({
-			shift: false,
-			control: false,
-			alt: false,
-			meta: false,
-			capsLock: false,
-			space: false
-		}).inject({
-			option: {
-				get: function() {
-					return this.alt;
-				}
-			},
-
-			command: {
-				get: function() {
-					var agent = paper && paper.agent;
-					return agent && agent.mac ? this.meta : this.control;
-				}
-			}
-		});
-
-	function getKey(event) {
-		var key = event.key || event.keyIdentifier;
-		key = /^U\+/.test(key)
-				? String.fromCharCode(parseInt(key.substr(2), 16))
-				: /^Arrow[A-Z]/.test(key) ? key.substr(5)
-				: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
-				: key;
-		return keyLookup[key] ||
-				(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());
-	}
-
-	function handleKey(down, key, character, event) {
-		var type = down ? 'keydown' : 'keyup',
-			view = View._focused,
-			name;
-		keyMap[key] = down;
-		if (down) {
-			charMap[key] = character;
-		} else {
-			delete charMap[key];
-		}
-		if (key.length > 1 && (name = Base.camelize(key)) in modifiers) {
-			modifiers[name] = down;
-			var agent = paper && paper.agent;
-			if (name === 'meta' && agent && agent.mac) {
-				if (down) {
-					metaFixMap = {};
-				} else {
-					for (var k in metaFixMap) {
-						if (k in charMap)
-							handleKey(false, k, metaFixMap[k], event);
-					}
-					metaFixMap = null;
-				}
-			}
-		} else if (down && metaFixMap) {
-			metaFixMap[key] = character;
-		}
-		if (view) {
-			view._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,
-					character);
-		}
-	}
-
-	DomEvent.add(document, {
-		keydown: function(event) {
-			var key = getKey(event),
-				agent = paper && paper.agent;
-			if (key.length > 1 || agent && (agent.chrome && (event.altKey
-						|| agent.mac && event.metaKey
-						|| !agent.mac && event.ctrlKey))) {
-				handleKey(true, key,
-						charLookup[key] || (key.length > 1 ? '' : key), event);
-			} else {
-				downKey = key;
-			}
-		},
-
-		keypress: function(event) {
-			if (downKey) {
-				var key = getKey(event),
-					code = event.charCode,
-					character = code >= 32 ? String.fromCharCode(code)
-						: key.length > 1 ? '' : key;
-				if (key !== downKey) {
-					key = character.toLowerCase();
-				}
-				handleKey(true, key, character, event);
-				downKey = null;
-			}
-		},
-
-		keyup: function(event) {
-			var key = getKey(event);
-			if (key in charMap)
-				handleKey(false, key, charMap[key], event);
-		}
-	});
-
-	DomEvent.add(window, {
-		blur: function(event) {
-			for (var key in charMap)
-				handleKey(false, key, charMap[key], event);
-		}
-	});
-
-	return {
-		modifiers: modifiers,
-
-		isDown: function(key) {
-			return !!keyMap[key];
-		}
-	};
-};
-
-var MouseEvent = Event.extend({
-	_class: 'MouseEvent',
-
-	initialize: function MouseEvent(type, event, point, target, delta) {
-		this.type = type;
-		this.event = event;
-		this.point = point;
-		this.target = target;
-		this.delta = delta;
-	},
-
-	toString: function() {
-		return "{ type: '" + this.type
-				+ "', point: " + this.point
-				+ ', target: ' + this.target
-				+ (this.delta ? ', delta: ' + this.delta : '')
-				+ ', modifiers: ' + this.getModifiers()
-				+ ' }';
-	}
-});
-
-var ToolEvent = Event.extend({
-	_class: 'ToolEvent',
-	_item: null,
-
-	initialize: function ToolEvent(tool, type, event) {
-		this.tool = tool;
-		this.type = type;
-		this.event = event;
-	},
-
-	_choosePoint: function(point, toolPoint) {
-		return point ? point : toolPoint ? toolPoint.clone() : null;
-	},
-
-	getPoint: function() {
-		return this._choosePoint(this._point, this.tool._point);
-	},
-
-	setPoint: function(point) {
-		this._point = point;
-	},
-
-	getLastPoint: function() {
-		return this._choosePoint(this._lastPoint, this.tool._lastPoint);
-	},
-
-	setLastPoint: function(lastPoint) {
-		this._lastPoint = lastPoint;
-	},
-
-	getDownPoint: function() {
-		return this._choosePoint(this._downPoint, this.tool._downPoint);
-	},
-
-	setDownPoint: function(downPoint) {
-		this._downPoint = downPoint;
-	},
-
-	getMiddlePoint: function() {
-		if (!this._middlePoint && this.tool._lastPoint) {
-			return this.tool._point.add(this.tool._lastPoint).divide(2);
-		}
-		return this._middlePoint;
-	},
-
-	setMiddlePoint: function(middlePoint) {
-		this._middlePoint = middlePoint;
-	},
-
-	getDelta: function() {
-		return !this._delta && this.tool._lastPoint
-				? this.tool._point.subtract(this.tool._lastPoint)
-				: this._delta;
-	},
-
-	setDelta: function(delta) {
-		this._delta = delta;
-	},
-
-	getCount: function() {
-		return this.tool[/^mouse(down|up)$/.test(this.type)
-				? '_downCount' : '_moveCount'];
-	},
-
-	setCount: function(count) {
-		this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
-			= count;
-	},
-
-	getItem: function() {
-		if (!this._item) {
-			var result = this.tool._scope.project.hitTest(this.getPoint());
-			if (result) {
-				var item = result.item,
-					parent = item._parent;
-				while (/^(Group|CompoundPath)$/.test(parent._class)) {
-					item = parent;
-					parent = parent._parent;
-				}
-				this._item = item;
-			}
-		}
-		return this._item;
-	},
-
-	setItem: function(item) {
-		this._item = item;
-	},
-
-	toString: function() {
-		return '{ type: ' + this.type
-				+ ', point: ' + this.getPoint()
-				+ ', count: ' + this.getCount()
-				+ ', modifiers: ' + this.getModifiers()
-				+ ' }';
-	}
-});
-
-var Tool = PaperScopeItem.extend({
-	_class: 'Tool',
-	_list: 'tools',
-	_reference: 'tool',
-	_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',
-			'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',
-			'onKeyUp'],
-
-	initialize: function Tool(props) {
-		PaperScopeItem.call(this);
-		this._moveCount = -1;
-		this._downCount = -1;
-		this._set(props);
-	},
-
-	getMinDistance: function() {
-		return this._minDistance;
-	},
-
-	setMinDistance: function(minDistance) {
-		this._minDistance = minDistance;
-		if (minDistance != null && this._maxDistance != null
-				&& minDistance > this._maxDistance) {
-			this._maxDistance = minDistance;
-		}
-	},
-
-	getMaxDistance: function() {
-		return this._maxDistance;
-	},
-
-	setMaxDistance: function(maxDistance) {
-		this._maxDistance = maxDistance;
-		if (this._minDistance != null && maxDistance != null
-				&& maxDistance < this._minDistance) {
-			this._minDistance = maxDistance;
-		}
-	},
-
-	getFixedDistance: function() {
-		return this._minDistance == this._maxDistance
-			? this._minDistance : null;
-	},
-
-	setFixedDistance: function(distance) {
-		this._minDistance = this._maxDistance = distance;
-	},
-
-	_handleMouseEvent: function(type, event, point, mouse) {
-		paper = this._scope;
-		if (mouse.drag && !this.responds(type))
-			type = 'mousemove';
-		var move = mouse.move || mouse.drag,
-			responds = this.responds(type),
-			minDistance = this.minDistance,
-			maxDistance = this.maxDistance,
-			called = false,
-			tool = this;
-		function update(minDistance, maxDistance) {
-			var pt = point,
-				toolPoint = move ? tool._point : (tool._downPoint || pt);
-			if (move) {
-				if (tool._moveCount && pt.equals(toolPoint)) {
-					return false;
-				}
-				if (toolPoint && (minDistance != null || maxDistance != null)) {
-					var vector = pt.subtract(toolPoint),
-						distance = vector.getLength();
-					if (distance < (minDistance || 0))
-						return false;
-					if (maxDistance) {
-						pt = toolPoint.add(vector.normalize(
-								Math.min(distance, maxDistance)));
-					}
-				}
-				tool._moveCount++;
-			}
-			tool._point = pt;
-			tool._lastPoint = toolPoint || pt;
-			if (mouse.down) {
-				tool._moveCount = -1;
-				tool._downPoint = pt;
-				tool._downCount++;
-			}
-			return true;
-		}
-
-		function emit() {
-			if (responds) {
-				called = tool.emit(type, new ToolEvent(tool, type, event))
-						|| called;
-			}
-		}
-
-		if (mouse.down) {
-			update();
-			emit();
-		} else if (mouse.up) {
-			update(null, maxDistance);
-			emit();
-		} else if (responds) {
-			while (update(minDistance, maxDistance))
-				emit();
-		}
-		return called;
-	}
-
-});
-
-var Http = {
-	request: function(options) {
-		var xhr = new window.XMLHttpRequest();
-		xhr.open((options.method || 'get').toUpperCase(), options.url,
-				Base.pick(options.async, true));
-		if (options.mimeType)
-			xhr.overrideMimeType(options.mimeType);
-		xhr.onload = function() {
-			var status = xhr.status;
-			if (status === 0 || status === 200) {
-				if (options.onLoad) {
-					options.onLoad.call(xhr, xhr.responseText);
-				}
-			} else {
-				xhr.onerror();
-			}
-		};
-		xhr.onerror = function() {
-			var status = xhr.status,
-				message = 'Could not load "' + options.url + '" (Status: '
-						+ status + ')';
-			if (options.onError) {
-				options.onError(message, status);
-			} else {
-				throw new Error(message);
-			}
-		};
-		return xhr.send(null);
-	}
-};
-
-var CanvasProvider = {
-	canvases: [],
-
-	getCanvas: function(width, height) {
-		if (!window)
-			return null;
-		var canvas,
-			clear = true;
-		if (typeof width === 'object') {
-			height = width.height;
-			width = width.width;
-		}
-		if (this.canvases.length) {
-			canvas = this.canvases.pop();
-		} else {
-			canvas = document.createElement('canvas');
-			clear = false;
-		}
-		var ctx = canvas.getContext('2d');
-		if (!ctx) {
-			throw new Error('Canvas ' + canvas +
-					' is unable toprovide a 2D context.');
-		}
-		if (canvas.width === width && canvas.height === height) {
-			if (clear)
-				ctx.clearRect(0, 0, width + 1, height + 1);
-		} else {
-			canvas.width = width;
-			canvas.height = height;
-		}
-		ctx.save();
-		return canvas;
-	},
-
-	getContext: function(width, height) {
-		var canvas = this.getCanvas(width, height);
-		return canvas ? canvas.getContext('2d') : null;
-	},
-
-	release: function(obj) {
-		var canvas = obj && obj.canvas ? obj.canvas : obj;
-		if (canvas && canvas.getContext) {
-			canvas.getContext('2d').restore();
-			this.canvases.push(canvas);
-		}
-	}
-};
-
-var BlendMode = new function() {
-	var min = Math.min,
-		max = Math.max,
-		abs = Math.abs,
-		sr, sg, sb, sa,
-		br, bg, bb, ba,
-		dr, dg, db;
-
-	function getLum(r, g, b) {
-		return 0.2989 * r + 0.587 * g + 0.114 * b;
-	}
-
-	function setLum(r, g, b, l) {
-		var d = l - getLum(r, g, b);
-		dr = r + d;
-		dg = g + d;
-		db = b + d;
-		var l = getLum(dr, dg, db),
-			mn = min(dr, dg, db),
-			mx = max(dr, dg, db);
-		if (mn < 0) {
-			var lmn = l - mn;
-			dr = l + (dr - l) * l / lmn;
-			dg = l + (dg - l) * l / lmn;
-			db = l + (db - l) * l / lmn;
-		}
-		if (mx > 255) {
-			var ln = 255 - l,
-				mxl = mx - l;
-			dr = l + (dr - l) * ln / mxl;
-			dg = l + (dg - l) * ln / mxl;
-			db = l + (db - l) * ln / mxl;
-		}
-	}
-
-	function getSat(r, g, b) {
-		return max(r, g, b) - min(r, g, b);
-	}
-
-	function setSat(r, g, b, s) {
-		var col = [r, g, b],
-			mx = max(r, g, b),
-			mn = min(r, g, b),
-			md;
-		mn = mn === r ? 0 : mn === g ? 1 : 2;
-		mx = mx === r ? 0 : mx === g ? 1 : 2;
-		md = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;
-		if (col[mx] > col[mn]) {
-			col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);
-			col[mx] = s;
-		} else {
-			col[md] = col[mx] = 0;
-		}
-		col[mn] = 0;
-		dr = col[0];
-		dg = col[1];
-		db = col[2];
-	}
-
-	var modes = {
-		multiply: function() {
-			dr = br * sr / 255;
-			dg = bg * sg / 255;
-			db = bb * sb / 255;
-		},
-
-		screen: function() {
-			dr = br + sr - (br * sr / 255);
-			dg = bg + sg - (bg * sg / 255);
-			db = bb + sb - (bb * sb / 255);
-		},
-
-		overlay: function() {
-			dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;
-			dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;
-			db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;
-		},
-
-		'soft-light': function() {
-			var t = sr * br / 255;
-			dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;
-			t = sg * bg / 255;
-			dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;
-			t = sb * bb / 255;
-			db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;
-		},
-
-		'hard-light': function() {
-			dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;
-			dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;
-			db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;
-		},
-
-		'color-dodge': function() {
-			dr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));
-			dg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));
-			db = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));
-		},
-
-		'color-burn': function() {
-			dr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);
-			dg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);
-			db = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);
-		},
-
-		darken: function() {
-			dr = br < sr ? br : sr;
-			dg = bg < sg ? bg : sg;
-			db = bb < sb ? bb : sb;
-		},
-
-		lighten: function() {
-			dr = br > sr ? br : sr;
-			dg = bg > sg ? bg : sg;
-			db = bb > sb ? bb : sb;
-		},
-
-		difference: function() {
-			dr = br - sr;
-			if (dr < 0)
-				dr = -dr;
-			dg = bg - sg;
-			if (dg < 0)
-				dg = -dg;
-			db = bb - sb;
-			if (db < 0)
-				db = -db;
-		},
-
-		exclusion: function() {
-			dr = br + sr * (255 - br - br) / 255;
-			dg = bg + sg * (255 - bg - bg) / 255;
-			db = bb + sb * (255 - bb - bb) / 255;
-		},
-
-		hue: function() {
-			setSat(sr, sg, sb, getSat(br, bg, bb));
-			setLum(dr, dg, db, getLum(br, bg, bb));
-		},
-
-		saturation: function() {
-			setSat(br, bg, bb, getSat(sr, sg, sb));
-			setLum(dr, dg, db, getLum(br, bg, bb));
-		},
-
-		luminosity: function() {
-			setLum(br, bg, bb, getLum(sr, sg, sb));
-		},
-
-		color: function() {
-			setLum(sr, sg, sb, getLum(br, bg, bb));
-		},
-
-		add: function() {
-			dr = min(br + sr, 255);
-			dg = min(bg + sg, 255);
-			db = min(bb + sb, 255);
-		},
-
-		subtract: function() {
-			dr = max(br - sr, 0);
-			dg = max(bg - sg, 0);
-			db = max(bb - sb, 0);
-		},
-
-		average: function() {
-			dr = (br + sr) / 2;
-			dg = (bg + sg) / 2;
-			db = (bb + sb) / 2;
-		},
-
-		negation: function() {
-			dr = 255 - abs(255 - sr - br);
-			dg = 255 - abs(255 - sg - bg);
-			db = 255 - abs(255 - sb - bb);
-		}
-	};
-
-	var nativeModes = this.nativeModes = Base.each([
-		'source-over', 'source-in', 'source-out', 'source-atop',
-		'destination-over', 'destination-in', 'destination-out',
-		'destination-atop', 'lighter', 'darker', 'copy', 'xor'
-	], function(mode) {
-		this[mode] = true;
-	}, {});
-
-	var ctx = CanvasProvider.getContext(1, 1);
-	if (ctx) {
-		Base.each(modes, function(func, mode) {
-			var darken = mode === 'darken',
-				ok = false;
-			ctx.save();
-			try {
-				ctx.fillStyle = darken ? '#300' : '#a00';
-				ctx.fillRect(0, 0, 1, 1);
-				ctx.globalCompositeOperation = mode;
-				if (ctx.globalCompositeOperation === mode) {
-					ctx.fillStyle = darken ? '#a00' : '#300';
-					ctx.fillRect(0, 0, 1, 1);
-					ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken
-							? 170 : 51;
-				}
-			} catch (e) {}
-			ctx.restore();
-			nativeModes[mode] = ok;
-		});
-		CanvasProvider.release(ctx);
-	}
-
-	this.process = function(mode, srcContext, dstContext, alpha, offset) {
-		var srcCanvas = srcContext.canvas,
-			normal = mode === 'normal';
-		if (normal || nativeModes[mode]) {
-			dstContext.save();
-			dstContext.setTransform(1, 0, 0, 1, 0, 0);
-			dstContext.globalAlpha = alpha;
-			if (!normal)
-				dstContext.globalCompositeOperation = mode;
-			dstContext.drawImage(srcCanvas, offset.x, offset.y);
-			dstContext.restore();
-		} else {
-			var process = modes[mode];
-			if (!process)
-				return;
-			var dstData = dstContext.getImageData(offset.x, offset.y,
-					srcCanvas.width, srcCanvas.height),
-				dst = dstData.data,
-				src = srcContext.getImageData(0, 0,
-					srcCanvas.width, srcCanvas.height).data;
-			for (var i = 0, l = dst.length; i < l; i += 4) {
-				sr = src[i];
-				br = dst[i];
-				sg = src[i + 1];
-				bg = dst[i + 1];
-				sb = src[i + 2];
-				bb = dst[i + 2];
-				sa = src[i + 3];
-				ba = dst[i + 3];
-				process();
-				var a1 = sa * alpha / 255,
-					a2 = 1 - a1;
-				dst[i] = a1 * dr + a2 * br;
-				dst[i + 1] = a1 * dg + a2 * bg;
-				dst[i + 2] = a1 * db + a2 * bb;
-				dst[i + 3] = sa * alpha + a2 * ba;
-			}
-			dstContext.putImageData(dstData, offset.x, offset.y);
-		}
-	};
-};
-
-var SvgElement = new function() {
-	var svg = 'http://www.w3.org/2000/svg',
-		xmlns = 'http://www.w3.org/2000/xmlns',
-		xlink = 'http://www.w3.org/1999/xlink',
-		attributeNamespace = {
-			href: xlink,
-			xlink: xmlns,
-			xmlns: xmlns + '/',
-			'xmlns:xlink': xmlns + '/'
-		};
-
-	function create(tag, attributes, formatter) {
-		return set(document.createElementNS(svg, tag), attributes, formatter);
-	}
-
-	function get(node, name) {
-		var namespace = attributeNamespace[name],
-			value = namespace
-				? node.getAttributeNS(namespace, name)
-				: node.getAttribute(name);
-		return value === 'null' ? null : value;
-	}
-
-	function set(node, attributes, formatter) {
-		for (var name in attributes) {
-			var value = attributes[name],
-				namespace = attributeNamespace[name];
-			if (typeof value === 'number' && formatter)
-				value = formatter.number(value);
-			if (namespace) {
-				node.setAttributeNS(namespace, name, value);
-			} else {
-				node.setAttribute(name, value);
-			}
-		}
-		return node;
-	}
-
-	return {
-		svg: svg,
-		xmlns: xmlns,
-		xlink: xlink,
-
-		create: create,
-		get: get,
-		set: set
-	};
-};
-
-var SvgStyles = Base.each({
-	fillColor: ['fill', 'color'],
-	fillRule: ['fill-rule', 'string'],
-	strokeColor: ['stroke', 'color'],
-	strokeWidth: ['stroke-width', 'number'],
-	strokeCap: ['stroke-linecap', 'string'],
-	strokeJoin: ['stroke-linejoin', 'string'],
-	strokeScaling: ['vector-effect', 'lookup', {
-		true: 'none',
-		false: 'non-scaling-stroke'
-	}, function(item, value) {
-		return !value
-				&& (item instanceof PathItem
-					|| item instanceof Shape
-					|| item instanceof TextItem);
-	}],
-	miterLimit: ['stroke-miterlimit', 'number'],
-	dashArray: ['stroke-dasharray', 'array'],
-	dashOffset: ['stroke-dashoffset', 'number'],
-	fontFamily: ['font-family', 'string'],
-	fontWeight: ['font-weight', 'string'],
-	fontSize: ['font-size', 'number'],
-	justification: ['text-anchor', 'lookup', {
-		left: 'start',
-		center: 'middle',
-		right: 'end'
-	}],
-	opacity: ['opacity', 'number'],
-	blendMode: ['mix-blend-mode', 'style']
-}, function(entry, key) {
-	var part = Base.capitalize(key),
-		lookup = entry[2];
-	this[key] = {
-		type: entry[1],
-		property: key,
-		attribute: entry[0],
-		toSVG: lookup,
-		fromSVG: lookup && Base.each(lookup, function(value, name) {
-			this[value] = name;
-		}, {}),
-		exportFilter: entry[3],
-		get: 'get' + part,
-		set: 'set' + part
-	};
-}, {});
-
-new function() {
-	var formatter;
-
-	function getTransform(matrix, coordinates, center) {
-		var attrs = new Base(),
-			trans = matrix.getTranslation();
-		if (coordinates) {
-			matrix = matrix._shiftless();
-			var point = matrix._inverseTransform(trans);
-			attrs[center ? 'cx' : 'x'] = point.x;
-			attrs[center ? 'cy' : 'y'] = point.y;
-			trans = null;
-		}
-		if (!matrix.isIdentity()) {
-			var decomposed = matrix.decompose();
-			if (decomposed) {
-				var parts = [],
-					angle = decomposed.rotation,
-					scale = decomposed.scaling,
-					skew = decomposed.skewing;
-				if (trans && !trans.isZero())
-					parts.push('translate(' + formatter.point(trans) + ')');
-				if (angle)
-					parts.push('rotate(' + formatter.number(angle) + ')');
-				if (!Numerical.isZero(scale.x - 1)
-						|| !Numerical.isZero(scale.y - 1))
-					parts.push('scale(' + formatter.point(scale) +')');
-				if (skew && skew.x)
-					parts.push('skewX(' + formatter.number(skew.x) + ')');
-				if (skew && skew.y)
-					parts.push('skewY(' + formatter.number(skew.y) + ')');
-				attrs.transform = parts.join(' ');
-			} else {
-				attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';
-			}
-		}
-		return attrs;
-	}
-
-	function exportGroup(item, options) {
-		var attrs = getTransform(item._matrix),
-			children = item._children;
-		var node = SvgElement.create('g', attrs, formatter);
-		for (var i = 0, l = children.length; i < l; i++) {
-			var child = children[i];
-			var childNode = exportSVG(child, options);
-			if (childNode) {
-				if (child.isClipMask()) {
-					var clip = SvgElement.create('clipPath');
-					clip.appendChild(childNode);
-					setDefinition(child, clip, 'clip');
-					SvgElement.set(node, {
-						'clip-path': 'url(#' + clip.id + ')'
-					});
-				} else {
-					node.appendChild(childNode);
-				}
-			}
-		}
-		return node;
-	}
-
-	function exportRaster(item, options) {
-		var attrs = getTransform(item._matrix, true),
-			size = item.getSize(),
-			image = item.getImage();
-		attrs.x -= size.width / 2;
-		attrs.y -= size.height / 2;
-		attrs.width = size.width;
-		attrs.height = size.height;
-		attrs.href = options.embedImages === false && image && image.src
-				|| item.toDataURL();
-		return SvgElement.create('image', attrs, formatter);
-	}
-
-	function exportPath(item, options) {
-		var matchShapes = options.matchShapes;
-		if (matchShapes) {
-			var shape = item.toShape(false);
-			if (shape)
-				return exportShape(shape, options);
-		}
-		var segments = item._segments,
-			length = segments.length,
-			type,
-			attrs = getTransform(item._matrix);
-		if (matchShapes && length >= 2 && !item.hasHandles()) {
-			if (length > 2) {
-				type = item._closed ? 'polygon' : 'polyline';
-				var parts = [];
-				for(var i = 0; i < length; i++)
-					parts.push(formatter.point(segments[i]._point));
-				attrs.points = parts.join(' ');
-			} else {
-				type = 'line';
-				var start = segments[0]._point,
-					end = segments[1]._point;
-				attrs.set({
-					x1: start.x,
-					y1: start.y,
-					x2: end.x,
-					y2: end.y
-				});
-			}
-		} else {
-			type = 'path';
-			attrs.d = item.getPathData(null, options.precision);
-		}
-		return SvgElement.create(type, attrs, formatter);
-	}
-
-	function exportShape(item) {
-		var type = item._type,
-			radius = item._radius,
-			attrs = getTransform(item._matrix, true, type !== 'rectangle');
-		if (type === 'rectangle') {
-			type = 'rect';
-			var size = item._size,
-				width = size.width,
-				height = size.height;
-			attrs.x -= width / 2;
-			attrs.y -= height / 2;
-			attrs.width = width;
-			attrs.height = height;
-			if (radius.isZero())
-				radius = null;
-		}
-		if (radius) {
-			if (type === 'circle') {
-				attrs.r = radius;
-			} else {
-				attrs.rx = radius.width;
-				attrs.ry = radius.height;
-			}
-		}
-		return SvgElement.create(type, attrs, formatter);
-	}
-
-	function exportCompoundPath(item, options) {
-		var attrs = getTransform(item._matrix);
-		var data = item.getPathData(null, options.precision);
-		if (data)
-			attrs.d = data;
-		return SvgElement.create('path', attrs, formatter);
-	}
-
-	function exportSymbolItem(item, options) {
-		var attrs = getTransform(item._matrix, true),
-			definition = item._definition,
-			node = getDefinition(definition, 'symbol'),
-			definitionItem = definition._item,
-			bounds = definitionItem.getBounds();
-		if (!node) {
-			node = SvgElement.create('symbol', {
-				viewBox: formatter.rectangle(bounds)
-			});
-			node.appendChild(exportSVG(definitionItem, options));
-			setDefinition(definition, node, 'symbol');
-		}
-		attrs.href = '#' + node.id;
-		attrs.x += bounds.x;
-		attrs.y += bounds.y;
-		attrs.width = bounds.width;
-		attrs.height = bounds.height;
-		attrs.overflow = 'visible';
-		return SvgElement.create('use', attrs, formatter);
-	}
-
-	function exportGradient(color) {
-		var gradientNode = getDefinition(color, 'color');
-		if (!gradientNode) {
-			var gradient = color.getGradient(),
-				radial = gradient._radial,
-				origin = color.getOrigin(),
-				destination = color.getDestination(),
-				attrs;
-			if (radial) {
-				attrs = {
-					cx: origin.x,
-					cy: origin.y,
-					r: origin.getDistance(destination)
-				};
-				var highlight = color.getHighlight();
-				if (highlight) {
-					attrs.fx = highlight.x;
-					attrs.fy = highlight.y;
-				}
-			} else {
-				attrs = {
-					x1: origin.x,
-					y1: origin.y,
-					x2: destination.x,
-					y2: destination.y
-				};
-			}
-			attrs.gradientUnits = 'userSpaceOnUse';
-			gradientNode = SvgElement.create((radial ? 'radial' : 'linear')
-					+ 'Gradient', attrs, formatter);
-			var stops = gradient._stops;
-			for (var i = 0, l = stops.length; i < l; i++) {
-				var stop = stops[i],
-					stopColor = stop._color,
-					alpha = stopColor.getAlpha();
-				attrs = {
-					offset: stop._offset || i / (l - 1)
-				};
-				if (stopColor)
-					attrs['stop-color'] = stopColor.toCSS(true);
-				if (alpha < 1)
-					attrs['stop-opacity'] = alpha;
-				gradientNode.appendChild(
-						SvgElement.create('stop', attrs, formatter));
-			}
-			setDefinition(color, gradientNode, 'color');
-		}
-		return 'url(#' + gradientNode.id + ')';
-	}
-
-	function exportText(item) {
-		var node = SvgElement.create('text', getTransform(item._matrix, true),
-				formatter);
-		node.textContent = item._content;
-		return node;
-	}
-
-	var exporters = {
-		Group: exportGroup,
-		Layer: exportGroup,
-		Raster: exportRaster,
-		Path: exportPath,
-		Shape: exportShape,
-		CompoundPath: exportCompoundPath,
-		SymbolItem: exportSymbolItem,
-		PointText: exportText
-	};
-
-	function applyStyle(item, node, isRoot) {
-		var attrs = {},
-			parent = !isRoot && item.getParent(),
-			style = [];
-
-		if (item._name != null)
-			attrs.id = item._name;
-
-		Base.each(SvgStyles, function(entry) {
-			var get = entry.get,
-				type = entry.type,
-				value = item[get]();
-			if (entry.exportFilter
-					? entry.exportFilter(item, value)
-					: !parent || !Base.equals(parent[get](), value)) {
-				if (type === 'color' && value != null) {
-					var alpha = value.getAlpha();
-					if (alpha < 1)
-						attrs[entry.attribute + '-opacity'] = alpha;
-				}
-				if (type === 'style') {
-					style.push(entry.attribute + ': ' + value);
-				} else {
-					attrs[entry.attribute] = value == null ? 'none'
-							: type === 'color' ? value.gradient
-								? exportGradient(value, item)
-								: value.toCSS(true)
-							: type === 'array' ? value.join(',')
-							: type === 'lookup' ? entry.toSVG[value]
-							: value;
-				}
-			}
-		});
-
-		if (style.length)
-			attrs.style = style.join(';');
-
-		if (attrs.opacity === 1)
-			delete attrs.opacity;
-
-		if (!item._visible)
-			attrs.visibility = 'hidden';
-
-		return SvgElement.set(node, attrs, formatter);
-	}
-
-	var definitions;
-	function getDefinition(item, type) {
-		if (!definitions)
-			definitions = { ids: {}, svgs: {} };
-		var id = item._id || item.__id || (item.__id = UID.get('svg'));
-		return item && definitions.svgs[type + '-' + id];
-	}
-
-	function setDefinition(item, node, type) {
-		if (!definitions)
-			getDefinition();
-		var typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;
-		node.id = type + '-' + typeId;
-		definitions.svgs[type + '-' + (item._id || item.__id)] = node;
-	}
-
-	function exportDefinitions(node, options) {
-		var svg = node,
-			defs = null;
-		if (definitions) {
-			svg = node.nodeName.toLowerCase() === 'svg' && node;
-			for (var i in definitions.svgs) {
-				if (!defs) {
-					if (!svg) {
-						svg = SvgElement.create('svg');
-						svg.appendChild(node);
-					}
-					defs = svg.insertBefore(SvgElement.create('defs'),
-							svg.firstChild);
-				}
-				defs.appendChild(definitions.svgs[i]);
-			}
-			definitions = null;
-		}
-		return options.asString
-				? new window.XMLSerializer().serializeToString(svg)
-				: svg;
-	}
-
-	function exportSVG(item, options, isRoot) {
-		var exporter = exporters[item._class],
-			node = exporter && exporter(item, options);
-		if (node) {
-			var onExport = options.onExport;
-			if (onExport)
-				node = onExport(item, node, options) || node;
-			var data = JSON.stringify(item._data);
-			if (data && data !== '{}' && data !== 'null')
-				node.setAttribute('data-paper-data', data);
-		}
-		return node && applyStyle(item, node, isRoot);
-	}
-
-	function setOptions(options) {
-		if (!options)
-			options = {};
-		formatter = new Formatter(options.precision);
-		return options;
-	}
-
-	Item.inject({
-		exportSVG: function(options) {
-			options = setOptions(options);
-			return exportDefinitions(exportSVG(this, options, true), options);
-		}
-	});
-
-	Project.inject({
-		exportSVG: function(options) {
-			options = setOptions(options);
-			var children = this._children,
-				view = this.getView(),
-				bounds = Base.pick(options.bounds, 'view'),
-				mx = options.matrix || bounds === 'view' && view._matrix,
-				matrix = mx && Matrix.read([mx]),
-				rect = bounds === 'view'
-					? new Rectangle([0, 0], view.getViewSize())
-					: bounds === 'content'
-						? Item._getBounds(children, matrix, { stroke: true })
-						: Rectangle.read([bounds], 0, { readNull: true }),
-				attrs = {
-					version: '1.1',
-					xmlns: SvgElement.svg,
-					'xmlns:xlink': SvgElement.xlink,
-				};
-			if (rect) {
-				attrs.width = rect.width;
-				attrs.height = rect.height;
-				if (rect.x || rect.y)
-					attrs.viewBox = formatter.rectangle(rect);
-			}
-			var node = SvgElement.create('svg', attrs, formatter),
-				parent = node;
-			if (matrix && !matrix.isIdentity()) {
-				parent = node.appendChild(SvgElement.create('g',
-						getTransform(matrix), formatter));
-			}
-			for (var i = 0, l = children.length; i < l; i++) {
-				parent.appendChild(exportSVG(children[i], options, true));
-			}
-			return exportDefinitions(node, options);
-		}
-	});
-};
-
-new function() {
-
-	var definitions = {},
-		rootSize;
-
-	function getValue(node, name, isString, allowNull, allowPercent) {
-		var value = SvgElement.get(node, name),
-			res = value == null
-				? allowNull
-					? null
-					: isString ? '' : 0
-				: isString
-					? value
-					: parseFloat(value);
-		return /%\s*$/.test(value)
-			? (res / 100) * (allowPercent ? 1
-				: rootSize[/x|^width/.test(name) ? 'width' : 'height'])
-			: res;
-	}
-
-	function getPoint(node, x, y, allowNull, allowPercent) {
-		x = getValue(node, x || 'x', false, allowNull, allowPercent);
-		y = getValue(node, y || 'y', false, allowNull, allowPercent);
-		return allowNull && (x == null || y == null) ? null
-				: new Point(x, y);
-	}
-
-	function getSize(node, w, h, allowNull, allowPercent) {
-		w = getValue(node, w || 'width', false, allowNull, allowPercent);
-		h = getValue(node, h || 'height', false, allowNull, allowPercent);
-		return allowNull && (w == null || h == null) ? null
-				: new Size(w, h);
-	}
-
-	function convertValue(value, type, lookup) {
-		return value === 'none' ? null
-				: type === 'number' ? parseFloat(value)
-				: type === 'array' ?
-					value ? value.split(/[\s,]+/g).map(parseFloat) : []
-				: type === 'color' ? getDefinition(value) || value
-				: type === 'lookup' ? lookup[value]
-				: value;
-	}
-
-	function importGroup(node, type, options, isRoot) {
-		var nodes = node.childNodes,
-			isClip = type === 'clippath',
-			isDefs = type === 'defs',
-			item = new Group(),
-			project = item._project,
-			currentStyle = project._currentStyle,
-			children = [];
-		if (!isClip && !isDefs) {
-			item = applyAttributes(item, node, isRoot);
-			project._currentStyle = item._style.clone();
-		}
-		if (isRoot) {
-			var defs = node.querySelectorAll('defs');
-			for (var i = 0, l = defs.length; i < l; i++) {
-				importNode(defs[i], options, false);
-			}
-		}
-		for (var i = 0, l = nodes.length; i < l; i++) {
-			var childNode = nodes[i],
-				child;
-			if (childNode.nodeType === 1
-					&& !/^defs$/i.test(childNode.nodeName)
-					&& (child = importNode(childNode, options, false))
-					&& !(child instanceof SymbolDefinition))
-				children.push(child);
-		}
-		item.addChildren(children);
-		if (isClip)
-			item = applyAttributes(item.reduce(), node, isRoot);
-		project._currentStyle = currentStyle;
-		if (isClip || isDefs) {
-			item.remove();
-			item = null;
-		}
-		return item;
-	}
-
-	function importPoly(node, type) {
-		var coords = node.getAttribute('points').match(
-					/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),
-			points = [];
-		for (var i = 0, l = coords.length; i < l; i += 2)
-			points.push(new Point(
-					parseFloat(coords[i]),
-					parseFloat(coords[i + 1])));
-		var path = new Path(points);
-		if (type === 'polygon')
-			path.closePath();
-		return path;
-	}
-
-	function importPath(node) {
-		return PathItem.create(node.getAttribute('d'));
-	}
-
-	function importGradient(node, type) {
-		var id = (getValue(node, 'href', true) || '').substring(1),
-			radial = type === 'radialgradient',
-			gradient;
-		if (id) {
-			gradient = definitions[id].getGradient();
-			if (gradient._radial ^ radial) {
-				gradient = gradient.clone();
-				gradient._radial = radial;
-			}
-		} else {
-			var nodes = node.childNodes,
-				stops = [];
-			for (var i = 0, l = nodes.length; i < l; i++) {
-				var child = nodes[i];
-				if (child.nodeType === 1)
-					stops.push(applyAttributes(new GradientStop(), child));
-			}
-			gradient = new Gradient(stops, radial);
-		}
-		var origin, destination, highlight,
-			scaleToBounds = getValue(node, 'gradientUnits', true) !==
-				'userSpaceOnUse';
-		if (radial) {
-			origin = getPoint(node, 'cx', 'cy', false, scaleToBounds);
-			destination = origin.add(
-					getValue(node, 'r', false, false, scaleToBounds), 0);
-			highlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);
-		} else {
-			origin = getPoint(node, 'x1', 'y1', false, scaleToBounds);
-			destination = getPoint(node, 'x2', 'y2', false, scaleToBounds);
-		}
-		var color = applyAttributes(
-				new Color(gradient, origin, destination, highlight), node);
-		color._scaleToBounds = scaleToBounds;
-		return null;
-	}
-
-	var importers = {
-		'#document': function (node, type, options, isRoot) {
-			var nodes = node.childNodes;
-			for (var i = 0, l = nodes.length; i < l; i++) {
-				var child = nodes[i];
-				if (child.nodeType === 1)
-					return importNode(child, options, isRoot);
-			}
-		},
-		g: importGroup,
-		svg: importGroup,
-		clippath: importGroup,
-		polygon: importPoly,
-		polyline: importPoly,
-		path: importPath,
-		lineargradient: importGradient,
-		radialgradient: importGradient,
-
-		image: function (node) {
-			var raster = new Raster(getValue(node, 'href', true));
-			raster.on('load', function() {
-				var size = getSize(node);
-				this.setSize(size);
-				var center = this._matrix._transformPoint(
-						getPoint(node).add(size.divide(2)));
-				this.translate(center);
-			});
-			return raster;
-		},
-
-		symbol: function(node, type, options, isRoot) {
-			return new SymbolDefinition(
-					importGroup(node, type, options, isRoot), true);
-		},
-
-		defs: importGroup,
-
-		use: function(node) {
-			var id = (getValue(node, 'href', true) || '').substring(1),
-				definition = definitions[id],
-				point = getPoint(node);
-			return definition
-					? definition instanceof SymbolDefinition
-						? definition.place(point)
-						: definition.clone().translate(point)
-					: null;
-		},
-
-		circle: function(node) {
-			return new Shape.Circle(
-					getPoint(node, 'cx', 'cy'),
-					getValue(node, 'r'));
-		},
-
-		ellipse: function(node) {
-			return new Shape.Ellipse({
-				center: getPoint(node, 'cx', 'cy'),
-				radius: getSize(node, 'rx', 'ry')
-			});
-		},
-
-		rect: function(node) {
-			return new Shape.Rectangle(new Rectangle(
-						getPoint(node),
-						getSize(node)
-					), getSize(node, 'rx', 'ry'));
-			},
-
-		line: function(node) {
-			return new Path.Line(
-					getPoint(node, 'x1', 'y1'),
-					getPoint(node, 'x2', 'y2'));
-		},
-
-		text: function(node) {
-			var text = new PointText(getPoint(node).add(
-					getPoint(node, 'dx', 'dy')));
-			text.setContent(node.textContent.trim() || '');
-			return text;
-		}
-	};
-
-	function applyTransform(item, value, name, node) {
-		if (item.transform) {
-			var transforms = (node.getAttribute(name) || '').split(/\)\s*/g),
-				matrix = new Matrix();
-			for (var i = 0, l = transforms.length; i < l; i++) {
-				var transform = transforms[i];
-				if (!transform)
-					break;
-				var parts = transform.split(/\(\s*/),
-					command = parts[0],
-					v = parts[1].split(/[\s,]+/g);
-				for (var j = 0, m = v.length; j < m; j++)
-					v[j] = parseFloat(v[j]);
-				switch (command) {
-				case 'matrix':
-					matrix.append(
-							new Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));
-					break;
-				case 'rotate':
-					matrix.rotate(v[0], v[1], v[2]);
-					break;
-				case 'translate':
-					matrix.translate(v[0], v[1]);
-					break;
-				case 'scale':
-					matrix.scale(v);
-					break;
-				case 'skewX':
-					matrix.skew(v[0], 0);
-					break;
-				case 'skewY':
-					matrix.skew(0, v[0]);
-					break;
-				}
-			}
-			item.transform(matrix);
-		}
-	}
-
-	function applyOpacity(item, value, name) {
-		var key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',
-			color = item[key] && item[key]();
-		if (color)
-			color.setAlpha(parseFloat(value));
-	}
-
-	var attributes = Base.set(Base.each(SvgStyles, function(entry) {
-		this[entry.attribute] = function(item, value) {
-			if (item[entry.set]) {
-				item[entry.set](convertValue(value, entry.type, entry.fromSVG));
-				if (entry.type === 'color') {
-					var color = item[entry.get]();
-					if (color) {
-						if (color._scaleToBounds) {
-							var bounds = item.getBounds();
-							color.transform(new Matrix()
-								.translate(bounds.getPoint())
-								.scale(bounds.getSize()));
-						}
-						if (item instanceof Shape) {
-							color.transform(new Matrix().translate(
-								item.getPosition(true).negate()));
-						}
-					}
-				}
-			}
-		};
-	}, {}), {
-		id: function(item, value) {
-			definitions[value] = item;
-			if (item.setName)
-				item.setName(value);
-		},
-
-		'clip-path': function(item, value) {
-			var clip = getDefinition(value);
-			if (clip) {
-				clip = clip.clone();
-				clip.setClipMask(true);
-				if (item instanceof Group) {
-					item.insertChild(0, clip);
-				} else {
-					return new Group(clip, item);
-				}
-			}
-		},
-
-		gradientTransform: applyTransform,
-		transform: applyTransform,
-
-		'fill-opacity': applyOpacity,
-		'stroke-opacity': applyOpacity,
-
-		visibility: function(item, value) {
-			if (item.setVisible)
-				item.setVisible(value === 'visible');
-		},
-
-		display: function(item, value) {
-			if (item.setVisible)
-				item.setVisible(value !== null);
-		},
-
-		'stop-color': function(item, value) {
-			if (item.setColor)
-				item.setColor(value);
-		},
-
-		'stop-opacity': function(item, value) {
-			if (item._color)
-				item._color.setAlpha(parseFloat(value));
-		},
-
-		offset: function(item, value) {
-			if (item.setOffset) {
-				var percent = value.match(/(.*)%$/);
-				item.setOffset(percent ? percent[1] / 100 : parseFloat(value));
-			}
-		},
-
-		viewBox: function(item, value, name, node, styles) {
-			var rect = new Rectangle(convertValue(value, 'array')),
-				size = getSize(node, null, null, true),
-				group,
-				matrix;
-			if (item instanceof Group) {
-				var scale = size ? size.divide(rect.getSize()) : 1,
-				matrix = new Matrix().scale(scale)
-						.translate(rect.getPoint().negate());
-				group = item;
-			} else if (item instanceof SymbolDefinition) {
-				if (size)
-					rect.setSize(size);
-				group = item._item;
-			}
-			if (group)  {
-				if (getAttribute(node, 'overflow', styles) !== 'visible') {
-					var clip = new Shape.Rectangle(rect);
-					clip.setClipMask(true);
-					group.addChild(clip);
-				}
-				if (matrix)
-					group.transform(matrix);
-			}
-		}
-	});
-
-	function getAttribute(node, name, styles) {
-		var attr = node.attributes[name],
-			value = attr && attr.value;
-		if (!value) {
-			var style = Base.camelize(name);
-			value = node.style[style];
-			if (!value && styles.node[style] !== styles.parent[style])
-				value = styles.node[style];
-		}
-		return !value ? undefined
-				: value === 'none' ? null
-				: value;
-	}
-
-	function applyAttributes(item, node, isRoot) {
-		var parent = node.parentNode,
-			styles = {
-				node: DomElement.getStyles(node) || {},
-				parent: !isRoot && !/^defs$/i.test(parent.tagName)
-						&& DomElement.getStyles(parent) || {}
-			};
-		Base.each(attributes, function(apply, name) {
-			var value = getAttribute(node, name, styles);
-			item = value !== undefined && apply(item, value, name, node, styles)
-					|| item;
-		});
-		return item;
-	}
-
-	function getDefinition(value) {
-		var match = value && value.match(/\((?:["'#]*)([^"')]+)/),
-			res = match && definitions[match[1]
-				.replace(window.location.href.split('#')[0] + '#', '')];
-		if (res && res._scaleToBounds) {
-			res = res.clone();
-			res._scaleToBounds = true;
-		}
-		return res;
-	}
-
-	function importNode(node, options, isRoot) {
-		var type = node.nodeName.toLowerCase(),
-			isElement = type !== '#document',
-			body = document.body,
-			container,
-			parent,
-			next;
-		if (isRoot && isElement) {
-			rootSize = getSize(node, null, null, true)
-					|| paper.getView().getSize();
-			container = SvgElement.create('svg', {
-				style: 'stroke-width: 1px; stroke-miterlimit: 10'
-			});
-			parent = node.parentNode;
-			next = node.nextSibling;
-			container.appendChild(node);
-			body.appendChild(container);
-		}
-		var settings = paper.settings,
-			applyMatrix = settings.applyMatrix,
-			insertItems = settings.insertItems;
-		settings.applyMatrix = false;
-		settings.insertItems = false;
-		var importer = importers[type],
-			item = importer && importer(node, type, options, isRoot) || null;
-		settings.insertItems = insertItems;
-		settings.applyMatrix = applyMatrix;
-		if (item) {
-			if (isElement && !(item instanceof Group))
-				item = applyAttributes(item, node, isRoot);
-			var onImport = options.onImport,
-				data = isElement && node.getAttribute('data-paper-data');
-			if (onImport)
-				item = onImport(node, item, options) || item;
-			if (options.expandShapes && item instanceof Shape) {
-				item.remove();
-				item = item.toPath();
-			}
-			if (data)
-				item._data = JSON.parse(data);
-		}
-		if (container) {
-			body.removeChild(container);
-			if (parent) {
-				if (next) {
-					parent.insertBefore(node, next);
-				} else {
-					parent.appendChild(node);
-				}
-			}
-		}
-		if (isRoot) {
-			definitions = {};
-			if (item && Base.pick(options.applyMatrix, applyMatrix))
-				item.matrix.apply(true, true);
-		}
-		return item;
-	}
-
-	function importSVG(source, options, owner) {
-		if (!source)
-			return null;
-		options = typeof options === 'function' ? { onLoad: options }
-				: options || {};
-		var scope = paper,
-			item = null;
-
-		function onLoad(svg) {
-			try {
-				var node = typeof svg === 'object' ? svg : new window.DOMParser()
-						.parseFromString(svg, 'image/svg+xml');
-				if (!node.nodeName) {
-					node = null;
-					throw new Error('Unsupported SVG source: ' + source);
-				}
-				paper = scope;
-				item = importNode(node, options, true);
-				if (!options || options.insert !== false) {
-					owner._insertItem(undefined, item);
-				}
-				var onLoad = options.onLoad;
-				if (onLoad)
-					onLoad(item, svg);
-			} catch (e) {
-				onError(e);
-			}
-		}
-
-		function onError(message, status) {
-			var onError = options.onError;
-			if (onError) {
-				onError(message, status);
-			} else {
-				throw new Error(message);
-			}
-		}
-
-		if (typeof source === 'string' && !/^.*</.test(source)) {
-			var node = document.getElementById(source);
-			if (node) {
-				onLoad(node);
-			} else {
-				Http.request({
-					url: source,
-					async: true,
-					onLoad: onLoad,
-					onError: onError
-				});
-			}
-		} else if (typeof File !== 'undefined' && source instanceof File) {
-			var reader = new FileReader();
-			reader.onload = function() {
-				onLoad(reader.result);
-			};
-			reader.onerror = function() {
-				onError(reader.error);
-			};
-			return reader.readAsText(source);
-		} else {
-			onLoad(source);
-		}
-
-		return item;
-	}
-
-	Item.inject({
-		importSVG: function(node, options) {
-			return importSVG(node, options, this);
-		}
-	});
-
-	Project.inject({
-		importSVG: function(node, options) {
-			this.activate();
-			return importSVG(node, options, this);
-		}
-	});
-};
-
-paper = new (PaperScope.inject(Base.exports, {
-	enumerable: true,
-	Base: Base,
-	Numerical: Numerical,
-	Key: Key,
-	DomEvent: DomEvent,
-	DomElement: DomElement,
-	document: document,
-	window: window,
-	Symbol: SymbolDefinition,
-	PlacedSymbol: SymbolItem
-}))();
-
-if (paper.agent.node)
-	require('./node/extend')(paper);
-
-if (typeof define === 'function' && define.amd) {
-	define('paper', paper);
-} else if (typeof module === 'object' && module) {
-	module.exports = paper;
-}
-
-return paper;
-}.call(this, typeof self === 'object' ? self : null);
diff --git a/dist/paper-core.js b/dist/paper-core.js
new file mode 120000
index 00000000..37e257c7
--- /dev/null
+++ b/dist/paper-core.js
@@ -0,0 +1 @@
+../src/load.js
\ No newline at end of file
diff --git a/dist/paper-core.min.js b/dist/paper-core.min.js
deleted file mode 100644
index 548fbcce..00000000
--- a/dist/paper-core.min.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/*!
- * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
- * http://paperjs.org/
- *
- * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
- * http://scratchdisk.com/ & http://jonathanpuckey.com/
- *
- * Distributed under the MIT license. See LICENSE file for details.
- *
- * All rights reserved.
- *
- * Date: Sat Jul 9 20:56:58 2016 +0200
- *
- ***
- *
- * Straps.js - Class inheritance library with support for bean-style accessors
- *
- * Copyright (c) 2006 - 2016 Juerg Lehni
- * http://scratchdisk.com/
- *
- * Distributed under the MIT license.
- *
- ***
- *
- * Acorn.js
- * http://marijnhaverbeke.nl/acorn/
- *
- * Acorn is a tiny, fast JavaScript parser written in JavaScript,
- * created by Marijn Haverbeke and released under an MIT license.
- *
- */
-var paper=function(t,e){var i=t?t.window:require("./node/window"),n=i&&i.document;t=t||i;var r=new function(){function t(t,e,i,n,a){function o(s,o){o=o||(o=u(e,s))&&(o.get?o:o.value),"string"==typeof o&&"#"===o[0]&&(o=t[o.substring(1)]||o);var l,d="function"==typeof o,f=o,_=a||d&&!o.base?o&&o.get?s in t:t[s]:null;a&&_||(d&&_&&(o.base=_),d&&n!==!1&&(l=s.match(/^([gs]et|is)(([A-Z])(.*))$/))&&(h[l[3].toLowerCase()+l[4]]=l[2]),f&&!d&&f.get&&"function"==typeof f.get&&r.isPlainObject(f)||(f={value:f,writable:!0}),(u(t,s)||{configurable:!0}).configurable&&(f.configurable=!0,f.enumerable=i),c(t,s,f))}var h={};if(e){for(var l in e)e.hasOwnProperty(l)&&!s.test(l)&&o(l);for(var l in h){var d=h[l],f=t["set"+d],_=t["get"+d]||f&&t["is"+d];!_||n!==!0&&0!==_.length||o(l,{get:_,set:f})}}return t}function i(t,e,i){return t&&("length"in t&&!t.getLength&&"number"==typeof t.length?a:o).call(t,e,i=i||t),i}function n(t,e,i){for(var n=i,r=e.length;n<r;n++){var s=e[n];for(var a in s)s.hasOwnProperty(a)&&(t[a]=s[a])}return t}var s=/^(statics|enumerable|beans|preserve)$/,a=[].forEach||function(t,e){for(var i=0,n=this.length;i<n;i++)t.call(e,this[i],i,this)},o=function(t,e){for(var i in this)this.hasOwnProperty(i)&&t.call(e,this[i],i,this)},h=Object.create||function(t){return{__proto__:t}},u=Object.getOwnPropertyDescriptor||function(t,e){var i=t.__lookupGetter__&&t.__lookupGetter__(e);return i?{get:i,set:t.__lookupSetter__(e),enumerable:!0,configurable:!0}:t.hasOwnProperty(e)?{value:t[e],enumerable:!0,configurable:!0,writable:!0}:null},l=Object.defineProperty||function(t,e,i){return(i.get||i.set)&&t.__defineGetter__?(i.get&&t.__defineGetter__(e,i.get),i.set&&t.__defineSetter__(e,i.set)):t[e]=i.value,t},c=function(t,e,i){return delete t[e],l(t,e,i)};return t(function(){n(this,arguments,0)},{inject:function(e){if(e){var i=e.statics===!0?e:e.statics,n=e.beans,r=e.preserve;i!==e&&t(this.prototype,e,e.enumerable,n,r),t(this,i,!0,n,r)}for(var s=1,a=arguments.length;s<a;s++)this.inject(arguments[s]);return this},extend:function(){for(var e,i,n,r=this,s=0,a=arguments.length;s<a&&(!e||!i);s++)n=arguments[s],e=e||n.initialize,i=i||n.prototype;return e=e||function(){r.apply(this,arguments)},i=e.prototype=i||h(this.prototype),c(i,"constructor",{value:e,writable:!0,configurable:!0}),t(e,this,!0),arguments.length&&this.inject.apply(e,arguments),e.base=r,e}},!0).inject({inject:function(){for(var e=0,i=arguments.length;e<i;e++){var n=arguments[e];n&&t(this,n,n.enumerable,n.beans,n.preserve)}return this},extend:function(){var t=h(this);return t.inject.apply(t,arguments)},each:function(t,e){return i(this,t,e)},set:function(){return n(this,arguments,0)},clone:function(){return new this.constructor(this)},statics:{each:i,create:h,define:c,describe:u,set:function(t){return n(t,arguments,1)},clone:function(t){return n(new t.constructor,arguments,0)},isPlainObject:function(t){var e=null!=t&&t.constructor;return e&&(e===Object||e===r||"Object"===e.name)},pick:function(t,i){return t!==e?t:i}}})};"undefined"!=typeof module&&(module.exports=r),r.inject({toString:function(){return null!=this._id?(this._class||"Object")+(this._name?" '"+this._name+"'":" @"+this._id):"{ "+r.each(this,function(t,e){if(!/^_/.test(e)){var i=typeof t;this.push(e+": "+("number"===i?h.instance.number(t):"string"===i?"'"+t+"'":t))}},[]).join(", ")+" }"},getClassName:function(){return this._class||""},importJSON:function(t){return r.importJSON(t,this)},exportJSON:function(t){return r.exportJSON(this,t)},toJSON:function(){return r.serialize(this)},_set:function(t){if(t&&r.isPlainObject(t))return r.filter(this,t)},statics:{exports:{enumerable:!0},extend:function nt(){var t=nt.base.apply(this,arguments),e=t.prototype._class;return e&&!r.exports[e]&&(r.exports[e]=t),t},equals:function(t,e){if(t===e)return!0;if(t&&t.equals)return t.equals(e);if(e&&e.equals)return e.equals(t);if(t&&e&&"object"==typeof t&&"object"==typeof e){if(Array.isArray(t)&&Array.isArray(e)){var i=t.length;if(i!==e.length)return!1;for(;i--;)if(!r.equals(t[i],e[i]))return!1}else{var n=Object.keys(t),i=n.length;if(i!==Object.keys(e).length)return!1;for(;i--;){var s=n[i];if(!e.hasOwnProperty(s)||!r.equals(t[s],e[s]))return!1}}return!0}return!1},read:function(t,i,n,s){if(this===r){var a=this.peek(t,i);return t.__index++,a}var o=this.prototype,h=o._readIndex,u=i||h&&t.__index||0;s||(s=t.length-u);var l=t[u];return l instanceof this||n&&n.readNull&&null==l&&s<=1?(h&&(t.__index=u+1),l&&n&&n.clone?l.clone():l):(l=r.create(this.prototype),h&&(l.__read=!0),l=l.initialize.apply(l,u>0||s<t.length?Array.prototype.slice.call(t,u,u+s):t)||l,h&&(t.__index=u+l.__read,l.__read=e),l)},peek:function(t,e){return t[t.__index=e||t.__index||0]},remain:function(t){return t.length-(t.__index||0)},readAll:function(t,e,i){for(var n,r=[],s=e||0,a=t.length;s<a;s++)r.push(Array.isArray(n=t[s])?this.read(n,0,i):this.read(t,s,i,1));return r},readNamed:function(t,i,n,s,a){var o=this.getNamed(t,i),h=o!==e;if(h){var u=t._filtered;u||(u=t._filtered=r.create(t[0]),u._filtering=t[0]),u[i]=e}return this.read(h?[o]:t,n,s,a)},getNamed:function(t,i){var n=t[0];if(t._hasObject===e&&(t._hasObject=1===t.length&&r.isPlainObject(n)),t._hasObject)return i?n[i]:t._filtered||n},hasNamed:function(t,e){return!!this.getNamed(t,e)},filter:function(t,i,n){for(var r=Object.keys(i._filtering||i),s=0,a=r.length;s<a;s++){var o=r[s];if(!n||!n[o]){var h=i[o];h!==e&&(t[o]=h)}}return t},isPlainValue:function(t,e){return this.isPlainObject(t)||Array.isArray(t)||e&&"string"==typeof t},serialize:function(t,e,i,n){e=e||{};var s,a=!n;if(a&&(e.formatter=new h(e.precision),n={length:0,definitions:{},references:{},add:function(t,e){var i="#"+t._id,n=this.references[i];if(!n){this.length++;var r=e.call(t),s=t._class;s&&r[0]!==s&&r.unshift(s),this.definitions[i]=r,n=this.references[i]=[i]}return n}}),t&&t._serialize){s=t._serialize(e,n);var o=t._class;!o||t._compactSerialize||!a&&i||s[0]===o||s.unshift(o)}else if(Array.isArray(t)){s=[];for(var u=0,l=t.length;u<l;u++)s[u]=r.serialize(t[u],e,i,n)}else if(r.isPlainObject(t)){s={};for(var c=Object.keys(t),u=0,l=c.length;u<l;u++){var d=c[u];s[d]=r.serialize(t[d],e,i,n)}}else s="number"==typeof t?e.formatter.number(t,e.precision):t;return a&&n.length>0?[["dictionary",n.definitions],s]:s},deserialize:function(t,e,i,n,s){var a=t,o=!i,h=o&&t&&t.length&&"dictionary"===t[0][0];if(i=i||{},Array.isArray(t)){var u=t[0],l="dictionary"===u;if(1==t.length&&/^#/.test(u))return i.dictionary[u];u=r.exports[u],a=[];for(var c=u?1:0,d=t.length;c<d;c++)a.push(r.deserialize(t[c],e,i,l,h));if(u){var f=a;e?a=e(u,f,o||s):(a=r.create(u.prototype),u.apply(a,f))}}else if(r.isPlainObject(t)){a={},n&&(i.dictionary=a);for(var _ in t)a[_]=r.deserialize(t[_],e,i)}return h?a[1]:a},exportJSON:function(t,e){var i=r.serialize(t,e);return e&&e.asString===!1?i:JSON.stringify(i)},importJSON:function(t,e){return r.deserialize("string"==typeof t?JSON.parse(t):t,function(t,i,n){var s=n&&e&&e.constructor===t,a=s?e:r.create(t.prototype);if(1===i.length&&a instanceof w&&(s||!(a instanceof b))){var o=i[0];r.isPlainObject(o)&&(o.insert=!1)}return(s?a._set:t).apply(a,i),s&&(e=null),a})},splice:function(t,i,n,r){var s=i&&i.length,a=n===e;n=a?t.length:n,n>t.length&&(n=t.length);for(var o=0;o<s;o++)i[o]._index=n+o;if(a)return t.push.apply(t,i),[];var h=[n,r];i&&h.push.apply(h,i);for(var u=t.splice.apply(t,h),o=0,l=u.length;o<l;o++)u[o]._index=e;for(var o=n+s,l=t.length;o<l;o++)t[o]._index=o;return u},capitalize:function(t){return t.replace(/\b[a-z]/g,function(t){return t.toUpperCase()})},camelize:function(t){return t.replace(/-(.)/g,function(t,e){return e.toUpperCase()})},hyphenate:function(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}}});var s={on:function(t,e){if("string"!=typeof t)r.each(t,function(t,e){this.on(e,t)},this);else{var i=this._eventTypes,n=i&&i[t],s=this._callbacks=this._callbacks||{};s=s[t]=s[t]||[],s.indexOf(e)===-1&&(s.push(e),n&&n.install&&1===s.length&&n.install.call(this,t))}return this},off:function(t,e){if("string"!=typeof t)return void r.each(t,function(t,e){this.off(e,t)},this);var i,n=this._eventTypes,s=n&&n[t],a=this._callbacks&&this._callbacks[t];return a&&(!e||(i=a.indexOf(e))!==-1&&1===a.length?(s&&s.uninstall&&s.uninstall.call(this,t),delete this._callbacks[t]):i!==-1&&a.splice(i,1)),this},once:function(t,e){return this.on(t,function(){e.apply(this,arguments),this.off(t,e)})},emit:function(t,e){var i=this._callbacks&&this._callbacks[t];if(!i)return!1;var n=[].slice.call(arguments,1),r=e&&e.target&&!e.currentTarget;i=i.slice(),r&&(e.currentTarget=this);for(var s=0,a=i.length;s<a;s++)if(i[s].apply(this,n)===!1){e&&e.stop&&e.stop();break}return r&&delete e.currentTarget,!0},responds:function(t){return!(!this._callbacks||!this._callbacks[t])},attach:"#on",detach:"#off",fire:"#emit",_installEvents:function(t){var e=this._eventTypes,i=this._callbacks,n=t?"install":"uninstall";if(e)for(var r in i)if(i[r].length>0){var s=e[r],a=s&&s[n];a&&a.call(this,r)}},statics:{inject:function rt(t){var e=t._events;if(e){var i={};r.each(e,function(e,n){var s="string"==typeof e,a=s?e:n,o=r.capitalize(a),h=a.substring(2).toLowerCase();i[h]=s?{}:e,a="_"+a,t["get"+o]=function(){return this[a]},t["set"+o]=function(t){var e=this[a];e&&this.off(h,e),t&&this.on(h,t),this[a]=t}}),t._eventTypes=i}return rt.base.apply(this,arguments)}}},a=r.extend({_class:"PaperScope",initialize:function st(){paper=this,this.settings=new r({applyMatrix:!0,insertItems:!0,handleSize:4,hitTolerance:0}),this.project=null,this.projects=[],this.tools=[],this.palettes=[],this._id=st._id++,st._scopes[this._id]=this;var e=st.prototype;if(!this.support){var i=Q.getContext(1,1)||{};e.support={nativeDash:"setLineDash"in i||"mozDash"in i,nativeBlendModes:tt.nativeModes},Q.release(i)}if(!this.agent){var n=t.navigator.userAgent.toLowerCase(),s=(/(darwin|win|mac|linux|freebsd|sunos)/.exec(n)||[])[0],a="darwin"===s?"mac":s,o=e.agent=e.browser={platform:a};a&&(o[a]=!0),n.replace(/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,function(t,e,i,n,r){if(!o.chrome){var s="opera"===e?n:/^(node|trident)$/.test(e)?r:i;o.version=s,o.versionNumber=parseFloat(s),e="trident"===e?"msie":e,o.name=e,o[e]=!0}}),o.chrome&&delete o.webkit,o.atom&&delete o.chrome}},version:"0.10.2",getView:function(){var t=this.project;return t&&t._view},getPaper:function(){return this},execute:function(t,e){paper.PaperScript.execute(t,this,e),U.updateFocus()},install:function(t){var e=this;r.each(["project","view","tool"],function(i){r.define(t,i,{configurable:!0,get:function(){return e[i]}})});for(var i in this)!/^_/.test(i)&&this[i]&&(t[i]=this[i])},setup:function(t){return paper=this,this.project=new y(t),this},createCanvas:function(t,e){return Q.getCanvas(t,e)},activate:function(){paper=this},clear:function(){for(var t=this.projects,e=this.tools,i=this.palettes,n=t.length-1;n>=0;n--)t[n].remove();for(var n=e.length-1;n>=0;n--)e[n].remove();for(var n=i.length-1;n>=0;n--)i[n].remove()},remove:function(){this.clear(),delete a._scopes[this._id]},statics:new function(){function t(t){return t+="Attribute",function(e,i){return e[t](i)||e[t]("data-paper-"+i)}}return{_scopes:{},_id:0,get:function(t){return this._scopes[t]||null},getAttribute:t("get"),hasAttribute:t("has")}}}),o=r.extend(s,{initialize:function(t){this._scope=paper,this._index=this._scope[this._list].push(this)-1,!t&&this._scope[this._reference]||this.activate()},activate:function(){if(!this._scope)return!1;var t=this._scope[this._reference];return t&&t!==this&&t.emit("deactivate"),this._scope[this._reference]=this,this.emit("activate",t),!0},isActive:function(){return this._scope[this._reference]===this},remove:function(){return null!=this._index&&(r.splice(this._scope[this._list],null,this._index,1),this._scope[this._reference]==this&&(this._scope[this._reference]=null),this._scope=null,!0)},getView:function(){return this._scope.getView()}}),h=r.extend({initialize:function(t){this.precision=r.pick(t,5),this.multiplier=Math.pow(10,this.precision)},number:function(t){return this.precision<16?Math.round(t*this.multiplier)/this.multiplier:t},pair:function(t,e,i){return this.number(t)+(i||",")+this.number(e)},point:function(t,e){return this.number(t.x)+(e||",")+this.number(t.y)},size:function(t,e){return this.number(t.width)+(e||",")+this.number(t.height)},rectangle:function(t,e){return this.point(t,e)+(e||",")+this.size(t,e)}});h.instance=new h;var u=new function(){function t(t,e,i){return t<e?e:t>i?i:t}function e(t,e,i){function n(t){var e=134217729*t,i=t-e,n=i+e,r=t-n;return[n,r]}var r=e*e-t*i,a=e*e+t*i;if(3*s(r)<a){var o=n(t),h=n(e),u=n(i),l=e*e,c=h[0]*h[0]-l+2*h[0]*h[1]+h[1]*h[1],d=t*i,f=o[0]*u[0]-d+o[0]*u[1]+o[1]*u[0]+o[1]*u[1];r=l-d+(c-f)}return r}function i(){var t=Math.max.apply(Math,arguments);return t&&(t<1e-8||t>1e8)?o(2,-Math.round(h(t))):0}var n=[[.5773502691896257],[0,.7745966692414834],[.33998104358485626,.8611363115940526],[0,.5384693101056831,.906179845938664],[.2386191860831969,.6612093864662645,.932469514203152],[0,.4058451513773972,.7415311855993945,.9491079123427585],[.1834346424956498,.525532409916329,.7966664774136267,.9602898564975363],[0,.3242534234038089,.6133714327005904,.8360311073266358,.9681602395076261],[.14887433898163122,.4333953941292472,.6794095682990244,.8650633666889845,.9739065285171717],[0,.26954315595234496,.5190961292068118,.7301520055740494,.8870625997680953,.978228658146057],[.1252334085114689,.3678314989981802,.5873179542866175,.7699026741943047,.9041172563704749,.9815606342467192],[0,.2304583159551348,.44849275103644687,.6423493394403402,.8015780907333099,.9175983992229779,.9841830547185881],[.10805494870734367,.31911236892788974,.5152486363581541,.6872929048116855,.827201315069765,.9284348836635735,.9862838086968123],[0,.20119409399743451,.3941513470775634,.5709721726085388,.7244177313601701,.8482065834104272,.937273392400706,.9879925180204854],[.09501250983763744,.2816035507792589,.45801677765722737,.6178762444026438,.755404408355003,.8656312023878318,.9445750230732326,.9894009349916499]],r=[[1],[.8888888888888888,.5555555555555556],[.6521451548625461,.34785484513745385],[.5688888888888889,.47862867049936647,.23692688505618908],[.46791393457269104,.3607615730481386,.17132449237917036],[.4179591836734694,.3818300505051189,.27970539148927664,.1294849661688697],[.362683783378362,.31370664587788727,.22238103445337448,.10122853629037626],[.3302393550012598,.31234707704000286,.26061069640293544,.1806481606948574,.08127438836157441],[.29552422471475287,.26926671930999635,.21908636251598204,.1494513491505806,.06667134430868814],[.2729250867779006,.26280454451024665,.23319376459199048,.18629021092773426,.1255803694649046,.05566856711617366],[.24914704581340277,.2334925365383548,.20316742672306592,.16007832854334622,.10693932599531843,.04717533638651183],[.2325515532308739,.22628318026289723,.2078160475368885,.17814598076194574,.13887351021978725,.09212149983772845,.04048400476531588],[.2152638534631578,.2051984637212956,.18553839747793782,.15720316715819355,.12151857068790319,.08015808715976021,.03511946033175186],[.2025782419255613,.19843148532711158,.1861610000155622,.16626920581699392,.13957067792615432,.10715922046717194,.07036604748810812,.03075324199611727],[.1894506104550685,.18260341504492358,.16915651939500254,.14959598881657674,.12462897125553388,.09515851168249279,.062253523938647894,.027152459411754096]],s=Math.abs,a=Math.sqrt,o=Math.pow,h=Math.log2||function(t){return Math.log(t)*Math.LOG2E},l=1e-12,c=1.12e-16;return{TOLERANCE:1e-6,EPSILON:l,MACHINE_EPSILON:c,CURVETIME_EPSILON:4e-7,GEOMETRIC_EPSILON:2e-7,WINDING_EPSILON:2e-7,TRIGONOMETRIC_EPSILON:1e-7,CLIPPING_EPSILON:1e-9,KAPPA:4*(a(2)-1)/3,isZero:function(t){return t>=-l&&t<=l},clamp:t,integrate:function(t,e,i,s){for(var a=n[s-2],o=r[s-2],h=.5*(i-e),u=h+e,l=0,c=s+1>>1,d=1&s?o[l++]*t(u):0;l<c;){var f=h*a[l];d+=o[l++]*(t(u+f)+t(u-f))}return h*d},findRoot:function(t,e,i,n,r,a,o){for(var h=0;h<a;h++){var u=t(i),l=u/e(i),c=i-l;if(s(l)<o)return c;u>0?(r=i,i=c<=n?.5*(n+r):c):(n=i,i=c>=r?.5*(n+r):c)}return i},solveQuadratic:function(n,r,o,h,u,d){var f,_=1/0;if(s(n)<l){if(s(r)<l)return s(o)<l?-1:0;f=-o/r}else{r*=-.5;var g=e(n,r,o);if(g&&s(g)<c){var v=i(s(n),s(r),s(o));v&&(n*=v,r*=v,o*=v,g=e(n,r,o))}if(g>=-c){var p=g<0?0:a(g),m=r+(r<0?-p:p);0===m?(f=o/n,_=-f):(f=m/n,_=o/m)}}var y=0,w=null==u,x=u-l,b=d+l;return isFinite(f)&&(w||f>x&&f<b)&&(h[y++]=w?f:t(f,u,d)),_!==f&&isFinite(_)&&(w||_>x&&_<b)&&(h[y++]=w?_:t(_,u,d)),y},solveCubic:function(e,n,r,h,d,f,_){function g(t){v=t;var i=e*v;p=i+n,m=p*v+r,y=(i+p)*v+m,w=m*v+h}var v,p,m,y,w,x=i(s(e),s(n),s(r),s(h));if(x&&(e*=x,n*=x,r*=x,h*=x),s(e)<l)e=n,p=r,m=h,v=1/0;else if(s(h)<l)p=n,m=r,v=0;else{g(-(n/e)/3);var b=w/e,C=o(s(b),1/3),S=b<0?-1:1,P=-y/e,I=P>0?1.324717957244746*Math.max(C,a(P)):C,M=v-S*I;if(M!==v){do g(M),M=0===y?v:v-w/y/(1+c);while(S*M>S*v);s(e)*v*v>s(h/v)&&(m=-h/v,p=(m-r)/v)}}var T=u.solveQuadratic(e,p,m,d,f,_),k=null==f;return isFinite(v)&&(0===T||T>0&&v!==d[0]&&v!==d[1])&&(k||v>f-l&&v<_+l)&&(d[T++]=k?v:t(v,f,_)),T}}},l={_id:1,_pools:{},get:function(t){if(t){var e=this._pools[t];return e||(e=this._pools[t]={_id:1}),e._id++}return this._id++}},c=r.extend({_class:"Point",_readIndex:!0,initialize:function(t,e){var i=typeof t;if("number"===i){var n="number"==typeof e;this.x=t,this.y=n?e:t,this.__read&&(this.__read=n?2:1)}else if("undefined"===i||null===t)this.x=this.y=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===i?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.x=r[0],this.y=r.length>1?r[1]:r[0]):"x"in r?(this.x=r.x,this.y=r.y):"width"in r?(this.x=r.width,this.y=r.height):"angle"in r?(this.x=r.length,this.y=0,this.setAngle(r.angle)):(this.x=this.y=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.x=t,this.y=e,this},equals:function(t){return this===t||t&&(this.x===t.x&&this.y===t.y||Array.isArray(t)&&this.x===t[0]&&this.y===t[1])||!1},clone:function(){return new c(this.x,this.y)},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y)]},getLength:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},setLength:function(t){if(this.isZero()){var e=this._angle||0;this.set(Math.cos(e)*t,Math.sin(e)*t)}else{var i=t/this.getLength();u.isZero(i)&&this.getAngle(),this.set(this.x*i,this.y*i)}},getAngle:function(){return 180*this.getAngleInRadians.apply(this,arguments)/Math.PI},setAngle:function(t){this.setAngleInRadians.call(this,t*Math.PI/180)},getAngleInDegrees:"#getAngle",setAngleInDegrees:"#setAngle",getAngleInRadians:function(){if(arguments.length){var t=c.read(arguments),e=this.getLength()*t.getLength();if(u.isZero(e))return NaN;var i=this.dot(t)/e;return Math.acos(i<-1?-1:i>1?1:i)}return this.isZero()?this._angle||0:this._angle=Math.atan2(this.y,this.x)},setAngleInRadians:function(t){if(this._angle=t,!this.isZero()){var e=this.getLength();this.set(Math.cos(t)*e,Math.sin(t)*e)}},getQuadrant:function(){return this.x>=0?this.y>=0?1:4:this.y>=0?2:3}},{beans:!1,getDirectedAngle:function(){var t=c.read(arguments);return 180*Math.atan2(this.cross(t),this.dot(t))/Math.PI},getDistance:function(){var t=c.read(arguments),e=t.x-this.x,i=t.y-this.y,n=e*e+i*i,s=r.read(arguments);return s?n:Math.sqrt(n)},normalize:function(t){t===e&&(t=1);var i=this.getLength(),n=0!==i?t/i:0,r=new c(this.x*n,this.y*n);return n>=0&&(r._angle=this._angle),r},rotate:function(t,e){if(0===t)return this.clone();t=t*Math.PI/180;var i=e?this.subtract(e):this,n=Math.sin(t),r=Math.cos(t);return i=new c(i.x*r-i.y*n,i.x*n+i.y*r),e?i.add(e):i},transform:function(t){return t?t._transformPoint(this):this},add:function(){var t=c.read(arguments);return new c(this.x+t.x,this.y+t.y)},subtract:function(){var t=c.read(arguments);return new c(this.x-t.x,this.y-t.y)},multiply:function(){var t=c.read(arguments);return new c(this.x*t.x,this.y*t.y)},divide:function(){var t=c.read(arguments);return new c(this.x/t.x,this.y/t.y)},modulo:function(){var t=c.read(arguments);return new c(this.x%t.x,this.y%t.y)},negate:function(){return new c((-this.x),(-this.y))},isInside:function(){return g.read(arguments).contains(this)},isClose:function(){var t=c.read(arguments),e=r.read(arguments);return this.getDistance(t)<=e},isCollinear:function(){var t=c.read(arguments);return c.isCollinear(this.x,this.y,t.x,t.y)},isColinear:"#isCollinear",isOrthogonal:function(){var t=c.read(arguments);return c.isOrthogonal(this.x,this.y,t.x,t.y)},isZero:function(){return u.isZero(this.x)&&u.isZero(this.y)},isNaN:function(){return isNaN(this.x)||isNaN(this.y)},dot:function(){var t=c.read(arguments);return this.x*t.x+this.y*t.y},cross:function(){var t=c.read(arguments);return this.x*t.y-this.y*t.x},project:function(){var t=c.read(arguments),e=t.isZero()?0:this.dot(t)/t.dot(t);return new c(t.x*e,t.y*e)},statics:{min:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.min(t.x,e.x),Math.min(t.y,e.y))},max:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.max(t.x,e.x),Math.max(t.y,e.y))},random:function(){return new c(Math.random(),Math.random())},isCollinear:function(t,e,i,n){return Math.abs(t*n-e*i)<=1e-7*Math.sqrt((t*t+e*e)*(i*i+n*n))},isOrthogonal:function(t,e,i,n){return Math.abs(t*i+e*n)<=1e-7*Math.sqrt((t*t+e*e)*(i*i+n*n))}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new c(e(this.x),e(this.y))}},{})),d=c.extend({initialize:function(t,e,i,n){this._x=t,this._y=e,this._owner=i,this._setter=n},set:function(t,e,i){return this._x=t,this._y=e,i||this._owner[this._setter](this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner[this._setter](this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner[this._setter](this)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){return"setPosition"===this._setter?4:0}}),f=r.extend({_class:"Size",_readIndex:!0,initialize:function(t,e){var i=typeof t;if("number"===i){var n="number"==typeof e;this.width=t,this.height=n?e:t,this.__read&&(this.__read=n?2:1)}else if("undefined"===i||null===t)this.width=this.height=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===i?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.width=r[0],this.height=r.length>1?r[1]:r[0]):"width"in r?(this.width=r.width,this.height=r.height):"x"in r?(this.width=r.x,this.height=r.y):(this.width=this.height=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.width=t,this.height=e,this},equals:function(t){return t===this||t&&(this.width===t.width&&this.height===t.height||Array.isArray(t)&&this.width===t[0]&&this.height===t[1])||!1},clone:function(){return new f(this.width,this.height)},toString:function(){var t=h.instance;return"{ width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.width),e.number(this.height)]},add:function(){var t=f.read(arguments);return new f(this.width+t.width,this.height+t.height)},subtract:function(){var t=f.read(arguments);return new f(this.width-t.width,this.height-t.height)},multiply:function(){var t=f.read(arguments);return new f(this.width*t.width,this.height*t.height)},divide:function(){var t=f.read(arguments);return new f(this.width/t.width,this.height/t.height)},modulo:function(){var t=f.read(arguments);return new f(this.width%t.width,this.height%t.height)},negate:function(){return new f((-this.width),(-this.height))},isZero:function(){return u.isZero(this.width)&&u.isZero(this.height)},isNaN:function(){return isNaN(this.width)||isNaN(this.height)},statics:{min:function(t,e){return new f(Math.min(t.width,e.width),Math.min(t.height,e.height))},max:function(t,e){return new f(Math.max(t.width,e.width),Math.max(t.height,e.height))},random:function(){return new f(Math.random(),Math.random())}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new f(e(this.width),e(this.height))}},{})),_=f.extend({initialize:function(t,e,i,n){this._width=t,this._height=e,this._owner=i,this._setter=n},set:function(t,e,i){return this._width=t,this._height=e,i||this._owner[this._setter](this),this},getWidth:function(){return this._width},setWidth:function(t){this._width=t,this._owner[this._setter](this)},getHeight:function(){return this._height},setHeight:function(t){this._height=t,this._owner[this._setter](this)}}),g=r.extend({_class:"Rectangle",_readIndex:!0,beans:!0,initialize:function(t,i,n,s){var a=typeof t,o=0;if("number"===a?(this.x=t,this.y=i,this.width=n,this.height=s,o=4):"undefined"===a||null===t?(this.x=this.y=this.width=this.height=0,o=null===t?1:0):1===arguments.length&&(Array.isArray(t)?(this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],o=1):t.x!==e||t.width!==e?(this.x=t.x||0,this.y=t.y||0,this.width=t.width||0,this.height=t.height||0,o=1):t.from===e&&t.to===e&&(this.x=this.y=this.width=this.height=0,this._set(t),o=1)),!o){var h=c.readNamed(arguments,"from"),u=r.peek(arguments);if(this.x=h.x,this.y=h.y,u&&u.x!==e||r.hasNamed(arguments,"to")){var l=c.readNamed(arguments,"to");this.width=l.x-h.x,this.height=l.y-h.y,this.width<0&&(this.x=l.x,this.width=-this.width),this.height<0&&(this.y=l.y,this.height=-this.height)}else{var d=f.read(arguments);this.width=d.width,this.height=d.height}o=arguments.__index}this.__read&&(this.__read=o)},set:function(t,e,i,n){return this.x=t,this.y=e,this.width=i,this.height=n,this},clone:function(){return new g(this.x,this.y,this.width,this.height)},equals:function(t){var e=r.isPlainValue(t)?g.read(arguments):t;return e===this||e&&this.x===e.x&&this.y===e.y&&this.width===e.width&&this.height===e.height||!1},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+", width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y),e.number(this.width),e.number(this.height)]},getPoint:function(t){var e=t?c:d;return new e(this.x,this.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.x=t.x,this.y=t.y},getSize:function(t){var e=t?f:_;return new e(this.width,this.height,this,"setSize")},setSize:function(){var t=f.read(arguments);this._fixX&&(this.x+=(this.width-t.width)*this._fixX),this._fixY&&(this.y+=(this.height-t.height)*this._fixY),this.width=t.width,this.height=t.height,this._fixW=1,this._fixH=1},getLeft:function(){return this.x},setLeft:function(t){this._fixW||(this.width-=t-this.x),this.x=t,this._fixX=0},getTop:function(){return this.y},setTop:function(t){this._fixH||(this.height-=t-this.y),this.y=t,this._fixY=0},getRight:function(){return this.x+this.width},setRight:function(t){this._fixX!==e&&1!==this._fixX&&(this._fixW=0),this._fixW?this.x=t-this.width:this.width=t-this.x,this._fixX=1},getBottom:function(){return this.y+this.height},setBottom:function(t){this._fixY!==e&&1!==this._fixY&&(this._fixH=0),this._fixH?this.y=t-this.height:this.height=t-this.y,this._fixY=1},getCenterX:function(){return this.x+.5*this.width},setCenterX:function(t){this.x=t-.5*this.width,this._fixX=.5},getCenterY:function(){return this.y+.5*this.height},setCenterY:function(t){this.y=t-.5*this.height,this._fixY=.5},getCenter:function(t){var e=t?c:d;return new e(this.getCenterX(),this.getCenterY(),this,"setCenter")},setCenter:function(){var t=c.read(arguments);return this.setCenterX(t.x),this.setCenterY(t.y),this},getArea:function(){return this.width*this.height},isEmpty:function(){return 0===this.width||0===this.height},contains:function(t){return t&&t.width!==e||4===(Array.isArray(t)?t:arguments).length?this._containsRectangle(g.read(arguments)):this._containsPoint(c.read(arguments))},_containsPoint:function(t){var e=t.x,i=t.y;return e>=this.x&&i>=this.y&&e<=this.x+this.width&&i<=this.y+this.height},_containsRectangle:function(t){var e=t.x,i=t.y;return e>=this.x&&i>=this.y&&e+t.width<=this.x+this.width&&i+t.height<=this.y+this.height},intersects:function(){var t=g.read(arguments);return t.x+t.width>this.x&&t.y+t.height>this.y&&t.x<this.x+this.width&&t.y<this.y+this.height},touches:function(){var t=g.read(arguments);return t.x+t.width>=this.x&&t.y+t.height>=this.y&&t.x<=this.x+this.width&&t.y<=this.y+this.height},intersect:function(){var t=g.read(arguments),e=Math.max(this.x,t.x),i=Math.max(this.y,t.y),n=Math.min(this.x+this.width,t.x+t.width),r=Math.min(this.y+this.height,t.y+t.height);return new g(e,i,n-e,r-i)},unite:function(){var t=g.read(arguments),e=Math.min(this.x,t.x),i=Math.min(this.y,t.y),n=Math.max(this.x+this.width,t.x+t.width),r=Math.max(this.y+this.height,t.y+t.height);return new g(e,i,n-e,r-i)},include:function(){var t=c.read(arguments),e=Math.min(this.x,t.x),i=Math.min(this.y,t.y),n=Math.max(this.x+this.width,t.x),r=Math.max(this.y+this.height,t.y);return new g(e,i,n-e,r-i)},expand:function(){var t=f.read(arguments),e=t.width,i=t.height;return new g(this.x-e/2,this.y-i/2,this.width+e,this.height+i)},scale:function(t,i){return this.expand(this.width*t-this.width,this.height*(i===e?t:i)-this.height)}},r.each([["Top","Left"],["Top","Right"],["Bottom","Left"],["Bottom","Right"],["Left","Center"],["Top","Center"],["Right","Center"],["Bottom","Center"]],function(t,e){var i=t.join(""),n=/^[RL]/.test(i);e>=4&&(t[1]+=n?"Y":"X");var r=t[n?0:1],s=t[n?1:0],a="get"+r,o="get"+s,h="set"+r,u="set"+s,l="get"+i,f="set"+i;this[l]=function(t){var e=t?c:d;return new e(this[a](),this[o](),this,f)},this[f]=function(){var t=c.read(arguments);this[h](t.x),this[u](t.y)}},{beans:!0})),v=g.extend({initialize:function(t,e,i,n,r,s){this.set(t,e,i,n,!0),this._owner=r,this._setter=s},set:function(t,e,i,n,r){return this._x=t,this._y=e,this._width=i,this._height=n,r||this._owner[this._setter](this),this}},new function(){var t=g.prototype;return r.each(["x","y","width","height"],function(t){var e=r.capitalize(t),i="_"+t;this["get"+e]=function(){return this[i]},this["set"+e]=function(t){this[i]=t,this._dontNotify||this._owner[this._setter](this)}},r.each(["Point","Size","Center","Left","Top","Right","Bottom","CenterX","CenterY","TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],function(e){var i="set"+e;this[i]=function(){this._dontNotify=!0,t[i].apply(this,arguments),this._dontNotify=!1,this._owner[this._setter](this)}},{isSelected:function(){return!!(2&this._owner._selection)},setSelected:function(t){var e=this._owner;e.changeSelection&&e.changeSelection(2,t)}}))}),p=r.extend({_class:"Matrix",initialize:function at(t){var e=arguments.length,i=!0;if(6===e?this.set.apply(this,arguments):1===e?t instanceof at?this.set(t._a,t._b,t._c,t._d,t._tx,t._ty):Array.isArray(t)?this.set.apply(this,t):i=!1:0===e?this.reset():i=!1,!i)throw new Error("Unsupported matrix parameters")},set:function(t,e,i,n,r,s,a){return this._a=t,this._b=e,this._c=i,this._d=n,this._tx=r,this._ty=s,a||this._changed(),this},_serialize:function(t,e){return r.serialize(this.getValues(),t,!0,e)},_changed:function(){var t=this._owner;t&&(t._applyMatrix?t.transform(null,!0):t._changed(9))},clone:function(){return new p(this._a,this._b,this._c,this._d,this._tx,this._ty)},equals:function(t){return t===this||t&&this._a===t._a&&this._b===t._b&&this._c===t._c&&this._d===t._d&&this._tx===t._tx&&this._ty===t._ty},toString:function(){var t=h.instance;return"[["+[t.number(this._a),t.number(this._c),t.number(this._tx)].join(", ")+"], ["+[t.number(this._b),t.number(this._d),t.number(this._ty)].join(", ")+"]]"},reset:function(t){return this._a=this._d=1,this._b=this._c=this._tx=this._ty=0,t||this._changed(),this},apply:function(t,e){var i=this._owner;return!!i&&(i.transform(null,!0,r.pick(t,!0),e),this.isIdentity())},translate:function(){var t=c.read(arguments),e=t.x,i=t.y;return this._tx+=e*this._a+i*this._c,
-this._ty+=e*this._b+i*this._d,this._changed(),this},scale:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});return e&&this.translate(e),this._a*=t.x,this._b*=t.x,this._c*=t.y,this._d*=t.y,e&&this.translate(e.negate()),this._changed(),this},rotate:function(t){t*=Math.PI/180;var e=c.read(arguments,1),i=e.x,n=e.y,r=Math.cos(t),s=Math.sin(t),a=i-i*r+n*s,o=n-i*s-n*r,h=this._a,u=this._b,l=this._c,d=this._d;return this._a=r*h+s*l,this._b=r*u+s*d,this._c=-s*h+r*l,this._d=-s*u+r*d,this._tx+=a*h+o*l,this._ty+=a*u+o*d,this._changed(),this},shear:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});e&&this.translate(e);var i=this._a,n=this._b;return this._a+=t.y*this._c,this._b+=t.y*this._d,this._c+=t.x*i,this._d+=t.x*n,e&&this.translate(e.negate()),this._changed(),this},skew:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0}),i=Math.PI/180,n=new c(Math.tan(t.x*i),Math.tan(t.y*i));return this.shear(n,e)},append:function(t){if(t){var e=this._a,i=this._b,n=this._c,r=this._d,s=t._a,a=t._c,o=t._b,h=t._d,u=t._tx,l=t._ty;this._a=s*e+o*n,this._c=a*e+h*n,this._b=s*i+o*r,this._d=a*i+h*r,this._tx+=u*e+l*n,this._ty+=u*i+l*r,this._changed()}return this},prepend:function(t){if(t){var e=this._a,i=this._b,n=this._c,r=this._d,s=this._tx,a=this._ty,o=t._a,h=t._c,u=t._b,l=t._d,c=t._tx,d=t._ty;this._a=o*e+h*i,this._c=o*n+h*r,this._b=u*e+l*i,this._d=u*n+l*r,this._tx=o*s+h*a+c,this._ty=u*s+l*a+d,this._changed()}return this},appended:function(t){return this.clone().append(t)},prepended:function(t){return this.clone().prepend(t)},invert:function(){var t=this._a,e=this._b,i=this._c,n=this._d,r=this._tx,s=this._ty,a=t*n-e*i,o=null;return a&&!isNaN(a)&&isFinite(r)&&isFinite(s)&&(this._a=n/a,this._b=-e/a,this._c=-i/a,this._d=t/a,this._tx=(i*s-n*r)/a,this._ty=(e*r-t*s)/a,o=this),o},inverted:function(){return this.clone().invert()},concatenate:"#append",preConcatenate:"#prepend",chain:"#appended",_shiftless:function(){return new p(this._a,this._b,this._c,this._d,0,0)},_orNullIfIdentity:function(){return this.isIdentity()?null:this},isIdentity:function(){return 1===this._a&&0===this._b&&0===this._c&&1===this._d&&0===this._tx&&0===this._ty},isInvertible:function(){var t=this._a*this._d-this._c*this._b;return t&&!isNaN(t)&&isFinite(this._tx)&&isFinite(this._ty)},isSingular:function(){return!this.isInvertible()},transform:function(t,e,i){return arguments.length<3?this._transformPoint(c.read(arguments)):this._transformCoordinates(t,e,i)},_transformPoint:function(t,e,i){var n=t.x,r=t.y;return e||(e=new c),e.set(n*this._a+r*this._c+this._tx,n*this._b+r*this._d+this._ty,i)},_transformCoordinates:function(t,e,i){for(var n=0,r=2*i;n<r;n+=2){var s=t[n],a=t[n+1];e[n]=s*this._a+a*this._c+this._tx,e[n+1]=s*this._b+a*this._d+this._ty}return e},_transformCorners:function(t){var e=t.x,i=t.y,n=e+t.width,r=i+t.height,s=[e,i,n,i,n,r,e,r];return this._transformCoordinates(s,s,4)},_transformBounds:function(t,e,i){for(var n=this._transformCorners(t),r=n.slice(0,2),s=r.slice(),a=2;a<8;a++){var o=n[a],h=1&a;o<r[h]?r[h]=o:o>s[h]&&(s[h]=o)}return e||(e=new g),e.set(r[0],r[1],s[0]-r[0],s[1]-r[1],i)},inverseTransform:function(){return this._inverseTransform(c.read(arguments))},_inverseTransform:function(t,e,i){var n=this._a,r=this._b,s=this._c,a=this._d,o=this._tx,h=this._ty,u=n*a-r*s,l=null;if(u&&!isNaN(u)&&isFinite(o)&&isFinite(h)){var d=t.x-this._tx,f=t.y-this._ty;e||(e=new c),l=e.set((d*a-f*s)/u,(f*n-d*r)/u,i)}return l},decompose:function(){var t,e,i,n=this._a,r=this._b,s=this._c,a=this._d,o=n*a-r*s,h=Math.sqrt,u=Math.atan2,l=180/Math.PI;if(0!==n||0!==r){var d=h(n*n+r*r);t=Math.acos(n/d)*(r>0?1:-1),e=[d,o/d],i=[u(n*s+r*a,d*d),0]}else if(0!==s||0!==a){var f=h(s*s+a*a);t=Math.asin(s/f)*(a>0?1:-1),e=[o/f,f],i=[0,u(n*s+r*a,f*f)]}else t=0,i=e=[0,0];return{translation:this.getTranslation(),rotation:t*l,scaling:new c(e),skewing:new c(i[0]*l,i[1]*l)}},getValues:function(){return[this._a,this._b,this._c,this._d,this._tx,this._ty]},getTranslation:function(){return new c(this._tx,this._ty)},getScaling:function(){return(this.decompose()||{}).scaling},getRotation:function(){return(this.decompose()||{}).rotation},applyToContext:function(t){this.isIdentity()||t.transform(this._a,this._b,this._c,this._d,this._tx,this._ty)}},r.each(["a","b","c","d","tx","ty"],function(t){var e=r.capitalize(t),i="_"+t;this["get"+e]=function(){return this[i]},this["set"+e]=function(t){this[i]=t,this._changed()}},{})),m=r.extend({_class:"Line",initialize:function(t,e,i,n,r){var s=!1;arguments.length>=4?(this._px=t,this._py=e,this._vx=i,this._vy=n,s=r):(this._px=t.x,this._py=t.y,this._vx=e.x,this._vy=e.y,s=i),s||(this._vx-=this._px,this._vy-=this._py)},getPoint:function(){return new c(this._px,this._py)},getVector:function(){return new c(this._vx,this._vy)},getLength:function(){return this.getVector().getLength()},intersect:function(t,e){return m.intersect(this._px,this._py,this._vx,this._vy,t._px,t._py,t._vx,t._vy,!0,e)},getSide:function(t,e){return m.getSide(this._px,this._py,this._vx,this._vy,t.x,t.y,!0,e)},getDistance:function(t){return Math.abs(m.getSignedDistance(this._px,this._py,this._vx,this._vy,t.x,t.y,!0))},isCollinear:function(t){return c.isCollinear(this._vx,this._vy,t._vx,t._vy)},isOrthogonal:function(t){return c.isOrthogonal(this._vx,this._vy,t._vx,t._vy)},statics:{intersect:function(t,e,i,n,r,s,a,o,h,l){h||(i-=t,n-=e,a-=r,o-=s);var d=i*o-n*a;if(!u.isZero(d)){var f=t-r,_=e-s,g=(a*_-o*f)/d,v=(i*_-n*f)/d,p=1e-12,m=-p,y=1+p;if(l||m<g&&g<y&&m<v&&v<y)return l||(g=g<=0?0:g>=1?1:g),new c(t+g*i,e+g*n)}},getSide:function(t,e,i,n,r,s,a,o){a||(i-=t,n-=e);var h=r-t,u=s-e,l=h*n-u*i;return 0!==l||o||(l=(h*i+h*i)/(i*i+n*n),l>=0&&l<=1&&(l=0)),l<0?-1:l>0?1:0},getSignedDistance:function(t,e,i,n,r,s,a){return a||(i-=t,n-=e),0===i?n>0?r-t:t-r:0===n?i<0?s-e:e-s:((r-t)*n-(s-e)*i)/Math.sqrt(i*i+n*n)}}}),y=o.extend({_class:"Project",_list:"projects",_reference:"project",_compactSerialize:!0,initialize:function(t){o.call(this,!0),this._children=[],this._namedChildren={},this._activeLayer=null,this._currentStyle=new V(null,null,this),this._view=U.create(this,t||Q.getCanvas(1,1)),this._selectionItems={},this._selectionCount=0,this._updateVersion=0},_serialize:function(t,e){return r.serialize(this._children,t,!0,e)},_changed:function(t,e){if(1&t){var i=this._view;i&&(i._needsUpdate=!0,!i._requested&&i._autoUpdate&&i.requestUpdate())}var n=this._changes;if(n&&e){var r=this._changesById,s=e._id,a=r[s];a?a.flags|=t:n.push(r[s]={item:e,flags:t})}},clear:function(){for(var t=this._children,e=t.length-1;e>=0;e--)t[e].remove()},isEmpty:function(){return 0===this._children.length},remove:function ot(){return!!ot.base.call(this)&&(this._view&&this._view.remove(),!0)},getView:function(){return this._view},getCurrentStyle:function(){return this._currentStyle},setCurrentStyle:function(t){this._currentStyle.initialize(t)},getIndex:function(){return this._index},getOptions:function(){return this._scope.settings},getLayers:function(){return this._children},getActiveLayer:function(){return this._activeLayer||new b({project:this,insert:!0})},getSymbolDefinitions:function(){var t=[],e={};return this.getItems({"class":P,match:function(i){var n=i._definition,r=n._id;return e[r]||(e[r]=!0,t.push(n)),!1}}),t},getSymbols:"getSymbolDefinitions",getSelectedItems:function(){var t=this._selectionItems,e=[];for(var i in t){var n=t[i],r=n._selection;1&r&&n.isInserted()?e.push(n):r||this._updateSelection(n)}return e},_updateSelection:function(t){var e=t._id,i=this._selectionItems;t._selection?i[e]!==t&&(this._selectionCount++,i[e]=t):i[e]===t&&(this._selectionCount--,delete i[e])},selectAll:function(){for(var t=this._children,e=0,i=t.length;e<i;e++)t[e].setFullySelected(!0)},deselectAll:function(){var t=this._selectionItems;for(var e in t)t[e].setFullySelected(!1)},addLayer:function(t){return this.insertLayer(e,t)},insertLayer:function(t,e){if(e instanceof b){e._remove(!1,!0),r.splice(this._children,[e],t,0),e._setProject(this,!0);var i=e._name;i&&e.setName(i),this._changes&&e._changed(5),this._activeLayer||(this._activeLayer=e)}else e=null;return e},_insertItem:function(t,i,n,r){return i=this.insertLayer(t,i)||(this._activeLayer||this._insertItem(e,new b(w.NO_INSERT),!0,!0)).insertChild(t,i,n),r&&i.activate&&i.activate(),i},getItems:function(t){return w._getItems(this,t)},getItem:function(t){return w._getItems(this,t,null,null,!0)[0]||null},importJSON:function(t){this.activate();var e=this._activeLayer;return r.importJSON(t,e&&e.isEmpty()&&e)},removeOn:function(t){var e=this._removeSets;if(e){"mouseup"===t&&(e.mousedrag=null);var i=e[t];if(i){for(var n in i){var r=i[n];for(var s in e){var a=e[s];a&&a!=i&&delete a[r._id]}r.remove()}e[t]=null}}},draw:function(t,e,i){this._updateVersion++,t.save(),e.applyToContext(t);for(var n=this._children,s=new r({offset:new c(0,0),pixelRatio:i,viewMatrix:e.isIdentity()?null:e,matrices:[new p],updateMatrix:!0}),a=0,o=n.length;a<o;a++)n[a].draw(t,s);if(t.restore(),this._selectionCount>0){t.save(),t.strokeWidth=1;var h=this._selectionItems,u=this._scope.settings.handleSize,l=this._updateVersion;for(var d in h)h[d]._drawSelection(t,e,u,h,l);t.restore()}}}),w=r.extend(s,{statics:{extend:function ht(t){return t._serializeFields&&(t._serializeFields=r.set({},this.prototype._serializeFields,t._serializeFields)),ht.base.apply(this,arguments)},NO_INSERT:{insert:!1}},_class:"Item",_name:null,_applyMatrix:!0,_canApplyMatrix:!0,_canScaleStroke:!1,_pivot:null,_visible:!0,_blendMode:"normal",_opacity:1,_locked:!1,_guide:!1,_clipMask:!1,_selection:0,_selectBounds:!0,_selectChildren:!1,_serializeFields:{name:null,applyMatrix:null,matrix:new p,pivot:null,visible:!0,blendMode:"normal",opacity:1,locked:!1,guide:!1,clipMask:!1,selected:!1,data:{}}},new function(){var t=["onMouseDown","onMouseUp","onMouseDrag","onClick","onDoubleClick","onMouseMove","onMouseEnter","onMouseLeave"];return r.each(t,function(t){this._events[t]={install:function(t){this.getView()._countItemEvent(t,1)},uninstall:function(t){this.getView()._countItemEvent(t,-1)}}},{_events:{onFrame:{install:function(){this.getView()._animateItem(this,!0)},uninstall:function(){this.getView()._animateItem(this,!1)}},onLoad:{},onError:{}},statics:{_itemHandlers:t}})},{initialize:function(){},_initialize:function(t,i){var n=t&&r.isPlainObject(t),s=n&&t.internal===!0,a=this._matrix=new p,o=n&&t.project||paper.project,h=paper.settings;return this._id=s?null:l.get(),this._parent=this._index=null,this._applyMatrix=this._canApplyMatrix&&h.applyMatrix,i&&a.translate(i),a._owner=this,this._style=new V(o._currentStyle,this,o),s||n&&t.insert===!1||!h.insertItems&&(!n||t.insert!==!0)?this._setProject(o):(n&&t.parent||o)._insertItem(e,this,!0,!0),n&&t!==w.NO_INSERT&&r.filter(this,t,{internal:!0,insert:!0,project:!0,parent:!0}),n},_serialize:function(t,e){function i(i){for(var a in i){var o=s[a];r.equals(o,"leading"===a?1.2*i.fontSize:i[a])||(n[a]=r.serialize(o,t,"data"!==a,e))}}var n={},s=this;return i(this._serializeFields),this instanceof x||i(this._style._defaults),[this._class,n]},_changed:function(t){var i=this._symbol,n=this._parent||i,r=this._project;8&t&&(this._bounds=this._position=this._decomposed=this._globalMatrix=e),n&&40&t&&w._clearBoundsCache(n),2&t&&w._clearBoundsCache(this),r&&r._changed(t,this),i&&i._changed(t)},set:function(t){return t&&this._set(t),this},getId:function(){return this._id},getName:function(){return this._name},setName:function(t){if(this._name&&this._removeNamed(),t===+t+"")throw new Error("Names consisting only of numbers are not supported.");var i=this._getOwner();if(t&&i){var n=i._children,r=i._namedChildren;(r[t]=r[t]||[]).push(this),t in n||(n[t]=this)}this._name=t||e,this._changed(128)},getStyle:function(){return this._style},setStyle:function(t){this.getStyle().set(t)}},r.each(["locked","visible","blendMode","opacity","guide"],function(t){var e=r.capitalize(t),t="_"+t;this["get"+e]=function(){return this[t]},this["set"+e]=function(e){e!=this[t]&&(this[t]=e,this._changed("_locked"===t?128:129))}},{}),{beans:!0,getSelection:function(){return this._selection},setSelection:function(t){if(t!==this._selection){this._selection=t;var e=this._project;e&&(e._updateSelection(this),this._changed(129))}},changeSelection:function(t,e){var i=this._selection;this.setSelection(e?i|t:i&~t)},isSelected:function(){if(this._selectChildren)for(var t=this._children,e=0,i=t.length;e<i;e++)if(t[e].isSelected())return!0;return!!(1&this._selection)},setSelected:function(t){if(this._selectChildren)for(var e=this._children,i=0,n=e.length;i<n;i++)e[i].setSelected(t);this.changeSelection(1,t)},isFullySelected:function(){var t=this._children,e=!!(1&this._selection);if(t&&e){for(var i=0,n=t.length;i<n;i++)if(!t[i].isFullySelected())return!1;return!0}return e},setFullySelected:function(t){var e=this._children;if(e)for(var i=0,n=e.length;i<n;i++)e[i].setFullySelected(t);this.changeSelection(1,t)},isClipMask:function(){return this._clipMask},setClipMask:function(t){this._clipMask!=(t=!!t)&&(this._clipMask=t,t&&(this.setFillColor(null),this.setStrokeColor(null)),this._changed(129),this._parent&&this._parent._changed(1024))},getData:function(){return this._data||(this._data={}),this._data},setData:function(t){this._data=t},getPosition:function(t){var e=this._position,i=t?c:d;if(!e){var n=this._pivot;e=this._position=n?this._matrix._transformPoint(n):this.getBounds().getCenter(!0)}return new i(e.x,e.y,this,"setPosition")},setPosition:function(){this.translate(c.read(arguments).subtract(this.getPosition(!0)))},getPivot:function(t){var e=this._pivot;if(e){var i=t?c:d;e=new i(e.x,e.y,this,"setPivot")}return e},setPivot:function(){this._pivot=c.read(arguments,0,{clone:!0,readNull:!0}),this._position=e}},r.each({getStrokeBounds:{stroke:!0},getHandleBounds:{handle:!0},getInternalBounds:{internal:!0}},function(t,e){this[e]=function(e){return this.getBounds(e,t)}},{beans:!0,getBounds:function(t,e){var i=e||t instanceof p,n=r.set({},i?e:t,this._boundsOptions);n.stroke&&!this.getStrokeScaling()||(n.cacheItem=this);var s=this._getCachedBounds(i&&t,n);return 0===arguments.length?new v(s.x,s.y,s.width,s.height,this,"setBounds"):s},setBounds:function(){var t=g.read(arguments),e=this.getBounds(),i=this._matrix,n=new p,r=t.getCenter();n.translate(r),t.width==e.width&&t.height==e.height||(i.isInvertible()||(i.initialize(i._backup||(new p).translate(i.getTranslation())),e=this.getBounds()),n.scale(0!==e.width?t.width/e.width:0,0!==e.height?t.height/e.height:0)),r=e.getCenter(),n.translate(-r.x,-r.y),this.transform(n)},_getBounds:function(t,e){var i=this._children;return i&&0!==i.length?(w._updateBoundsCache(this,e.cacheItem),w._getBounds(i,t,e)):new g},_getCachedBounds:function(t,e){t=t&&t._orNullIfIdentity();var i=e.internal,n=e.cacheItem,r=i?null:this._matrix._orNullIfIdentity(),s=n&&(!t||t.equals(r))&&[e.stroke?1:0,e.handle?1:0,i?1:0].join("");if(w._updateBoundsCache(this._parent||this._symbol,n),s&&this._bounds&&s in this._bounds)return this._bounds[s].rect.clone();var a=this._getBounds(t||r,e);if(s){this._bounds||(this._bounds={});this._bounds[s]={rect:a.clone(),internal:e.internal}}return a},_getStrokeMatrix:function(t,e){var i=this.getStrokeScaling()?null:e&&e.internal?this:this._parent||this._symbol&&this._symbol._item,n=i?i.getViewMatrix().invert():t;return n&&n._shiftless()},statics:{_updateBoundsCache:function(t,e){if(t&&e){var i=e._id,n=t._boundsCache=t._boundsCache||{ids:{},list:[]};n.ids[i]||(n.list.push(e),n.ids[i]=e)}},_clearBoundsCache:function(t){var i=t._boundsCache;if(i){t._bounds=t._position=t._boundsCache=e;for(var n=0,r=i.list,s=r.length;n<s;n++){var a=r[n];a!==t&&(a._bounds=a._position=e,a._boundsCache&&w._clearBoundsCache(a))}}},_getBounds:function(t,e,i){var n=1/0,r=-n,s=n,a=r;i=i||{};for(var o=0,h=t.length;o<h;o++){var u=t[o];if(u._visible&&!u.isEmpty()){var l=u._getCachedBounds(e&&e.appended(u._matrix),i);n=Math.min(l.x,n),s=Math.min(l.y,s),r=Math.max(l.x+l.width,r),a=Math.max(l.y+l.height,a)}}return isFinite(n)?new g(n,s,r-n,a-s):new g}}}),{beans:!0,_decompose:function(){return this._decomposed||(this._decomposed=this._matrix.decompose())},getRotation:function(){var t=this._decompose();return t&&t.rotation},setRotation:function(t){var e=this.getRotation();null!=e&&null!=t&&this.rotate(t-e)},getScaling:function(t){var e=this._decompose(),i=e&&e.scaling,n=t?c:d;return i&&new n(i.x,i.y,this,"setScaling")},setScaling:function(){var t=this.getScaling(),e=c.read(arguments,0,{clone:!0,readNull:!0});t&&e&&this.scale(e.x/t.x,e.y/t.y)},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},getGlobalMatrix:function(t){var e=this._globalMatrix,i=this._project._updateVersion;if(e&&e._updateVersion!==i&&(e=null),!e){e=this._globalMatrix=this._matrix.clone();var n=this._parent;n&&e.prepend(n.getGlobalMatrix(!0)),e._updateVersion=i}return t?e:e.clone()},getViewMatrix:function(){return this.getGlobalMatrix().prepend(this.getView()._matrix)},getApplyMatrix:function(){return this._applyMatrix},setApplyMatrix:function(t){(this._applyMatrix=this._canApplyMatrix&&!!t)&&this.transform(null,!0)},getTransformContent:"#getApplyMatrix",setTransformContent:"#setApplyMatrix"},{getProject:function(){return this._project},_setProject:function(t,e){if(this._project!==t){this._project&&this._installEvents(!1),this._project=t;for(var i=this._children,n=0,r=i&&i.length;n<r;n++)i[n]._setProject(t);e=!0}e&&this._installEvents(!0)},getView:function(){return this._project._view},_installEvents:function ut(t){ut.base.call(this,t);for(var e=this._children,i=0,n=e&&e.length;i<n;i++)e[i]._installEvents(t)},getLayer:function(){for(var t=this;t=t._parent;)if(t instanceof b)return t;return null},getParent:function(){return this._parent},setParent:function(t){return t.addChild(this)},_getOwner:"#getParent",getChildren:function(){return this._children},setChildren:function(t,e){this.removeChildren(),this.addChildren(t,e)},getFirstChild:function(){return this._children&&this._children[0]||null},getLastChild:function(){return this._children&&this._children[this._children.length-1]||null},getNextSibling:function(){var t=this._getOwner();return t&&t._children[this._index+1]||null},getPreviousSibling:function(){var t=this._getOwner();return t&&t._children[this._index-1]||null},getIndex:function(){return this._index},equals:function(t){return t===this||t&&this._class===t._class&&this._style.equals(t._style)&&this._matrix.equals(t._matrix)&&this._locked===t._locked&&this._visible===t._visible&&this._blendMode===t._blendMode&&this._opacity===t._opacity&&this._clipMask===t._clipMask&&this._guide===t._guide&&this._equals(t)||!1},_equals:function(t){return r.equals(this._children,t._children)},clone:function(t){var i=new this.constructor(w.NO_INSERT),n=this._children,s=r.pick(t?t.insert:e,t===e||t===!0),a=r.pick(t?t.deep:e,!0);n&&i.copyAttributes(this),n&&!a||i.copyContent(this),n||i.copyAttributes(this),s&&i.insertAbove(this);var o=this._name,h=this._parent;if(o&&h){for(var n=h._children,u=o,l=1;n[o];)o=u+" "+l++;o!==u&&i.setName(o)}return i},copyContent:function(t){for(var e=t._children,i=0,n=e&&e.length;i<n;i++)this.addChild(e[i].clone(!1),!0)},copyAttributes:function(t,e){this.setStyle(t._style);for(var i=["_locked","_visible","_blendMode","_opacity","_clipMask","_guide"],n=0,s=i.length;n<s;n++){var a=i[n];t.hasOwnProperty(a)&&(this[a]=t[a])}e||this._matrix.initialize(t._matrix),this.setApplyMatrix(t._applyMatrix),this.setPivot(t._pivot),this.setSelection(t._selection);var o=t._data,h=t._name;this._data=o?r.clone(o):null,h&&this.setName(h)},rasterize:function(t,i){var n=this.getStrokeBounds(),s=(t||this.getView().getResolution())/72,a=n.getTopLeft().floor(),o=n.getBottomRight().ceil(),h=new f(o.subtract(a)),u=new S(w.NO_INSERT);if(!h.isZero()){var l=Q.getCanvas(h.multiply(s)),c=l.getContext("2d"),d=(new p).scale(s).translate(a.negate());c.save(),d.applyToContext(c),this.draw(c,new r({matrices:[d]})),c.restore(),u.setCanvas(l)}return u.transform((new p).translate(a.add(h.divide(2))).scale(1/s)),(i===e||i)&&u.insertAbove(this),u},contains:function(){return!!this._contains(this._matrix._inverseTransform(c.read(arguments)))},_contains:function(t){var e=this._children;if(e){for(var i=e.length-1;i>=0;i--)if(e[i].contains(t))return!0;return!1}return t.isInside(this.getInternalBounds())},isInside:function(){return g.read(arguments).contains(this.getBounds())},_asPathItem:function(){return new L.Rectangle({rectangle:this.getInternalBounds(),matrix:this._matrix,insert:!1})},intersects:function(t,e){return t instanceof w&&this._asPathItem().getIntersections(t._asPathItem(),null,e,!0).length>0}},new function(){function t(){return this._hitTest(c.read(arguments),M.getOptions(arguments))}function e(){var t=c.read(arguments),e=M.getOptions(arguments),i=e.match,n=[];return e=r.set({},e,{match:function(t){i&&!i(t)||n.push(t)}}),this._hitTest(t,e),n}function i(t,e,i,n){var r=this._children;if(r)for(var s=r.length-1;s>=0;s--){var a=r[s],o=a!==n&&a._hitTest(t,e,i);if(o)return o}return null}return y.inject({hitTest:t,hitTestAll:e,_hitTest:i}),{hitTest:t,hitTestAll:e,_hitTestChildren:i}},{_hitTest:function(t,e,i){function n(t){return!g||t&&g(t)?t:null}function s(e,i){var n=c["get"+i]();if(t.subtract(n).divide(l).length<=1)return new M(e,v,{name:r.hyphenate(i),point:n})}if(this._locked||!this._visible||this._guide&&!e.guides||this.isEmpty())return null;var a=this._matrix,o=i?i.appended(a):this.getGlobalMatrix().prepend(this.getView()._matrix),h=this.getStrokeScaling()?null:o.inverted()._shiftless(),u=Math.max(e.tolerance,1e-6),l=e._tolerancePadding=new f(L._getStrokePadding(u,h));if(t=a._inverseTransform(t),!t||!this._children&&!this.getBounds({internal:!0,stroke:!0,handle:!0}).expand(l.multiply(2))._containsPoint(t))return null;var c,d,_=!(e.guides&&!this._guide||e.selected&&!this.isSelected()||e.type&&e.type!==r.hyphenate(this._class)||e["class"]&&!(this instanceof e["class"])),g=e.match,v=this;if(_&&(e.center||e.bounds)&&this._parent){if(c=this.getInternalBounds(),e.center&&(d=s("center","Center")),!d&&e.bounds)for(var p=["TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],m=0;m<8&&!d;m++)d=s("bounds",p[m]);d=n(d)}return d||(d=this._hitTestChildren(t,e,o)||_&&n(this._hitTestSelf(t,e,o,h))||null),d&&d.point&&(d.point=a.transform(d.point)),d},_hitTestSelf:function(t,e){if(e.fill&&this.hasFill()&&this._contains(t))return new M("fill",this)},matches:function(t,e){function i(t,e){for(var n in t)if(t.hasOwnProperty(n)){var s=t[n],a=e[n];if(r.isPlainObject(s)&&r.isPlainObject(a)){if(!i(s,a))return!1}else if(!r.equals(s,a))return!1}return!0}var n=typeof t;if("object"===n){for(var s in t)if(t.hasOwnProperty(s)&&!this.matches(s,t[s]))return!1;return!0}if("function"===n)return t(this);if("match"===t)return e(this);var a=/^(empty|editable)$/.test(t)?this["is"+r.capitalize(t)]():"type"===t?r.hyphenate(this._class):this[t];if("class"===t){if("function"==typeof e)return this instanceof e;a=this._class}if("function"==typeof e)return!!e(a);if(e){if(e.test)return e.test(a);if(r.isPlainObject(e))return i(e,a)}return r.equals(a,e)},getItems:function(t){return w._getItems(this,t,this._matrix)},getItem:function(t){return w._getItems(this,t,this._matrix,null,!0)[0]||null},statics:{_getItems:function lt(t,e,i,n,s){if(!n){var a="object"==typeof e&&e,o=a&&a.overlapping,h=a&&a.inside,u=o||h,l=u&&g.read([u]);n={items:[],recursive:a&&a.recursive!==!1,inside:!!h,overlapping:!!o,rect:l,path:o&&new L.Rectangle({rectangle:l,insert:!1})},a&&(e=r.filter({},e,{recursive:!0,inside:!0,overlapping:!0}))}var c=t._children,d=n.items,l=n.rect;i=l&&(i||new p);for(var f=0,_=c&&c.length;f<_;f++){var v=c[f],m=i&&i.appended(v._matrix),y=!0;if(l){var u=v.getBounds(m);if(!l.intersects(u))continue;l.contains(u)||n.overlapping&&(u.contains(l)||n.path.intersects(v,m))||(y=!1)}if(y&&v.matches(e)&&(d.push(v),s))break;if(n.recursive!==!1&&lt(v,e,m,n,s),s&&d.length>0)break}return d}}},{importJSON:function(t){var e=r.importJSON(t,this);return e!==this?this.addChild(e):e},addChild:function(t,i){return this.insertChild(e,t,i)},insertChild:function(t,e,i){var n=e?this.insertChildren(t,[e],i):null;return n&&n[0]},addChildren:function(t,e){return this.insertChildren(this._children.length,t,e)},insertChildren:function(t,e,i,n){var s=this._children;if(s&&e&&e.length>0){e=Array.prototype.slice.apply(e);for(var a=e.length-1;a>=0;a--){var o=e[a];o&&(!n||o instanceof n)?o._remove(!1,!0):e.splice(a,1)}r.splice(s,e,t,0);for(var h=this._project,u=h._changes,a=0,l=e.length;a<l;a++){var o=e[a],c=o._name;o._parent=this,o._setProject(h,!0),c&&o.setName(c),u&&this._changed(5)}this._changed(11)}else e=null;return e},_insertItem:"#insertChild",_insertAt:function(t,e,i){var n=this;if(n!==t){var r=t&&t._getOwner();r?(n._remove(!1,!0),r._insertItem(t._index+e,n,i)):n=null}return n},insertAbove:function(t,e){return this._insertAt(t,1,e)},insertBelow:function(t,e){return this._insertAt(t,0,e)},sendToBack:function(){var t=this._getOwner();return t?t._insertItem(0,this):null},bringToFront:function(){var t=this._getOwner();return t?t._insertItem(e,this):null},appendTop:"#addChild",appendBottom:function(t){return this.insertChild(0,t)},moveAbove:"#insertAbove",moveBelow:"#insertBelow",copyTo:function(t){return t._insertItem(e,this.clone(!1))},reduce:function(t){var e=this._children;if(e&&1===e.length){var i=e[0].reduce(t);return this._parent?(i.insertAbove(this),this.remove()):i.remove(),i}return this},_removeNamed:function(){var t=this._getOwner();if(t){var e=t._children,i=t._namedChildren,n=this._name,r=i[n],s=r?r.indexOf(this):-1;s!==-1&&(e[n]==this&&delete e[n],r.splice(s,1),r.length?e[n]=r[0]:delete i[n])}},_remove:function(t,e){var i=this._getOwner(),n=this._project,s=this._index;return!!i&&(null!=s&&(n._activeLayer===this&&(n._activeLayer=this.getNextSibling()||this.getPreviousSibling()),r.splice(i._children,null,s,1)),this._name&&this._removeNamed(),this._installEvents(!1),t&&n._changes&&this._changed(5),e&&i._changed(11,this),this._parent=null,!0)},remove:function(){return this._remove(!0,!0)},replaceWith:function(t){var e=t&&t.insertBelow(this);return e&&this.remove(),e},removeChildren:function(t,e){if(!this._children)return null;t=t||0,e=r.pick(e,this._children.length);for(var i=r.splice(this._children,null,t,e-t),n=i.length-1;n>=0;n--)i[n]._remove(!0,!1);return i.length>0&&this._changed(11),i},clear:"#removeChildren",reverseChildren:function(){if(this._children){this._children.reverse();for(var t=0,e=this._children.length;t<e;t++)this._children[t]._index=t;this._changed(11)}},isEmpty:function(){return!this._children||0===this._children.length},isEditable:function(){for(var t=this;t;){if(!t._visible||t._locked)return!1;t=t._parent}return!0},hasFill:function(){return this.getStyle().hasFill()},hasStroke:function(){return this.getStyle().hasStroke()},hasShadow:function(){return this.getStyle().hasShadow()},_getOrder:function(t){function e(t){var e=[];do e.unshift(t);while(t=t._parent);return e}for(var i=e(this),n=e(t),r=0,s=Math.min(i.length,n.length);r<s;r++)if(i[r]!=n[r])return i[r]._index<n[r]._index?1:-1;return 0},hasChildren:function(){return this._children&&this._children.length>0},isInserted:function(){return!!this._parent&&this._parent.isInserted()},isAbove:function(t){return this._getOrder(t)===-1},isBelow:function(t){return 1===this._getOrder(t)},isParent:function(t){return this._parent===t},isChild:function(t){return t&&t._parent===this},isDescendant:function(t){for(var e=this;e=e._parent;)if(e===t)return!0;return!1},isAncestor:function(t){return!!t&&t.isDescendant(this)},isSibling:function(t){return this._parent===t._parent},isGroupedWith:function(t){for(var e=this._parent;e;){if(e._parent&&/^(Group|Layer|CompoundPath)$/.test(e._class)&&t.isDescendant(e))return!0;e=e._parent}return!1}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var i=(e?r:c).read(arguments),n=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](i,n||this.getPosition(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t,e,i,n){t&&t.isIdentity()&&(t=null);var r=this._matrix,s=(e||this._applyMatrix)&&(!r.isIdentity()||t||e&&i&&this._children);if(!t&&!s)return this;if(t&&(!t.isInvertible()&&r.isInvertible()&&(r._backup=r.getValues()),r.prepend(t)),s=s&&this._transformContent(r,i,n)){var a=this._pivot,o=this._style,h=o.getFillColor(!0),u=o.getStrokeColor(!0);a&&r._transformPoint(a,a,!0),h&&h.transform(r),u&&u.transform(r),r.reset(!0),n&&this._canApplyMatrix&&(this._applyMatrix=!0)}var l=this._bounds,c=this._position;this._changed(9);var d=l&&t&&t.decompose();if(d&&!d.shearing&&d.rotation%90===0){for(var f in l){var _=l[f];if(s||!_.internal){var g=_.rect;t._transformBounds(g,g)}}var v=this._boundsGetter,g=l[v&&v.getBounds||v||"getBounds"];g&&(this._position=g.getCenter(!0)),this._bounds=l}else t&&c&&(this._position=t._transformPoint(c,c));return this},_transformContent:function(t,e,i){var n=this._children;if(n){for(var r=0,s=n.length;r<s;r++)n[r].transform(t,!0,e,i);return!0}},globalToLocal:function(){return this.getGlobalMatrix(!0)._inverseTransform(c.read(arguments))},localToGlobal:function(){return this.getGlobalMatrix(!0)._transformPoint(c.read(arguments))},parentToLocal:function(){return this._matrix._inverseTransform(c.read(arguments))},localToParent:function(){return this._matrix._transformPoint(c.read(arguments))},fitBounds:function(t,e){t=g.read(arguments);var i=this.getBounds(),n=i.height/i.width,r=t.height/t.width,s=(e?n>r:n<r)?t.width/i.width:t.height/i.height,a=new g(new c,new f(i.width*s,i.height*s));a.setCenter(t.getCenter()),this.setBounds(a)}}),{_setStyles:function(t,e,i){var n=this._style;if(n.hasFill()&&(t.fillStyle=n.getFillColor().toCanvasStyle(t)),n.hasStroke()){t.strokeStyle=n.getStrokeColor().toCanvasStyle(t),t.lineWidth=n.getStrokeWidth();var r=n.getStrokeJoin(),s=n.getStrokeCap(),a=n.getMiterLimit();if(r&&(t.lineJoin=r),s&&(t.lineCap=s),a&&(t.miterLimit=a),paper.support.nativeDash){var o=n.getDashArray(),h=n.getDashOffset();o&&o.length&&("setLineDash"in t?(t.setLineDash(o),t.lineDashOffset=h):(t.mozDash=o,t.mozDashOffset=h))}}if(n.hasShadow()){var u=e.pixelRatio||1,l=i._shiftless().prepend((new p).scale(u,u)),d=l.transform(new c(n.getShadowBlur(),0)),f=l.transform(this.getShadowOffset());t.shadowColor=n.getShadowColor().toCanvasStyle(t),t.shadowBlur=d.getLength(),t.shadowOffsetX=f.x,t.shadowOffsetY=f.y}},draw:function(t,e,i){var n=this._updateVersion=this._project._updateVersion;if(this._visible&&0!==this._opacity){var r=e.matrices,s=e.viewMatrix,a=this._matrix,o=r[r.length-1].appended(a);if(o.isInvertible()){s=s?s.appended(o):o,r.push(o),e.updateMatrix&&(o._updateVersion=n,this._globalMatrix=o);var h,u,l,c=this._blendMode,d=this._opacity,f="normal"===c,_=tt.nativeModes[c],g=f&&1===d||e.dontStart||e.clip||(_||f&&d<1)&&this._canComposite(),v=e.pixelRatio||1;if(!g){var p=this.getStrokeBounds(s);if(!p.width||!p.height)return;l=e.offset,u=e.offset=p.getTopLeft().floor(),h=t,t=Q.getContext(p.getSize().ceil().add(1).multiply(v)),1!==v&&t.scale(v,v)}t.save();var m=i?i.appended(a):this._canScaleStroke&&!this.getStrokeScaling(!0)&&s,y=!g&&e.clipItem,w=!m||y;if(g?(t.globalAlpha=d,_&&(t.globalCompositeOperation=c)):w&&t.translate(-u.x,-u.y),w&&(g?a:s).applyToContext(t),y&&e.clipItem.draw(t,e.extend({clip:!0})),m){t.setTransform(v,0,0,v,0,0);var x=e.offset;x&&t.translate(-x.x,-x.y)}this._draw(t,e,s,m),t.restore(),r.pop(),e.clip&&!e.dontFinish&&t.clip(),g||(tt.process(c,t,h,d,u.subtract(l).multiply(v)),Q.release(t),e.offset=l)}}},_isUpdated:function(t){var e=this._parent;if(e instanceof N)return e._isUpdated(t);var i=this._updateVersion===t;return!i&&e&&e._visible&&e._isUpdated(t)&&(this._updateVersion=t,i=!0),i},_drawSelection:function(t,e,i,n,r){var s=this._selection,a=1&s,o=2&s||a&&this._selectBounds,h=4&s;if(this._drawSelected||(a=!1),
-(a||o||h)&&this._isUpdated(r)){var u,l=this.getSelectedColor(!0)||(u=this.getLayer())&&u.getSelectedColor(!0),c=e.appended(this.getGlobalMatrix(!0)),d=i/2;if(t.strokeStyle=t.fillStyle=l?l.toCanvasStyle(t):"#009dec",a&&this._drawSelected(t,c,n),h){var f=this.getPosition(!0),_=f.x,g=f.y;t.beginPath(),t.arc(_,g,d,0,2*Math.PI,!0),t.stroke();for(var v=[[0,-1],[1,0],[0,1],[-1,0]],p=d,m=i+1,y=0;y<4;y++){var w=v[y],x=w[0],b=w[1];t.moveTo(_+x*p,g+b*p),t.lineTo(_+x*m,g+b*m),t.stroke()}}if(o){var C=c._transformCorners(this.getInternalBounds());t.beginPath();for(var y=0;y<8;y++)t[0===y?"moveTo":"lineTo"](C[y],C[++y]);t.closePath(),t.stroke();for(var y=0;y<8;y++)t.fillRect(C[y]-d,C[++y]-d,i,i)}}},_canComposite:function(){return!1}},r.each(["down","drag","up","move"],function(t){this["removeOn"+r.capitalize(t)]=function(){var e={};return e[t]=!0,this.removeOn(e)}},{removeOn:function(t){for(var e in t)if(t[e]){var i="mouse"+e,n=this._project,r=n._removeSets=n._removeSets||{};r[i]=r[i]||{},r[i][this._id]=this}return this}})),x=w.extend({_class:"Group",_selectBounds:!1,_selectChildren:!0,_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||this.addChildren(Array.isArray(t)?t:arguments)},_changed:function ct(t){ct.base.call(this,t),1026&t&&(this._clipItem=e)},_getClipItem:function(){var t=this._clipItem;if(t===e){t=null;for(var i=this._children,n=0,r=i.length;n<r;n++)if(i[n]._clipMask){t=i[n];break}this._clipItem=t}return t},isClipped:function(){return!!this._getClipItem()},setClipped:function(t){var e=this.getFirstChild();e&&e.setClipMask(t)},_getBounds:function dt(t,e){var i=this._getClipItem();return i?i._getCachedBounds(t&&t.appended(i._matrix),r.set({},e,{stroke:!1})):dt.base.call(this,t,e)},_hitTestChildren:function ft(t,e,i){var n=this._getClipItem();return(!n||n.contains(t))&&ft.base.call(this,t,e,i,n)},_draw:function(t,e){var i=e.clip,n=!i&&this._getClipItem();e=e.extend({clipItem:n,clip:!1}),i?(t.beginPath(),e.dontStart=e.dontFinish=!0):n&&n.draw(t,e.extend({clip:!0}));for(var r=this._children,s=0,a=r.length;s<a;s++){var o=r[s];o!==n&&o.draw(t,e)}}}),b=x.extend({_class:"Layer",initialize:function(){x.apply(this,arguments)},_getOwner:function(){return this._parent||null!=this._index&&this._project},isInserted:function _t(){return this._parent?_t.base.call(this):null!=this._index},activate:function(){this._project._activeLayer=this},_hitTestSelf:function(){}}),C=w.extend({_class:"Shape",_applyMatrix:!1,_canApplyMatrix:!1,_canScaleStroke:!0,_serializeFields:{type:null,size:null,radius:null},initialize:function(t){this._initialize(t)},_equals:function(t){return this._type===t._type&&this._size.equals(t._size)&&r.equals(this._radius,t._radius)},copyContent:function(t){this.setType(t._type),this.setSize(t._size),this.setRadius(t._radius)},getType:function(){return this._type},setType:function(t){this._type=t},getShape:"#getType",setShape:"#setType",getSize:function(){var t=this._size;return new _(t.width,t.height,this,"setSize")},setSize:function(){var t=f.read(arguments);if(this._size){if(!this._size.equals(t)){var e=this._type,i=t.width,n=t.height;if("rectangle"===e){var r=f.min(this._radius,t.divide(2));this._radius.set(r.width,r.height)}else"circle"===e?(i=n=(i+n)/2,this._radius=i/2):"ellipse"===e&&this._radius.set(i/2,n/2);this._size.set(i,n),this._changed(9)}}else this._size=t.clone()},getRadius:function(){var t=this._radius;return"circle"===this._type?t:new _(t.width,t.height,this,"setRadius")},setRadius:function(t){var e=this._type;if("circle"===e){if(t===this._radius)return;var i=2*t;this._radius=t,this._size.set(i,i)}else if(t=f.read(arguments),this._radius){if(this._radius.equals(t))return;if(this._radius.set(t.width,t.height),"rectangle"===e){var i=f.max(this._size,t.multiply(2));this._size.set(i.width,i.height)}else"ellipse"===e&&this._size.set(2*t.width,2*t.height)}else this._radius=t.clone();this._changed(9)},isEmpty:function(){return!1},toPath:function(t){var i=new(L[r.capitalize(this._type)])({center:new c,size:this._size,radius:this._radius,insert:!1});return i.copyAttributes(this),paper.settings.applyMatrix&&i.setApplyMatrix(!0),(t===e||t)&&i.insertAbove(this),i},toShape:"#clone",_draw:function(t,e,i,n){var r=this._style,s=r.hasFill(),a=r.hasStroke(),o=e.dontFinish||e.clip,h=!n;if(s||a||o){var u=this._type,l=this._radius,c="circle"===u;if(e.dontStart||t.beginPath(),h&&c)t.arc(0,0,l,0,2*Math.PI,!0);else{var d=c?l:l.width,f=c?l:l.height,_=this._size,g=_.width,v=_.height;if(h&&"rectangle"===u&&0===d&&0===f)t.rect(-g/2,-v/2,g,v);else{var p=g/2,m=v/2,y=.44771525016920644,w=d*y,x=f*y,b=[-p,-m+f,-p,-m+x,-p+w,-m,-p+d,-m,p-d,-m,p-w,-m,p,-m+x,p,-m+f,p,m-f,p,m-x,p-w,m,p-d,m,-p+d,m,-p+w,m,-p,m-x,-p,m-f];n&&n.transform(b,b,32),t.moveTo(b[0],b[1]),t.bezierCurveTo(b[2],b[3],b[4],b[5],b[6],b[7]),p!==d&&t.lineTo(b[8],b[9]),t.bezierCurveTo(b[10],b[11],b[12],b[13],b[14],b[15]),m!==f&&t.lineTo(b[16],b[17]),t.bezierCurveTo(b[18],b[19],b[20],b[21],b[22],b[23]),p!==d&&t.lineTo(b[24],b[25]),t.bezierCurveTo(b[26],b[27],b[28],b[29],b[30],b[31])}}t.closePath()}o||!s&&!a||(this._setStyles(t,e,i),s&&(t.fill(r.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),a&&t.stroke())},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_getBounds:function(t,e){var i=new g(this._size).setCenter(0,0),n=this._style,r=e.stroke&&n.hasStroke()&&n.getStrokeWidth();return t&&(i=t._transformBounds(i)),r?i.expand(L._getStrokePadding(r,this._getStrokeMatrix(t,e))):i}},new function(){function t(t,e,i){var n=t._radius;if(!n.isZero())for(var r=t._size.divide(2),s=0;s<4;s++){var a=new c(1&s?1:-1,s>1?1:-1),o=a.multiply(r),h=o.subtract(a.multiply(n)),u=new g(o,h);if((i?u.expand(i):u).contains(e))return h}}function e(t,e,i,n){var r=t.divide(e);return(!n||r.quadrant===n)&&r.subtract(r.normalize()).multiply(e).divide(i).length<=1}return{_contains:function i(e){if("rectangle"===this._type){var n=t(this,e);return n?e.subtract(n).divide(this._radius).getLength()<=1:i.base.call(this,e)}return e.divide(this.size).getLength()<=.5},_hitTestSelf:function n(i,r,s,a){var o=!1,h=this._style,u=r.stroke&&h.hasStroke(),l=r.fill&&h.hasFill();if(u||l){var c=this._type,d=this._radius,f=u?h.getStrokeWidth()/2:0,_=r._tolerancePadding.add(L._getStrokePadding(f,!h.getStrokeScaling()&&a));if("rectangle"===c){var v=_.multiply(2),p=t(this,i,v);if(p)o=e(i.subtract(p),d,_,p.getQuadrant());else{var m=new g(this._size).setCenter(0,0),y=m.expand(v),w=m.expand(v.negate());o=y._containsPoint(i)&&!w._containsPoint(i)}}else o=e(i,d,_)}return o?new M(u?"stroke":"fill",this):n.base.apply(this,arguments)}}},{statics:new function(){function t(t,e,i,n,s){var a=new C(r.getNamed(s));return a._type=t,a._size=i,a._radius=n,a.translate(e)}return{Circle:function(){var e=c.readNamed(arguments,"center"),i=r.readNamed(arguments,"radius");return t("circle",e,new f(2*i),i,arguments)},Rectangle:function(){var e=g.readNamed(arguments,"rectangle"),i=f.min(f.readNamed(arguments,"radius"),e.getSize(!0).divide(2));return t("rectangle",e.getCenter(!0),e.getSize(!0),i,arguments)},Ellipse:function(){var e=C._readEllipse(arguments),i=e.radius;return t("ellipse",e.center,i.multiply(2),i,arguments)},_readEllipse:function(t){var e,i;if(r.hasNamed(t,"radius"))e=c.readNamed(t,"center"),i=f.readNamed(t,"radius");else{var n=g.readNamed(t,"rectangle");e=n.getCenter(!0),i=n.getSize(!0).divide(2)}return{center:e,radius:i}}}}}),S=w.extend({_class:"Raster",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!1,handle:!1},_serializeFields:{crossOrigin:null,source:null},initialize:function(t,i){if(!this._initialize(t,i!==e&&c.read(arguments,1))){var r="string"==typeof t?n.getElementById(t):t;r?this.setImage(r):this.setSource(t)}this._size||(this._size=new f,this._loaded=!1)},_equals:function(t){return this.getSource()===t.getSource()},copyContent:function(t){var e=t._image,i=t._canvas;if(e)this._setImage(e);else if(i){var n=Q.getCanvas(t._size);n.getContext("2d").drawImage(i,0,0),this._setImage(n)}this._crossOrigin=t._crossOrigin},getSize:function(){var t=this._size;return new _(t?t.width:0,t?t.height:0,this,"setSize")},setSize:function(){var t=f.read(arguments);if(!t.equals(this._size))if(t.width>0&&t.height>0){var e=this.getElement();this._setImage(Q.getCanvas(t)),e&&this.getContext(!0).drawImage(e,0,0,t.width,t.height)}else this._canvas&&Q.release(this._canvas),this._size=t.clone()},getWidth:function(){return this._size?this._size.width:0},setWidth:function(t){this.setSize(t,this.getHeight())},getHeight:function(){return this._size?this._size.height:0},setHeight:function(t){this.setSize(this.getWidth(),t)},getLoaded:function(){return this._loaded},isEmpty:function(){var t=this._size;return!t||0===t.width&&0===t.height},getResolution:function(){var t=this._matrix,e=new c(0,0).transform(t),i=new c(1,0).transform(t).subtract(e),n=new c(0,1).transform(t).subtract(e);return new f(72/i.getLength(),72/n.getLength())},getPpi:"#getResolution",getImage:function(){return this._image},setImage:function(t){function e(t){var e=i.getView(),n=t&&t.type||"load";e&&i.responds(n)&&(paper=e._scope,i.emit(n,new G(t)))}var i=this;this._setImage(t),this._loaded?setTimeout(e,0):t&&Z.add(t,{load:function(n){i._setImage(t),e(n)},error:e})},_setImage:function(t){this._canvas&&Q.release(this._canvas),t&&t.getContext?(this._image=null,this._canvas=t,this._loaded=!0):(this._image=t,this._canvas=null,this._loaded=!!(t&&t.src&&t.complete)),this._size=new f(t?t.naturalWidth||t.width:0,t?t.naturalHeight||t.height:0),this._context=null,this._changed(521)},getCanvas:function(){if(!this._canvas){var t=Q.getContext(this._size);try{this._image&&t.drawImage(this._image,0,0),this._canvas=t.canvas}catch(e){Q.release(t)}}return this._canvas},setCanvas:"#setImage",getContext:function(t){return this._context||(this._context=this.getCanvas().getContext("2d")),t&&(this._image=null,this._changed(513)),this._context},setContext:function(t){this._context=t},getSource:function(){var t=this._image;return t&&t.src||this.toDataURL()},setSource:function(t){var e=new i.Image,n=this._crossOrigin;n&&(e.crossOrigin=n),e.src=t,this.setImage(e)},getCrossOrigin:function(){var t=this._image;return t&&t.crossOrigin||this._crossOrigin||""},setCrossOrigin:function(t){this._crossOrigin=t;var e=this._image;e&&(e.crossOrigin=t)},getElement:function(){return this._canvas||this._loaded&&this._image}},{beans:!1,getSubCanvas:function(){var t=g.read(arguments),e=Q.getContext(t.getSize());return e.drawImage(this.getCanvas(),t.x,t.y,t.width,t.height,0,0,t.width,t.height),e.canvas},getSubRaster:function(){var t=g.read(arguments),e=new S(w.NO_INSERT);return e._setImage(this.getSubCanvas(t)),e.translate(t.getCenter().subtract(this.getSize().divide(2))),e._matrix.prepend(this._matrix),e.insertAbove(this),e},toDataURL:function(){var t=this._image,e=t&&t.src;if(/^data:/.test(e))return e;var i=this.getCanvas();return i?i.toDataURL.apply(i,arguments):null},drawImage:function(t){var e=c.read(arguments,1);this.getContext(!0).drawImage(t,e.x,e.y)},getAverageColor:function(t){var e,i;if(t?t instanceof A?(i=t,e=t.getBounds()):"object"==typeof t&&("width"in t?e=new g(t):"x"in t&&(e=new g(t.x-.5,t.y-.5,1,1))):e=this.getBounds(),!e)return null;var n=32,s=Math.min(e.width,n),a=Math.min(e.height,n),o=S._sampleContext;o?o.clearRect(0,0,n+1,n+1):o=S._sampleContext=Q.getContext(new f(n)),o.save();var h=(new p).scale(s/e.width,a/e.height).translate(-e.x,-e.y);h.applyToContext(o),i&&i.draw(o,new r({clip:!0,matrices:[h]})),this._matrix.applyToContext(o);var u=this.getElement(),l=this._size;u&&o.drawImage(u,-l.width/2,-l.height/2),o.restore();for(var c=o.getImageData(.5,.5,Math.ceil(s),Math.ceil(a)).data,d=[0,0,0],_=0,v=0,m=c.length;v<m;v+=4){var y=c[v+3];_+=y,y/=255,d[0]+=c[v]*y,d[1]+=c[v+1]*y,d[2]+=c[v+2]*y}for(var v=0;v<3;v++)d[v]/=_;return _?F.read(d):null},getPixel:function(){var t=c.read(arguments),e=this.getContext().getImageData(t.x,t.y,1,1).data;return new F("rgb",[e[0]/255,e[1]/255,e[2]/255],e[3]/255)},setPixel:function(){var t=c.read(arguments),e=F.read(arguments),i=e._convert("rgb"),n=e._alpha,r=this.getContext(!0),s=r.createImageData(1,1),a=s.data;a[0]=255*i[0],a[1]=255*i[1],a[2]=255*i[2],a[3]=null!=n?255*n:255,r.putImageData(s,t.x,t.y)},createImageData:function(){var t=f.read(arguments);return this.getContext().createImageData(t.width,t.height)},getImageData:function(){var t=g.read(arguments);return t.isEmpty()&&(t=new g(this._size)),this.getContext().getImageData(t.x,t.y,t.width,t.height)},setImageData:function(t){var e=c.read(arguments,1);this.getContext(!0).putImageData(t,e.x,e.y)},_getBounds:function(t,e){var i=new g(this._size).setCenter(0,0);return t?t._transformBounds(i):i},_hitTestSelf:function(t){if(this._contains(t)){var e=this;return new M("pixel",e,{offset:t.add(e._size.divide(2)).round(),color:{get:function(){return e.getPixel(this.offset)}}})}},_draw:function(t){var e=this.getElement();e&&(t.globalAlpha=this._opacity,t.drawImage(e,-this._size.width/2,-this._size.height/2))},_canComposite:function(){return!0}}),P=w.extend({_class:"SymbolItem",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!0},_serializeFields:{symbol:null},initialize:function(t,i){this._initialize(t,i!==e&&c.read(arguments,1))||this.setDefinition(t instanceof I?t:new I(t))},_equals:function(t){return this._definition===t._definition},copyContent:function(t){this.setDefinition(t._definition)},getDefinition:function(){return this._definition},setDefinition:function(t){this._definition=t,this._changed(9)},getSymbol:"#getDefinition",setSymbol:"#setDefinition",isEmpty:function(){return this._definition._item.isEmpty()},_getBounds:function(t,e){var i=this._definition._item;return i._getCachedBounds(i._matrix.prepended(t),e)},_hitTestSelf:function(t,e,i,n){var r=this._definition._item._hitTest(t,e,i);return r&&(r.item=this),r},_draw:function(t,e){this._definition._item.draw(t,e)}}),I=r.extend({_class:"SymbolDefinition",initialize:function(t,e){this._id=l.get(),this.project=paper.project,t&&this.setItem(t,e)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._class,this._item],t,!1,e)})},_changed:function(t){8&t&&w._clearBoundsCache(this),1&t&&this.project._changed(t)},getItem:function(){return this._item},setItem:function(t,e){t._symbol&&(t=t.clone()),this._item&&(this._item._symbol=null),this._item=t,t.remove(),t.setSelected(!1),e||t.setPosition(new c),t._symbol=this,this._changed(9)},getDefinition:"#getItem",setDefinition:"#setItem",place:function(t){return new P(this,t)},clone:function(){return new I(this._item.clone(!1))},equals:function(t){return t===this||t&&this._item.equals(t._item)||!1}}),M=r.extend({_class:"HitResult",initialize:function(t,e,i){this.type=t,this.item=e,i&&(i.enumerable=!0,this.inject(i))},statics:{getOptions:function(t){var e=t&&r.read(t);return r.set({type:null,tolerance:paper.settings.hitTolerance,fill:!e,stroke:!e,segments:!e,handles:!1,ends:!1,center:!1,bounds:!1,guides:!1,selected:!1},e)}}}),T=r.extend({_class:"Segment",beans:!0,_selection:0,initialize:function(t,i,n,r,s,a){var o,h,u,l,c=arguments.length;0===c||(1===c?t&&"point"in t?(o=t.point,h=t.handleIn,u=t.handleOut,l=t.selection):o=t:null==t||"object"==typeof t?(o=t,h=i,u=n,l=r):(o=t!==e?[t,i]:null,h=n!==e?[n,r]:null,u=s!==e?[s,a]:null)),new k(o,this,"_point"),new k(h,this,"_handleIn"),new k(u,this,"_handleOut"),l&&this.setSelection(l)},_serialize:function(t,e){var i=this._point,n=this._selection,s=n||this.hasHandles()?[i,this._handleIn,this._handleOut]:i;return n&&s.push(n),r.serialize(s,t,!0,e)},_changed:function(t){var e=this._path;if(e){var i,n=e._curves,r=this._index;n&&(t&&t!==this._point&&t!==this._handleIn||!(i=r>0?n[r-1]:e._closed?n[n.length-1]:null)||i._changed(),t&&t!==this._point&&t!==this._handleOut||!(i=n[r])||i._changed()),e._changed(25)}},getPoint:function(){return this._point},setPoint:function(){var t=c.read(arguments);this._point.set(t.x,t.y)},getHandleIn:function(){return this._handleIn},setHandleIn:function(){var t=c.read(arguments);this._handleIn.set(t.x,t.y)},getHandleOut:function(){return this._handleOut},setHandleOut:function(){var t=c.read(arguments);this._handleOut.set(t.x,t.y)},hasHandles:function(){return!this._handleIn.isZero()||!this._handleOut.isZero()},clearHandles:function(){this._handleIn.set(0,0),this._handleOut.set(0,0)},getSelection:function(){return this._selection},setSelection:function(t){var e=this._selection,i=this._path;this._selection=t=t||0,i&&t!==e&&(i._updateSelection(this,e,t),i._changed(129))},changeSelection:function(t,e){var i=this._selection;this.setSelection(e?i|t:i&~t)},isSelected:function(){return!!(7&this._selection)},setSelected:function(t){this.changeSelection(7,t)},getIndex:function(){return this._index!==e?this._index:null},getPath:function(){return this._path||null},getCurve:function(){var t=this._path,e=this._index;return t?(e>0&&!t._closed&&e===t._segments.length-1&&e--,t.getCurves()[e]||null):null},getLocation:function(){var t=this.getCurve();return t?new O(t,this===t._segment1?0:1):null},getNext:function(){var t=this._path&&this._path._segments;return t&&(t[this._index+1]||this._path._closed&&t[0])||null},smooth:function(t,i,n){var r=t||{},s=r.type,a=r.factor,o=this.getPrevious(),h=this.getNext(),u=(o||this)._point,l=this._point,d=(h||this)._point,f=u.getDistance(l),_=l.getDistance(d);if(s&&"catmull-rom"!==s){if("geometric"!==s)throw new Error("Smoothing method '"+s+"' not supported.");if(o&&h){var g=u.subtract(d),v=a===e?.4:a,p=v*f/(f+_);i||this.setHandleIn(g.multiply(p)),n||this.setHandleOut(g.multiply(p-v))}}else{var m=a===e?.5:a,y=Math.pow(f,m),w=y*y,x=Math.pow(_,m),b=x*x;if(!i&&o){var C=2*b+3*x*y+w,S=3*x*(x+y);this.setHandleIn(0!==S?new c((b*u._x+C*l._x-w*d._x)/S-l._x,(b*u._y+C*l._y-w*d._y)/S-l._y):new c)}if(!n&&h){var C=2*w+3*y*x+b,S=3*y*(y+x);this.setHandleOut(0!==S?new c((w*d._x+C*l._x-b*u._x)/S-l._x,(w*d._y+C*l._y-b*u._y)/S-l._y):new c)}}},getPrevious:function(){var t=this._path&&this._path._segments;return t&&(t[this._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._index},isLast:function(){var t=this._path;return t&&this._index===t._segments.length-1||!1},reverse:function(){var t=this._handleIn,e=this._handleOut,i=t._x,n=t._y;t.set(e._x,e._y),e.set(i,n)},reversed:function(){return new T(this._point,this._handleOut,this._handleIn)},remove:function(){return!!this._path&&!!this._path.removeSegment(this._index)},clone:function(){return new T(this._point,this._handleIn,this._handleOut)},equals:function(t){return t===this||t&&this._class===t._class&&this._point.equals(t._point)&&this._handleIn.equals(t._handleIn)&&this._handleOut.equals(t._handleOut)||!1},toString:function(){var t=["point: "+this._point];return this._handleIn.isZero()||t.push("handleIn: "+this._handleIn),this._handleOut.isZero()||t.push("handleOut: "+this._handleOut),"{ "+t.join(", ")+" }"},transform:function(t){this._transformCoordinates(t,new Array(6),!0),this._changed()},interpolate:function(t,e,i){var n=1-i,r=i,s=t._point,a=e._point,o=t._handleIn,h=e._handleIn,u=e._handleOut,l=t._handleOut;this._point.set(n*s._x+r*a._x,n*s._y+r*a._y,!0),this._handleIn.set(n*o._x+r*h._x,n*o._y+r*h._y,!0),this._handleOut.set(n*l._x+r*u._x,n*l._y+r*u._y,!0),this._changed()},_transformCoordinates:function(t,e,i){var n=this._point,r=i&&this._handleIn.isZero()?null:this._handleIn,s=i&&this._handleOut.isZero()?null:this._handleOut,a=n._x,o=n._y,h=2;return e[0]=a,e[1]=o,r&&(e[h++]=r._x+a,e[h++]=r._y+o),s&&(e[h++]=s._x+a,e[h++]=s._y+o),t&&(t._transformCoordinates(e,e,h/2),a=e[0],o=e[1],i?(n._x=a,n._y=o,h=2,r&&(r._x=e[h++]-a,r._y=e[h++]-o),s&&(s._x=e[h++]-a,s._y=e[h++]-o)):(r||(e[h++]=a,e[h++]=o),s||(e[h++]=a,e[h++]=o))),e}}),k=c.extend({initialize:function(t,i,n){var r,s,a;if(t)if((r=t[0])!==e)s=t[1];else{var o=t;(r=o.x)===e&&(o=c.read(arguments),r=o.x),s=o.y,a=o.selected}else r=s=0;this._x=r,this._y=s,this._owner=i,i[n]=this,a&&this.setSelected(!0)},set:function(t,e){return this._x=t,this._y=e,this._owner._changed(this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner._changed(this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner._changed(this)},isZero:function(){return u.isZero(this._x)&&u.isZero(this._y)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){var t=this._owner;return this===t._point?1:this===t._handleIn?2:this===t._handleOut?4:0}}),z=r.extend({_class:"Curve",initialize:function(t,e,i,n,r,s,a,o){var h,u,l,c,d,f,_=arguments.length;3===_?(this._path=t,h=e,u=i):0===_?(h=new T,u=new T):1===_?"segment1"in t?(h=new T(t.segment1),u=new T(t.segment2)):"point1"in t?(l=t.point1,d=t.handle1,f=t.handle2,c=t.point2):Array.isArray(t)&&(l=[t[0],t[1]],c=[t[6],t[7]],d=[t[2]-t[0],t[3]-t[1]],f=[t[4]-t[6],t[5]-t[7]]):2===_?(h=new T(t),u=new T(e)):4===_?(l=t,d=e,f=i,c=n):8===_&&(l=[t,e],c=[a,o],d=[i-t,n-e],f=[r-a,s-o]),this._segment1=h||new T(l,null,d),this._segment2=u||new T(c,f,null)},_serialize:function(t,e){return r.serialize(this.hasHandles()?[this.getPoint1(),this.getHandle1(),this.getHandle2(),this.getPoint2()]:[this.getPoint1(),this.getPoint2()],t,!0,e)},_changed:function(){this._length=this._bounds=e},clone:function(){return new z(this._segment1,this._segment2)},toString:function(){var t=["point1: "+this._segment1._point];return this._segment1._handleOut.isZero()||t.push("handle1: "+this._segment1._handleOut),this._segment2._handleIn.isZero()||t.push("handle2: "+this._segment2._handleIn),t.push("point2: "+this._segment2._point),"{ "+t.join(", ")+" }"},remove:function(){var t=!1;if(this._path){var e=this._segment2,i=e._handleOut;t=e.remove(),t&&this._segment1._handleOut.set(i.x,i.y)}return t},getPoint1:function(){return this._segment1._point},setPoint1:function(){var t=c.read(arguments);this._segment1._point.set(t.x,t.y)},getPoint2:function(){return this._segment2._point},setPoint2:function(){var t=c.read(arguments);this._segment2._point.set(t.x,t.y)},getHandle1:function(){return this._segment1._handleOut},setHandle1:function(){var t=c.read(arguments);this._segment1._handleOut.set(t.x,t.y)},getHandle2:function(){return this._segment2._handleIn},setHandle2:function(){var t=c.read(arguments);this._segment2._handleIn.set(t.x,t.y)},getSegment1:function(){return this._segment1},getSegment2:function(){return this._segment2},getPath:function(){return this._path},getIndex:function(){return this._segment1._index},getNext:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index+1]||this._path._closed&&t[0])||null},getPrevious:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._segment1._index},isLast:function(){var t=this._path;return t&&this._segment1._index===t._curves.length-1||!1},isSelected:function(){return this.getPoint1().isSelected()&&this.getHandle2().isSelected()&&this.getHandle2().isSelected()&&this.getPoint2().isSelected()},setSelected:function(t){this.getPoint1().setSelected(t),this.getHandle1().setSelected(t),this.getHandle2().setSelected(t),this.getPoint2().setSelected(t)},getValues:function(t){return z.getValues(this._segment1,this._segment2,t)},getPoints:function(){for(var t=this.getValues(),e=[],i=0;i<8;i+=2)e.push(new c(t[i],t[i+1]));return e},getLength:function(){return null==this._length&&(this._length=z.getLength(this.getValues(),0,1)),this._length},getArea:function(){return z.getArea(this.getValues())},getLine:function(){return new m(this._segment1._point,this._segment2._point)},getPart:function(t,e){return new z(z.getPart(this.getValues(),t,e))},getPartLength:function(t,e){return z.getLength(this.getValues(),t,e)},getIntersections:function(t){return z._getIntersections(this.getValues(),t&&t!==this?t.getValues():null,this,t,[],{})},divideAt:function(t){return this.divideAtTime(t&&t.curve===this?t.time:t)},divideAtTime:function(t,e){var i=4e-7,n=1-i,r=null;if(t>=i&&t<=n){var s=z.subdivide(this.getValues(),t),a=s[0],o=s[1],h=e||this.hasHandles(),u=this._segment1,l=this._segment2,d=this._path;h&&(u._handleOut.set(a[2]-a[0],a[3]-a[1]),l._handleIn.set(o[4]-o[6],o[5]-o[7]));var f=a[6],_=a[7],g=new T(new c(f,_),h&&new c(a[4]-f,a[5]-_),h&&new c(o[2]-f,o[3]-_));d?(d.insert(u._index+1,g),r=this.getNext()):(this._segment2=g,this._changed(),r=new z(g,l))}return r},splitAt:function(t){return this._path?this._path.splitAt(t):null},splitAtTime:function(t){return this.splitAt(this.getLocationAtTime(t))},divide:function(t,i){return this.divideAtTime(t===e?.5:i?t:this.getTimeAt(t))},split:function(t,i){return this.splitAtTime(t===e?.5:i?t:this.getTimeAt(t))},reversed:function(){return new z(this._segment2.reversed(),this._segment1.reversed())},clearHandles:function(){this._segment1._handleOut.set(0,0),this._segment2._handleIn.set(0,0)},statics:{getValues:function(t,e,i){var n=t._point,r=t._handleOut,s=e._handleIn,a=e._point,o=[n._x,n._y,n._x+r._x,n._y+r._y,a._x+s._x,a._y+s._y,a._x,a._y];return i&&i._transformCoordinates(o,o,4),o},subdivide:function(t,i){var n=t[0],r=t[1],s=t[2],a=t[3],o=t[4],h=t[5],u=t[6],l=t[7];i===e&&(i=.5);var c=1-i,d=c*n+i*s,f=c*r+i*a,_=c*s+i*o,g=c*a+i*h,v=c*o+i*u,p=c*h+i*l,m=c*d+i*_,y=c*f+i*g,w=c*_+i*v,x=c*g+i*p,b=c*m+i*w,C=c*y+i*x;return[[n,r,d,f,m,y,b,C],[b,C,w,x,v,p,u,l]]},solveCubic:function(t,e,i,n,r,s){var a=t[e],o=t[e+2],h=t[e+4],l=t[e+6],c=0;if(!(a<i&&l<i&&o<i&&h<i||a>i&&l>i&&o>i&&h>i)){var d=3*(o-a),f=3*(h-o)-d,_=l-a-d-f;c=u.solveCubic(_,f,d,a-i,n,r,s)}return c},getTimeOf:function(t,e){var i=new c(t[0],t[1]),n=new c(t[6],t[7]),r=1e-12,s=e.isClose(i,r)?0:e.isClose(n,r)?1:null;if(null!==s)return s;for(var a=[e.x,e.y],o=[],h=2e-7,u=0;u<2;u++)for(var l=z.solveCubic(t,u,a[u],o,0,1),d=0;d<l;d++)if(s=o[d],e.isClose(z.getPoint(t,s),h))return s;return e.isClose(i,h)?0:e.isClose(n,h)?1:null},getNearestTime:function(t,e){function i(i){if(i>=0&&i<=1){var n=e.getDistance(z.getPoint(t,i),!0);if(n<f)return f=n,_=i,!0}}if(z.isStraight(t)){var n=t[0],r=t[1],s=t[6],a=t[7],o=s-n,h=a-r,u=o*o+h*h;if(0===u)return 0;var l=((e.x-n)*o+(e.y-r)*h)/u;return l<1e-12?0:l>.999999999999?1:z.getTimeOf(t,new c(n+l*o,r+l*h))}for(var d=100,f=1/0,_=0,g=0;g<=d;g++)i(g/d);for(var v=1/(2*d);v>4e-7;)i(_-v)||i(_+v)||(v/=2);return _},getPart:function(t,e,i){var n=e>i;if(n){var r=e;e=i,i=r}return e>0&&(t=z.subdivide(t,e)[1]),i<1&&(t=z.subdivide(t,(i-e)/(1-e))[0]),n?[t[6],t[7],t[4],t[5],t[2],t[3],t[0],t[1]]:t},isFlatEnough:function(t,e){var i=t[0],n=t[1],r=t[2],s=t[3],a=t[4],o=t[5],h=t[6],u=t[7],l=3*r-2*i-h,c=3*s-2*n-u,d=3*a-2*h-i,f=3*o-2*u-n;return Math.max(l*l,d*d)+Math.max(c*c,f*f)<=16*e*e},getArea:function(t){var e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7];return 3*((h-i)*(n+s)-(o-e)*(r+a)+r*(e-s)-n*(i-a)+h*(s+e/3)-o*(a+i/3))/20},getBounds:function(t){for(var e=t.slice(0,2),i=e.slice(),n=[0,0],r=0;r<2;r++)z._addBounds(t[r],t[r+2],t[r+4],t[r+6],r,0,e,i,n);return new g(e[0],e[1],i[0]-e[0],i[1]-e[1])},_addBounds:function(t,e,i,n,r,s,a,o,h){function l(t,e){var i=t-e,n=t+e;i<a[r]&&(a[r]=i),n>o[r]&&(o[r]=n)}s/=2;var c=a[r]-s,d=o[r]+s;if(t<c||e<c||i<c||n<c||t>d||e>d||i>d||n>d)if(e<t!=e<n&&i<t!=i<n)l(t,s),l(n,s);else{var f=3*(e-i)-t+n,_=2*(t+i)-4*e,g=e-t,v=u.solveQuadratic(f,_,g,h),p=4e-7,m=1-p;l(n,0);for(var y=0;y<v;y++){var w=h[y],x=1-w;p<w&&w<m&&l(x*x*x*t+3*x*x*w*e+3*x*w*w*i+w*w*w*n,s)}}}}},r.each(["getBounds","getStrokeBounds","getHandleBounds"],function(t){this[t]=function(){this._bounds||(this._bounds={});var e=this._bounds[t];return e||(e=this._bounds[t]=L[t]([this._segment1,this._segment2],!1,this._path)),e.clone()}},{}),r.each({isStraight:function(t,e,i){if(e.isZero()&&i.isZero())return!0;var n=t.getVector(),r=2e-7;if(n.isZero())return!1;if(t.getDistance(e)<r&&t.getDistance(i)<r){var s=n.dot(n),a=n.dot(e)/s,o=n.dot(i)/s;return a>=0&&a<=1&&o<=0&&o>=-1}return!1},isLinear:function(t,e,i){var n=t.getVector().divide(3);return e.equals(n)&&i.negate().equals(n)}},function(t,e){this[e]=function(){var e=this._segment1,i=this._segment2;return t(new m(e._point,i._point),e._handleOut,i._handleIn)},this.statics[e]=function(e){var i=e[0],n=e[1],r=e[6],s=e[7];return t(new m(i,n,r,s),new c(e[2]-i,e[3]-n),new c(e[4]-r,e[5]-s))}},{statics:{},hasHandles:function(){return!this._segment1._handleOut.isZero()||!this._segment2._handleIn.isZero()},isCollinear:function(t){return t&&this.isStraight()&&t.isStraight()&&this.getLine().isCollinear(t.getLine())},isHorizontal:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).y)<1e-7},isVertical:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).x)<1e-7}}),{beans:!1,getLocationAt:function(t,e){return this.getLocationAtTime(e?t:this.getTimeAt(t))},getLocationAtTime:function(t){return null!=t&&t>=0&&t<=1?new O(this,t):null},getTimeAt:function(t,e){return z.getTimeAt(this.getValues(),t,e)},getParameterAt:"#getTimeAt",getOffsetAtTime:function(t){return this.getPartLength(0,t)},getLocationOf:function(){return this.getLocationAtTime(this.getTimeOf(c.read(arguments)))},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getTimeOf:function(){return z.getTimeOf(this.getValues(),c.read(arguments))},getParameterOf:"#getTimeOf",getNearestLocation:function(){var t=c.read(arguments),e=this.getValues(),i=z.getNearestTime(e,t),n=z.getPoint(e,i);return new O(this,i,n,null,t.getDistance(n))},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t}},new function(){var t=["getPoint","getTangent","getNormal","getWeightedTangent","getWeightedNormal","getCurvature"];return r.each(t,function(t){this[t+"At"]=function(e,i){var n=this.getValues();return z[t](n,i?e:z.getTimeAt(n,e))},this[t+"AtTime"]=function(e){return z[t](this.getValues(),e)}},{statics:{_evaluateMethods:t}})},new function(){function t(t){var e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7],u=9*(n-s)+3*(o-e),l=6*(e+s)-12*n,c=3*(n-e),d=9*(r-a)+3*(h-i),f=6*(i+a)-12*r,_=3*(r-i);return function(t){var e=(u*t+l)*t+c,i=(d*t+f)*t+_;return Math.sqrt(e*e+i*i)}}function i(t,e){return Math.max(2,Math.min(16,Math.ceil(32*Math.abs(e-t))))}function n(t,e,i,n){if(null==e||e<0||e>1)return null;var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],d=t[6],f=t[7],_=u.isZero;_(a-r)&&_(o-s)&&(a=r,o=s),_(h-d)&&_(l-f)&&(h=d,l=f);var g,v,p=3*(a-r),m=3*(h-a)-p,y=d-r-p-m,w=3*(o-s),x=3*(l-o)-w,b=f-s-w-x;if(0===i)g=0===e?r:1===e?d:((y*e+m)*e+p)*e+r,v=0===e?s:1===e?f:((b*e+x)*e+w)*e+s;else{var C=4e-7,S=1-C;if(e<C?(g=p,v=w):e>S?(g=3*(d-h),v=3*(f-l)):(g=(3*y*e+2*m)*e+p,v=(3*b*e+2*x)*e+w),n){0===g&&0===v&&(e<C||e>S)&&(g=h-a,v=l-o);var P=Math.sqrt(g*g+v*v);P&&(g/=P,v/=P)}if(3===i){var I=6*y*e+2*m,M=6*b*e+2*x,T=Math.pow(g*g+v*v,1.5);g=0!==T?(g*M-v*I)/T:0,v=0}}return 2===i?new c(v,(-g)):new c(g,v)}return{statics:{getLength:function(n,r,s,a){if(r===e&&(r=0),s===e&&(s=1),z.isStraight(n)){var o=n;s<1&&(o=z.subdivide(o,s)[0],r/=s),r>0&&(o=z.subdivide(o,r)[1]);var h=o[6]-o[0],l=o[7]-o[1];return Math.sqrt(h*h+l*l)}return u.integrate(a||t(n),r,s,i(r,s))},getTimeAt:function(n,r,s){function a(t){return p+=u.integrate(f,s,t,i(s,t)),s=t,p-r}if(s===e&&(s=r<0?1:0),0===r)return s;var o=Math.abs,h=1e-12,l=r>0,c=l?s:0,d=l?1:s,f=t(n),_=z.getLength(n,c,d,f),g=o(r)-_;if(o(g)<h)return l?d:c;if(g>h)return null;var v=r/_,p=0;return u.findRoot(a,f,s+v,c,d,32,1e-12)},getPoint:function(t,e){return n(t,e,0,!1)},getTangent:function(t,e){return n(t,e,1,!0)},getWeightedTangent:function(t,e){return n(t,e,1,!1)},getNormal:function(t,e){return n(t,e,2,!0)},getWeightedNormal:function(t,e){return n(t,e,2,!1)},getCurvature:function(t,e){return n(t,e,3,!1).x}}}},new function(){function t(t,e,i,n,r,s,a,o,h,u,l){var c=!l&&e.excludeStart,d=!l&&e.excludeEnd,f=4e-7,_=1-f;if(null==r&&(r=z.getTimeOf(i,s)),null!==r&&r>=(c?f:0)&&r<=(d?_:1)&&(null==h&&(h=z.getTimeOf(a,u)),null!==h&&h>=(d?f:0)&&h<=(c?_:1))){var g=e.renormalize;if(g){
-var v=g(r,h);r=v[0],h=v[1]}var p=new O(n,r,s||z.getPoint(i,r),l),m=new O(o,h,u||z.getPoint(a,h),l),y=p.getPath()===m.getPath()&&p.getIndex()>m.getIndex(),w=y?m:p,x=e.include;p._intersection=m,m._intersection=p,x&&!x(w)||O.insert(t,w,!0)}}function e(r,s,a,o,h,u,l,c,d,f,_,g,v){if(++g>=48||++v>4096)return v;var p,y,w=s[0],x=s[1],b=s[6],C=s[7],S=m.getSignedDistance,P=S(w,x,b,C,s[2],s[3]),I=S(w,x,b,C,s[4],s[5]),M=P*I>0?.75:4/9,T=M*Math.min(0,P,I),k=M*Math.max(0,P,I),O=S(w,x,b,C,r[0],r[1]),A=S(w,x,b,C,r[2],r[3]),L=S(w,x,b,C,r[4],r[5]),N=S(w,x,b,C,r[6],r[7]),B=i(O,A,L,N),E=B[0],D=B[1];if(0===P&&0===I&&0===O&&0===A&&0===L&&0===N||null==(p=n(E,D,T,k))||null==(y=n(E.reverse(),D.reverse(),T,k)))return v;var j=l+(c-l)*p,F=l+(c-l)*y;if(Math.max(f-d,F-j)<1e-9){var R=(j+F)/2,q=(d+f)/2;r=a.getValues(),s=o.getValues(),t(h,u,_?s:r,_?o:a,_?q:R,null,_?r:s,_?a:o,_?R:q,null)}else if(r=z.getPart(r,p,y),y-p>.8)if(F-j>f-d){var V=z.subdivide(r,.5),R=(j+F)/2;v=e(s,V[0],o,a,h,u,d,f,j,R,!_,g,v),v=e(s,V[1],o,a,h,u,d,f,R,F,!_,g,v)}else{var V=z.subdivide(s,.5),q=(d+f)/2;v=e(V[0],r,o,a,h,u,d,q,j,F,!_,g,v),v=e(V[1],r,o,a,h,u,q,f,j,F,!_,g,v)}else v=e(s,r,o,a,h,u,d,f,j,F,!_,g,v);return v}function i(t,e,i,n){var r,s=[0,t],a=[1/3,e],o=[2/3,i],h=[1,n],u=e-(2*t+n)/3,l=i-(t+2*n)/3;if(u*l<0)r=[[s,a,h],[s,o,h]];else{var c=u/l;r=[c>=2?[s,a,h]:c<=.5?[s,o,h]:[s,a,o,h],[s,h]]}return(u||l)<0?r.reverse():r}function n(t,e,i,n){return t[0][1]<i?r(t,!0,i):e[0][1]>n?r(e,!1,n):t[0][0]}function r(t,e,i){for(var n=t[0][0],r=t[0][1],s=1,a=t.length;s<a;s++){var o=t[s][0],h=t[s][1];if(e?h>=i:h<=i)return h===i?o:n+(i-r)*(o-n)/(h-r);n=o,r=h}return null}function s(e,i,n,r,s,a){for(var o=z.isStraight(e),h=o?i:e,l=o?e:i,c=l[0],d=l[1],f=l[6],_=l[7],g=f-c,v=_-d,p=Math.atan2(-v,g),m=Math.sin(p),y=Math.cos(p),w=[],x=0;x<8;x+=2){var b=h[x]-c,C=h[x+1]-d;w.push(b*y-C*m,b*m+C*y)}for(var S=[],P=z.solveCubic(w,1,0,S,0,1),x=0;x<P;x++){var I=S[x],M=z.getPoint(h,I),T=z.getTimeOf(l,M);if(null!==T){var k=z.getPoint(l,T),O=o?T:I,A=o?I:T;(!a.excludeEnd||A>u.CURVETIME_EPSILON)&&t(s,a,e,n,O,o?k:M,i,r,A,o?M:k)}}}function a(e,i,n,r,s,a){var o=m.intersect(e[0],e[1],e[6],e[7],i[0],i[1],i[6],i[7]);o&&t(s,a,e,n,null,o,i,r,null,o)}return{statics:{_getIntersections:function(i,n,r,o,h,u){if(!n)return z._getSelfIntersection(i,r,h,u);var l=2e-7,d=i[0],f=i[1],_=i[6],g=i[7],v=n[0],p=n[1],m=n[6],y=n[7],w=(3*i[2]+d)/4,x=(3*i[3]+f)/4,b=(3*i[4]+_)/4,C=(3*i[5]+g)/4,S=(3*n[2]+v)/4,P=(3*n[3]+p)/4,I=(3*n[4]+m)/4,M=(3*n[5]+y)/4,T=Math.min,k=Math.max;if(!(k(d,w,b,_)+l>T(v,S,I,m)&&T(d,w,b,_)-l<k(v,S,I,m)&&k(f,x,C,g)+l>T(p,P,M,y)&&T(f,x,C,g)-l<k(p,P,M,y)))return h;var O=z.getOverlaps(i,n);if(O){for(var A=0;A<2;A++){var L=O[A];t(h,u,i,r,L[0],null,n,o,L[1],null,!0)}return h}var N=z.isStraight(i),B=z.isStraight(n),E=N&&B,D=h.length;if((E?a:N||B?s:e)(i,n,r,o,h,u,0,1,0,1,0,0,0),E&&h.length>D)return h;var j=new c(d,f),F=new c(_,g),R=new c(v,p),q=new c(m,y);return j.isClose(R,l)&&t(h,u,i,r,0,j,n,o,0,R),!u.excludeStart&&j.isClose(q,l)&&t(h,u,i,r,0,j,n,o,1,q),!u.excludeEnd&&F.isClose(R,l)&&t(h,u,i,r,1,F,n,o,0,R),F.isClose(q,l)&&t(h,u,i,r,1,F,n,o,1,q),h},_getSelfIntersection:function(t,e,i,n){var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],d=t[6],f=t[7],_=new m(r,s,d,f,(!1)),g=_.getSide(new c(a,o),!0),v=_.getSide(new c(h,l),!0);if(g===v){var p=(r-h)*(o-f)+(a-d)*(l-s);if(p*g>0)return i}var y=d-3*h+3*a-r,w=h-2*a+r,x=a-r,b=f-3*l+3*o-s,C=l-2*o+s,S=o-s,P=b*x-y*S,I=b*w-y*C,M=C*x-w*S;if(P*P-4*I*M<0){var T,k=[],O=u.solveCubic(y*y+b*b,3*(y*w+b*C),2*(w*w+C*C)+y*x+b*S,w*x+C*S,k,0,1);if(O>0){for(var A=0,L=0;A<O;A++){var N=Math.abs(e.getCurvatureAtTime(k[A]));N>L&&(L=N,T=k[A])}var B=z.subdivide(t,T);n.excludeEnd=!0,n.renormalize=function(t,e){return[t*T,e*(1-T)+T]},z._getIntersections(B[0],B[1],e,e,i,n)}}return i},getOverlaps:function(t,e){function i(t){var e=t[6]-t[0],i=t[7]-t[1];return e*e+i*i}var n=Math.abs,r=4e-7,s=2e-7,a=z.isStraight(t),o=z.isStraight(e),h=a&&o,u=i(t)<i(e),l=u?e:t,d=u?t:e,f=new m(l[0],l[1],l[6],l[7]);if(f.getDistance(new c(d[0],d[1]))<s&&f.getDistance(new c(d[6],d[7]))<s)!h&&f.getDistance(new c(l[2],l[3]))<s&&f.getDistance(new c(l[4],l[5]))<s&&f.getDistance(new c(d[2],d[3]))<s&&f.getDistance(new c(d[4],d[5]))<s&&(a=o=h=!0);else if(h)return null;if(a^o)return null;for(var _=[t,e],g=[],v=0,p=0;v<2&&g.length<2;v+=0===p?0:1,p=1^p){var y=z.getTimeOf(_[1^v],new c(_[v][0===p?0:6],_[v][0===p?1:7]));if(null!=y){var w=0===v?[p,y]:[y,p];(0===g.length||n(w[0]-g[0][0])>r&&n(w[1]-g[0][1])>r)&&g.push(w)}if(1===v&&0===g.length)break}if(2!==g.length)g=null;else if(!h){var x=z.getPart(t,g[0][0],g[1][0]),b=z.getPart(e,g[0][1],g[1][1]);(n(b[2]-x[2])>s||n(b[3]-x[3])>s||n(b[4]-x[4])>s||n(b[5]-x[5])>s)&&(g=null)}return g}}}}),O=r.extend({_class:"CurveLocation",beans:!0,initialize:function(t,e,i,n,r){if(e>.9999996){var s=t.getNext();s&&(e=0,t=s)}this._setCurve(t),this._time=e,this._point=i||t.getPointAtTime(e),this._overlap=n,this._distance=r,this._intersection=this._next=this._previous=null},_setCurve:function(t){var e=t._path;this._path=e,this._version=e?e._version:0,this._curve=t,this._segment=null,this._segment1=t._segment1,this._segment2=t._segment2},_setSegment:function(t){this._setCurve(t.getCurve()),this._segment=t,this._time=t===this._segment1?0:1,this._point=t._point.clone()},getSegment:function(){var t=this.getCurve(),e=this._segment;if(!e){var i=this.getTime();0===i?e=t._segment1:1===i?e=t._segment2:null!=i&&(e=t.getPartLength(0,i)<t.getPartLength(i,1)?t._segment1:t._segment2),this._segment=e}return e},getCurve:function(){function t(t){var e=t&&t.getCurve();if(e&&null!=(i._time=e.getTimeOf(i._point)))return i._setCurve(e),i._segment=t,e}var e=this._path,i=this;return e&&e._version!==this._version&&(this._time=this._curve=this._offset=null),this._curve||t(this._segment)||t(this._segment1)||t(this._segment2.getPrevious())},getPath:function(){var t=this.getCurve();return t&&t._path},getIndex:function(){var t=this.getCurve();return t&&t.getIndex()},getTime:function(){var t=this.getCurve(),e=this._time;return t&&null==e?this._time=t.getTimeOf(this._point):e},getParameter:"#getTime",getPoint:function(){return this._point},getOffset:function(){var t=this._offset;if(null==t){t=0;var e=this.getPath(),i=this.getIndex();if(e&&null!=i)for(var n=e.getCurves(),r=0;r<i;r++)t+=n[r].getLength();this._offset=t+=this.getCurveOffset()}return t},getCurveOffset:function(){var t=this.getCurve(),e=this.getTime();return null!=e&&t&&t.getPartLength(0,e)},getIntersection:function(){return this._intersection},getDistance:function(){return this._distance},divide:function(){var t=this.getCurve(),e=null;return t&&(e=t.divideAtTime(this.getTime()),e&&this._setSegment(e._segment1)),e},split:function(){var t=this.getCurve();return t?t.splitAtTime(this.getTime()):null},equals:function(t,e){var i=this===t,n=2e-7;if(!i&&t instanceof O&&this.getPath()===t.getPath()&&this.getPoint().isClose(t.getPoint(),n)){var r=this.getCurve(),s=t.getCurve(),a=Math.abs,o=a((r.isLast()&&s.isFirst()?-1:r.getIndex())+this.getTime()-((s.isLast()&&r.isFirst()?-1:s.getIndex())+t.getTime()));i=(o<4e-7||(o=a(this.getOffset()-t.getOffset()))<n||a(this.getPath().getLength()-o)<n)&&(e||!this._intersection&&!t._intersection||this._intersection&&this._intersection.equals(t._intersection,!0))}return i},toString:function(){var t=[],e=this.getPoint(),i=h.instance;e&&t.push("point: "+e);var n=this.getIndex();null!=n&&t.push("index: "+n);var r=this.getTime();return null!=r&&t.push("time: "+i.number(r)),null!=this._distance&&t.push("distance: "+i.number(this._distance)),"{ "+t.join(", ")+" }"},isTouching:function(){var t=this._intersection;if(t&&this.getTangent().isCollinear(t.getTangent())){var e=this.getCurve(),i=t.getCurve();return!(e.isStraight()&&i.isStraight()&&e.getLine().intersect(i.getLine()))}return!1},isCrossing:function(){function t(t,e,i){return e<i?t>e&&t<i:t>e||t<i}var e=this._intersection;if(!e)return!1;var i=this.getTime(),n=e.getTime(),r=4e-7,s=1-r,a=i>r&&i<s,o=n>r&&n<s;if(a&&o)return!this.isTouching();var h=this.getCurve(),u=i<=r?h.getPrevious():h,l=e.getCurve(),c=n<=r?l.getPrevious():l;if(i>=s&&(h=h.getNext()),n>=s&&(l=l.getNext()),!(u&&h&&c&&l))return!1;var d=[];a||d.push(u.getLength(),h.getLength()),o||d.push(c.getLength(),l.getLength());var f=this.getPoint(),_=Math.min.apply(Math,d)/64,g=a?h.getTangentAtTime(i):h.getPointAt(_).subtract(f),v=a?g.negate():u.getPointAt(-_).subtract(f),p=o?l.getTangentAtTime(n):l.getPointAt(_).subtract(f),m=o?p.negate():c.getPointAt(-_).subtract(f),y=v.getAngle(),w=g.getAngle(),x=m.getAngle(),b=p.getAngle();return!!(a?t(y,x,b)^t(w,x,b)&&t(y,b,x)^t(w,b,x):t(x,y,w)^t(b,y,w)&&t(x,w,y)^t(b,w,y))},hasOverlap:function(){return!!this._overlap}},r.each(z._evaluateMethods,function(t){var e=t+"At";this[t]=function(){var t=this.getCurve(),i=this.getTime();return null!=i&&t&&t[e](i,!0)}},{preserve:!0}),new function(){function t(t,e,i){function n(i,n){for(var s=i+n;s>=-1&&s<=r;s+=n){var a=t[(s%r+r)%r];if(!e.getPoint().isClose(a.getPoint(),2e-7))break;if(e.equals(a))return a}return null}for(var r=t.length,s=0,a=r-1;s<=a;){var o,h=s+a>>>1,u=t[h];if(i&&(o=e.equals(u)?u:n(h,-1)||n(h,1)))return e._overlap&&(o._overlap=o._intersection._overlap=!0),o;var l=e.getPath(),c=u.getPath(),d=l===c?e.getIndex()+e.getTime()-(u.getIndex()+u.getTime()):l._id-c._id;d<0?a=h-1:s=h+1}return t.splice(s,0,e),e}return{statics:{insert:t,expand:function(e){for(var i=e.slice(),n=e.length-1;n>=0;n--)t(i,e[n]._intersection,!1);return i}}}}),A=w.extend({_class:"PathItem",_selectBounds:!1,_canScaleStroke:!0,initialize:function(){},statics:{create:function(t){var e=(t&&t.match(/m/gi)||[]).length>1||/z\s*\S+/i.test(t)?N:L;return new e(t)}},_asPathItem:function(){return this},setPathData:function(t){function e(t,e){var i=+n[t];return o&&(i+=h[e]),i}function i(t){return new c(e(t,"x"),e(t+1,"y"))}var n,r,s,a=t&&t.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/gi),o=!1,h=new c,u=new c;this.clear();for(var l=0,d=a&&a.length;l<d;l++){var _=a[l],g=_[0],v=g.toLowerCase();n=_.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);var p=n&&n.length;switch(o=g===v,"z"!==r||/[mz]/.test(v)||this.moveTo(h=u),v){case"m":case"l":for(var m="m"===v,y=0;y<p;y+=2)this[0===y&&m?"moveTo":"lineTo"](h=i(y));s=h,m&&(u=h);break;case"h":case"v":for(var w="h"===v?"x":"y",y=0;y<p;y++)h[w]=e(y,w),this.lineTo(h);s=h;break;case"c":for(var y=0;y<p;y+=6)this.cubicCurveTo(i(y),s=i(y+2),h=i(y+4));break;case"s":for(var y=0;y<p;y+=4)this.cubicCurveTo(/[cs]/.test(r)?h.multiply(2).subtract(s):h,s=i(y),h=i(y+2)),r=v;break;case"q":for(var y=0;y<p;y+=4)this.quadraticCurveTo(s=i(y),h=i(y+2));break;case"t":for(var y=0;y<p;y+=2)this.quadraticCurveTo(s=/[qt]/.test(r)?h.multiply(2).subtract(s):h,h=i(y)),r=v;break;case"a":for(var y=0;y<p;y+=7)this.arcTo(h=i(y+5),new f((+n[y]),(+n[y+1])),+n[y+2],+n[y+4],+n[y+3]);break;case"z":this.closePath(1e-12)}r=v}},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_contains:function(t){var e=t.isInside(this.getBounds({internal:!0,handle:!0}))&&this._getWinding(t);return!!("evenodd"===this.getFillRule()?1&e:e)},getIntersections:function(t,e,i,n){var r=this===t||!t,s=this._matrix._orNullIfIdentity(),a=r?s:(i||t._matrix)._orNullIfIdentity();if(!r&&!this.getBounds(s).touches(t.getBounds(a)))return[];for(var o,t,h=this.getCurves(),u=r?h:t.getCurves(),l=h.length,c=r?l:u.length,d=[],f=[],_=0;_<c;_++)d[_]=u[_].getValues(a);for(var _=0;_<l;_++){var g=h[_],v=r?d[_]:g.getValues(s),p=g.getPath();p!==t&&(t=p,o=[],f.push(o)),r&&z._getSelfIntersection(v,g,o,{include:e,excludeStart:1===l&&g.getPoint1().equals(g.getPoint2())});for(var m=r?_+1:0;m<c;m++){if(n&&o.length)return o;var y=u[m];z._getIntersections(v,d[m],g,y,o,{include:e,excludeStart:r&&g.getPrevious()===y,excludeEnd:r&&g.getNext()===y})}}o=[];for(var _=0,w=f.length;_<w;_++)o.push.apply(o,f[_]);return o},getCrossings:function(t){return this.getIntersections(t,function(t){return t._overlap||t.isCrossing()})},getNearestLocation:function(){for(var t=c.read(arguments),e=this.getCurves(),i=1/0,n=null,r=0,s=e.length;r<s;r++){var a=e[r].getNearestLocation(t);a._distance<i&&(i=a._distance,n=a)}return n},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t},interpolate:function(t,e,i){var n=!this._children,r=n?"_segments":"_children",s=t[r],a=e[r],o=this[r];if(!s||!a||s.length!==a.length)throw new Error("Invalid operands in interpolate() call: "+t+", "+e);var h=o.length,u=a.length;if(h<u)for(var l=n?T:L,c=h;c<u;c++)this.add(new l);else h>u&&this[n?"removeSegments":"removeChildren"](u,h);for(var c=0;c<u;c++)o[c].interpolate(s[c],a[c],i);n&&(this.setClosed(t._closed),this._changed(9))}}),L=A.extend({_class:"Path",_serializeFields:{segments:[],closed:!1},initialize:function(t){this._closed=!1,this._segments=[],this._version=0;var i=Array.isArray(t)?"object"==typeof t[0]?t:arguments:!t||t.size!==e||t.x===e&&t.point===e?null:arguments;i&&i.length>0?this.setSegments(i):(this._curves=e,this._segmentSelection=0,i||"string"!=typeof t||(this.setPathData(t),t=null)),this._initialize(!i&&t)},_equals:function(t){return this._closed===t._closed&&r.equals(this._segments,t._segments)},copyContent:function(t){this.setSegments(t._segments),this._closed=t._closed;var i=t._clockwise;i!==e&&(this._clockwise=i)},_changed:function gt(t){if(gt.base.call(this,t),8&t){if(this._length=this._area=this._clockwise=this._monoCurves=e,16&t)this._version++;else if(this._curves)for(var i=0,n=this._curves.length;i<n;i++)this._curves[i]._changed()}else 32&t&&(this._bounds=e)},getStyle:function(){var t=this._parent;return(t instanceof N?t:this)._style},getSegments:function(){return this._segments},setSegments:function(t){var i=this.isFullySelected();this._segments.length=0,this._segmentSelection=0,this._curves=e,t&&t.length>0&&this._add(T.readAll(t)),i&&this.setFullySelected(!0)},getFirstSegment:function(){return this._segments[0]},getLastSegment:function(){return this._segments[this._segments.length-1]},getCurves:function(){var t=this._curves,e=this._segments;if(!t){var i=this._countCurves();t=this._curves=new Array(i);for(var n=0;n<i;n++)t[n]=new z(this,e[n],e[n+1]||e[0])}return t},getFirstCurve:function(){return this.getCurves()[0]},getLastCurve:function(){var t=this.getCurves();return t[t.length-1]},isClosed:function(){return this._closed},setClosed:function(t){if(this._closed!=(t=!!t)){if(this._closed=t,this._curves){var e=this._curves.length=this._countCurves();t&&(this._curves[e-1]=new z(this,this._segments[e-1],this._segments[0]))}this._changed(25)}}},{beans:!0,getPathData:function(t,e){function i(e,i){e._transformCoordinates(t,g),n=g[0],r=g[1],v?(p.push("M"+_.pair(n,r)),v=!1):(o=g[2],u=g[3],o===n&&u===r&&l===s&&c===a?i||p.push("l"+_.pair(n-s,r-a)):p.push("c"+_.pair(l-s,c-a)+" "+_.pair(o-s,u-a)+" "+_.pair(n-s,r-a))),s=n,a=r,l=g[4],c=g[5]}var n,r,s,a,o,u,l,c,d=this._segments,f=d.length,_=new h(e),g=new Array(6),v=!0,p=[];if(0===f)return"";for(var m=0;m<f;m++)i(d[m]);return this._closed&&f>0&&(i(d[0],!0),p.push("z")),p.join("")},isEmpty:function(){return 0===this._segments.length},_transformContent:function(t){for(var e=this._segments,i=new Array(6),n=0,r=e.length;n<r;n++)e[n]._transformCoordinates(t,i,!0);return!0},_add:function(t,e){for(var i=this._segments,n=this._curves,r=t.length,s=null==e,e=s?i.length:e,a=0;a<r;a++){var o=t[a];o._path&&(o=t[a]=o.clone()),o._path=this,o._index=e+a,o._selection&&this._updateSelection(o,0,o._selection)}if(s)i.push.apply(i,t);else{i.splice.apply(i,[e,0].concat(t));for(var a=e+r,h=i.length;a<h;a++)i[a]._index=a}if(n){var u=this._countCurves(),l=e>0&&e+r-1===u?e-1:e,c=l,d=Math.min(l+r,u);t._curves&&(n.splice.apply(n,[l,0].concat(t._curves)),c+=t._curves.length);for(var a=c;a<d;a++)n.splice(a,0,new z(this,null,null));this._adjustCurves(l,d)}return this._changed(25),t},_adjustCurves:function(t,e){for(var i,n=this._segments,r=this._curves,s=t;s<e;s++)i=r[s],i._path=this,i._segment1=n[s],i._segment2=n[s+1]||n[0],i._changed();(i=r[this._closed&&0===t?n.length-1:t-1])&&(i._segment2=n[t]||n[0],i._changed()),(i=r[e])&&(i._segment1=n[e],i._changed())},_countCurves:function(){var t=this._segments.length;return!this._closed&&t>0?t-1:t},add:function(t){return arguments.length>1&&"number"!=typeof t?this._add(T.readAll(arguments)):this._add([T.read(arguments)])[0]},insert:function(t,e){return arguments.length>2&&"number"!=typeof e?this._add(T.readAll(arguments,1),t):this._add([T.read(arguments,1)],t)[0]},addSegment:function(){return this._add([T.read(arguments)])[0]},insertSegment:function(t){return this._add([T.read(arguments,1)],t)[0]},addSegments:function(t){return this._add(T.readAll(t))},insertSegments:function(t,e){return this._add(T.readAll(e),t)},removeSegment:function(t){return this.removeSegments(t,t+1)[0]||null},removeSegments:function(t,e,i){t=t||0,e=r.pick(e,this._segments.length);var n=this._segments,s=this._curves,a=n.length,o=n.splice(t,e-t),h=o.length;if(!h)return o;for(var u=0;u<h;u++){var l=o[u];l._selection&&this._updateSelection(l,l._selection,0),l._index=l._path=null}for(var u=t,c=n.length;u<c;u++)n[u]._index=u;if(s){for(var d=t>0&&e===a+(this._closed?1:0)?t-1:t,s=s.splice(d,h),u=s.length-1;u>=0;u--)s[u]._path=null;i&&(o._curves=s.slice(1)),this._adjustCurves(d,d)}return this._changed(25),o},clear:"#removeSegments",hasHandles:function(){for(var t=this._segments,e=0,i=t.length;e<i;e++)if(t[e].hasHandles())return!0;return!1},clearHandles:function(){for(var t=this._segments,e=0,i=t.length;e<i;e++)t[e].clearHandles()},getLength:function(){if(null==this._length){for(var t=this.getCurves(),e=0,i=0,n=t.length;i<n;i++)e+=t[i].getLength();this._length=e}return this._length},getArea:function(t){var i=t===e,n=this._area;if(!i||null==n){var r=this._segments,s=r.length,a=i?this._closed:t,o=s-1;n=0;for(var h=0,u=a?s:o;h<u;h++)n+=z.getArea(z.getValues(r[h],r[h<o?h+1:0]));i&&(this._area=n)}return n},isClockwise:function(){return this._clockwise!==e?this._clockwise:this.getArea()>=0},setClockwise:function(t){this.isClockwise()!=(t=!!t)&&this.reverse(),this._clockwise=t},isFullySelected:function(){var t=this._segments.length;return this.isSelected()&&t>0&&this._segmentSelection===7*t},setFullySelected:function(t){t&&this._selectSegments(!0),this.setSelected(t)},setSelection:function vt(t){1&t||this._selectSegments(!1),vt.base.call(this,t)},_selectSegments:function(t){var e=this._segments,i=e.length,n=t?7:0;this._segmentSelection=n*i;for(var r=0;r<i;r++)e[r]._selection=n},_updateSelection:function(t,e,i){t._selection=i;var n=this._segmentSelection+=i-e;n>0&&this.setSelected(!0)},splitAt:function(t){var e="number"==typeof t?this.getLocationAt(t):t,i=e&&e.index,n=e&&e.time,r=4e-7,s=1-r;n>=s&&(i++,n=0);var a=this.getCurves();if(i>=0&&i<a.length){n>=r&&a[i++].divideAtTime(n);var o,h=this.removeSegments(i,this._segments.length,!0);return this._closed?(this.setClosed(!1),o=this):(o=new L(w.NO_INSERT),o.insertAbove(this,!0),o.copyAttributes(this)),o._add(h,0),this.addSegment(h[0]),o}return null},split:function(t,i){var n,r=i===e?t:(n=this.getCurves()[t])&&n.getLocationAtTime(i);return null!=r?this.splitAt(r):null},join:function(t,e){var i=e||0;if(t&&t!==this){var n=t._segments,r=this.getLastSegment(),s=t.getLastSegment();if(!s)return this;r&&r._point.isClose(s._point,i)&&t.reverse();var a=t.getFirstSegment();if(r&&r._point.isClose(a._point,i))r.setHandleOut(a._handleOut),this._add(n.slice(1));else{var o=this.getFirstSegment();o&&o._point.isClose(a._point,i)&&t.reverse(),s=t.getLastSegment(),o&&o._point.isClose(s._point,i)?(o.setHandleIn(s._handleIn),this._add(n.slice(0,n.length-1),0)):this._add(n.slice())}t._closed&&this._add([n[0]]),t.remove()}var h=this.getFirstSegment(),u=this.getLastSegment();return h!==u&&h._point.isClose(u._point,i)&&(h.setHandleIn(u._handleIn),u.remove(),this.setClosed(!0)),this},reduce:function(t){for(var e=this.getCurves(),i=t&&t.simplify,n=i?2e-7:0,r=e.length-1;r>=0;r--){var s=e[r];!s.hasHandles()&&(s.getLength()<n||i&&s.isCollinear(s.getNext()))&&s.remove()}return this},reverse:function(){this._segments.reverse();for(var t=0,i=this._segments.length;t<i;t++){var n=this._segments[t],r=n._handleIn;n._handleIn=n._handleOut,n._handleOut=r,n._index=t}this._curves=null,this._clockwise!==e&&(this._clockwise=!this._clockwise),this._changed(9)},flatten:function(t){for(var e=new B(this,t||.25,256,(!0)),i=e.parts,n=i.length,r=[],s=0;s<n;s++)r.push(new T(i[s].curve.slice(0,2)));!this._closed&&n>0&&r.push(new T(i[n-1].curve.slice(6))),this.setSegments(r)},simplify:function(t){var e=new E(this).fit(t||2.5);return e&&this.setSegments(e),!!e},smooth:function(t){function i(t,e){var i=t&&t.index;if(null!=i){var r=t.path;if(r&&r!==n)throw new Error(t._class+" "+i+" of "+r+" is not part of "+n);e&&t instanceof z&&i++}else i="number"==typeof t?t:e;return Math.min(i<0&&h?i%o:i<0?i+o:i,o-1)}var n=this,r=t||{},s=r.type||"asymmetric",a=this._segments,o=a.length,h=this._closed,u=h&&r.from===e&&r.to===e,l=i(r.from,0),c=i(r.to,o-1);if(l>c)if(h)l-=o;else{var d=l;l=c,c=d}if(/^(?:asymmetric|continuous)$/.test(s)){var f="asymmetric"===s,_=Math.min,g=c-l+1,v=g-1,p=u?_(g,4):1,m=p,y=p,w=[];if(h||(m=_(1,l),y=_(1,o-c-1)),v+=m+y,v<=1)return;for(var x=0,b=l-m;x<=v;x++,b++)w[x]=a[(b<0?b+o:b)%o]._point;for(var C=w[0]._x+2*w[1]._x,S=w[0]._y+2*w[1]._y,P=2,I=v-1,M=[C],T=[S],k=[P],O=[],A=[],x=1;x<v;x++){var L=x<I,N=L?1:f?1:2,B=L?4:f?2:7,E=L?4:f?3:8,D=L?2:f?0:1,j=N/P;P=k[x]=B-j,C=M[x]=E*w[x]._x+D*w[x+1]._x-j*C,S=T[x]=E*w[x]._y+D*w[x+1]._y-j*S}O[I]=M[I]/k[I],A[I]=T[I]/k[I];for(var x=v-2;x>=0;x--)O[x]=(M[x]-O[x+1])/k[x],A[x]=(T[x]-A[x+1])/k[x];O[v]=(3*w[v]._x-O[I])/2,A[v]=(3*w[v]._y-A[I])/2;for(var x=m,F=v-y,b=l;x<=F;x++,b++){var R=a[b<0?b+o:b],q=R._point,V=O[x]-q._x,H=A[x]-q._y;(u||x<F)&&R.setHandleOut(V,H),(u||x>m)&&R.setHandleIn(-V,-H)}}else for(var x=l;x<=c;x++)a[x<0?x+o:x].smooth(r,!u&&x===l,!u&&x===c)},toShape:function(t){function i(t,e){var i=c[t],n=i.getNext(),r=c[e],s=r.getNext();return i._handleOut.isZero()&&n._handleIn.isZero()&&r._handleOut.isZero()&&s._handleIn.isZero()&&n._point.subtract(i._point).isCollinear(s._point.subtract(r._point))}function n(t){var e=c[t],i=e.getPrevious(),n=e.getNext();return i._handleOut.isZero()&&e._handleIn.isZero()&&e._handleOut.isZero()&&n._handleIn.isZero()&&e._point.subtract(i._point).isOrthogonal(n._point.subtract(e._point))}function r(t){var e=c[t],i=e.getNext(),n=e._handleOut,r=i._handleIn,s=.5522847498307936;if(n.isOrthogonal(r)){var a=e._point,o=i._point,h=new m(a,n,(!0)).intersect(new m(o,r,(!0)),!0);return h&&u.isZero(n.getLength()/h.subtract(a).getLength()-s)&&u.isZero(r.getLength()/h.subtract(o).getLength()-s)}return!1}function s(t,e){return c[t]._point.getDistance(c[e]._point)}if(!this._closed)return null;var a,o,h,l,c=this._segments;if(!this.hasHandles()&&4===c.length&&i(0,2)&&i(1,3)&&n(1)?(a=C.Rectangle,o=new f(s(0,3),s(0,1)),l=c[1]._point.add(c[2]._point).divide(2)):8===c.length&&r(0)&&r(2)&&r(4)&&r(6)&&i(1,5)&&i(3,7)?(a=C.Rectangle,o=new f(s(1,6),s(0,3)),h=o.subtract(new f(s(0,7),s(1,2))).divide(2),l=c[3]._point.add(c[4]._point).divide(2)):4===c.length&&r(0)&&r(1)&&r(2)&&r(3)&&(u.isZero(s(0,2)-s(1,3))?(a=C.Circle,h=s(0,2)/2):(a=C.Ellipse,h=new f(s(2,0)/2,s(3,1)/2)),l=c[1]._point),a){var d=this.getPosition(!0),_=new a({center:d,size:o,radius:h,insert:!1});return _.copyAttributes(this,!0),_._matrix.prepend(this._matrix),_.rotate(l.subtract(d).getAngle()+90),(t===e||t)&&_.insertAbove(this),_}return null},toPath:"#clone",_hitTestSelf:function(t,e,i,n){function r(e,i){return t.subtract(e).divide(i).length<=1}function s(t,i,n){if(!e.selected||i.isSelected()){var s=t._point;if(i!==s&&(i=i.add(s)),r(i,x))return new M(n,g,{segment:t,point:i})}}function a(t,i){return(i||e.segments)&&s(t,t._point,"segment")||!i&&e.handles&&(s(t,t._handleIn,"handle-in")||s(t,t._handleOut,"handle-out"))}function o(t){d.add(t)}function h(e){if(("round"!==u||"round"!==l)&&(d=new L({internal:!0,closed:!0}),y||e._index>0&&e._index<m-1?"round"!==u&&(e._handleIn.isZero()||e._handleOut.isZero())&&L._addBevelJoin(e,u,P,c,null,n,o,!0):"round"!==l&&L._addSquareCap(e,l,P,null,n,o,!0),!d.isEmpty())){var i;return d.contains(t)||(i=d.getNearestLocation(t))&&r(i.getPoint(),w)}return r(e._point,x)}var u,l,c,d,f,_,g=this,v=this.getStyle(),p=this._segments,m=p.length,y=this._closed,w=e._tolerancePadding,x=w,b=e.stroke&&v.hasStroke(),C=e.fill&&v.hasFill(),S=e.curves,P=b?v.getStrokeWidth()/2:C&&e.tolerance>0||S?0:null;if(null!==P&&(P>0?(u=v.getStrokeJoin(),l=v.getStrokeCap(),c=P*v.getMiterLimit(),x=x.add(L._getStrokePadding(P,n))):u=l="round"),!e.ends||e.segments||y){if(e.segments||e.handles)for(var I=0;I<m;I++)if(_=a(p[I]))return _}else if(_=a(p[0],!0)||a(p[m-1],!0))return _;if(null!==P){if(f=this.getNearestLocation(t)){var T=f.getTime();0===T||1===T&&m>1?h(f.getSegment())||(f=null):r(f.getPoint(),x)||(f=null)}if(!f&&"miter"===u&&m>1)for(var I=0;I<m;I++){var k=p[I];if(t.getDistance(k._point)<=c&&h(k)){f=k.getLocation();break}}}return!f&&C&&this._contains(t)||f&&!b&&!S?new M("fill",this):f?new M(b?"stroke":"curve",this,{location:f,point:f.getPoint()}):null}},r.each(z._evaluateMethods,function(t){this[t+"At"]=function(e){var i=this.getLocationAt(e);return i&&i[t]()}},{beans:!1,getLocationOf:function(){for(var t=c.read(arguments),e=this.getCurves(),i=0,n=e.length;i<n;i++){var r=e[i].getLocationOf(t);if(r)return r}return null},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getLocationAt:function(t){for(var e=this.getCurves(),i=0,n=0,r=e.length;n<r;n++){var s=i,a=e[n];if(i+=a.getLength(),i>t)return a.getLocationAt(t-s)}return e.length>0&&t<=this.getLength()?new O(e[e.length-1],1):null}}),new function(){function t(t,e,i,n){function r(e){var i=h[e],n=h[e+1];s==i&&a==n||(t.beginPath(),t.moveTo(s,a),t.lineTo(i,n),t.stroke(),t.beginPath(),t.arc(i,n,o,0,2*Math.PI,!0),t.fill())}for(var s,a,o=n/2,h=new Array(6),u=0,l=e.length;u<l;u++){var c=e[u],d=c._selection;if(c._transformCoordinates(i,h),s=h[0],a=h[1],2&d&&r(2),4&d&&r(4),t.fillRect(s-o,a-o,n,n),!(1&d)){var f=t.fillStyle;t.fillStyle="#ffffff",t.fillRect(s-o+1,a-o+1,n-2,n-2),t.fillStyle=f}}}function e(t,e,i){function n(e){if(i)e._transformCoordinates(i,_),r=_[0],s=_[1];else{var n=e._point;r=n._x,s=n._y}if(g)t.moveTo(r,s),g=!1;else{if(i)h=_[2],u=_[3];else{var d=e._handleIn;h=r+d._x,u=s+d._y}h===r&&u===s&&l===a&&c===o?t.lineTo(r,s):t.bezierCurveTo(l,c,h,u,r,s)}if(a=r,o=s,i)l=_[4],c=_[5];else{var d=e._handleOut;l=a+d._x,c=o+d._y}}for(var r,s,a,o,h,u,l,c,d=e._segments,f=d.length,_=new Array(6),g=!0,v=0;v<f;v++)n(d[v]);e._closed&&f>0&&n(d[0])}return{_draw:function(t,i,n,r){function s(t){return c[(t%d+d)%d]}var a=i.dontStart,o=i.dontFinish||i.clip,h=this.getStyle(),u=h.hasFill(),l=h.hasStroke(),c=h.getDashArray(),d=!paper.support.nativeDash&&l&&c&&c.length;if(a||t.beginPath(),(u||l&&!d||o)&&(e(t,this,r),this._closed&&t.closePath()),!o&&(u||l)&&(this._setStyles(t,i,n),u&&(t.fill(h.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),l)){if(d){a||t.beginPath();var f,_=new B(this,.25,32,(!1),r),g=_.length,v=-h.getDashOffset(),p=0;for(v%=g;v>0;)v-=s(p--)+s(p--);for(;v<g;)f=v+s(p++),(v>0||f>0)&&_.drawPart(t,Math.max(v,0),Math.max(f,0)),v=f+s(p++)}t.stroke()}},_drawSelected:function(i,n){i.beginPath(),e(i,this,n),i.stroke(),t(i,this._segments,n,paper.settings.handleSize)}}},new function(){function t(t){var e=t._segments;if(0===e.length)throw new Error("Use a moveTo() command first");return e[e.length-1]}return{moveTo:function(){var t=this._segments;1===t.length&&this.removeSegment(0),t.length||this._add([new T(c.read(arguments))])},moveBy:function(){throw new Error("moveBy() is unsupported on Path items.")},lineTo:function(){this._add([new T(c.read(arguments))])},cubicCurveTo:function(){var e=c.read(arguments),i=c.read(arguments),n=c.read(arguments),r=t(this);r.setHandleOut(e.subtract(r._point)),this._add([new T(n,i.subtract(n))])},quadraticCurveTo:function(){var e=c.read(arguments),i=c.read(arguments),n=t(this)._point;this.cubicCurveTo(e.add(n.subtract(e).multiply(1/3)),e.add(i.subtract(e).multiply(1/3)),i)},curveTo:function(){var e=c.read(arguments),i=c.read(arguments),n=r.pick(r.read(arguments),.5),s=1-n,a=t(this)._point,o=e.subtract(a.multiply(s*s)).subtract(i.multiply(n*n)).divide(2*n*s);if(o.isNaN())throw new Error("Cannot put a curve through points with parameter = "+n);this.quadraticCurveTo(o,i)},arcTo:function(){var e,i,n,s,a,o=t(this),h=o._point,l=c.read(arguments),d=r.peek(arguments),_=r.pick(d,!0);if("boolean"==typeof _)var g=h.add(l).divide(2),e=g.add(g.subtract(h).rotate(_?-90:90));else if(r.remain(arguments)<=2)e=l,l=c.read(arguments);else{var v=f.read(arguments),y=u.isZero;if(y(v.width)||y(v.height))return this.lineTo(l);var w=r.read(arguments),_=!!r.read(arguments),x=!!r.read(arguments),g=h.add(l).divide(2),b=h.subtract(g).rotate(-w),C=b.x,S=b.y,P=Math.abs,I=P(v.width),M=P(v.height),k=I*I,z=M*M,O=C*C,A=S*S,L=Math.sqrt(O/k+A/z);if(L>1&&(I*=L,M*=L,k=I*I,z=M*M),L=(k*z-k*A-z*O)/(k*A+z*O),P(L)<1e-12&&(L=0),L<0)throw new Error("Cannot create an arc with the given arguments");i=new c(I*S/M,-M*C/I).multiply((x===_?-1:1)*Math.sqrt(L)).rotate(w).add(g),a=(new p).translate(i).rotate(w).scale(I,M),s=a._inverseTransform(h),n=s.getDirectedAngle(a._inverseTransform(l)),!_&&n>0?n-=360:_&&n<0&&(n+=360)}if(e){var N=new m(h.add(e).divide(2),e.subtract(h).rotate(90),(!0)),B=new m(e.add(l).divide(2),l.subtract(e).rotate(90),(!0)),E=new m(h,l),D=E.getSide(e);if(i=N.intersect(B,!0),!i){if(!D)return this.lineTo(l);throw new Error("Cannot create an arc with the given arguments")}s=h.subtract(i),n=s.getDirectedAngle(l.subtract(i));var j=E.getSide(i);0===j?n=D*Math.abs(n):D===j&&(n+=n<0?360:-360)}for(var F=Math.abs(n),R=F>=360?4:Math.ceil(F/90),q=n/R,V=q*Math.PI/360,H=4/3*Math.sin(V)/(1+Math.cos(V)),Z=[],U=0;U<=R;U++){var b=l,W=null;if(U<R&&(W=s.rotate(90).multiply(H),a?(b=a._transformPoint(s),W=a._transformPoint(s.add(W)).subtract(b)):b=i.add(s)),0===U)o.setHandleOut(W);else{var G=s.rotate(-90).multiply(H);a&&(G=a._transformPoint(s.add(G)).subtract(b)),Z.push(new T(b,G,W))}s=s.rotate(q)}this._add(Z)},lineBy:function(){var e=c.read(arguments),i=t(this)._point;this.lineTo(i.add(e))},curveBy:function(){var e=c.read(arguments),i=c.read(arguments),n=r.read(arguments),s=t(this)._point;this.curveTo(s.add(e),s.add(i),n)},cubicCurveBy:function(){var e=c.read(arguments),i=c.read(arguments),n=c.read(arguments),r=t(this)._point;this.cubicCurveTo(r.add(e),r.add(i),r.add(n))},quadraticCurveBy:function(){var e=c.read(arguments),i=c.read(arguments),n=t(this)._point;this.quadraticCurveTo(n.add(e),n.add(i))},arcBy:function(){var e=t(this)._point,i=e.add(c.read(arguments)),n=r.pick(r.peek(arguments),!0);"boolean"==typeof n?this.arcTo(i,n):this.arcTo(i,e.add(c.read(arguments)))},closePath:function(t){this.setClosed(!0),this.join(this,t)}}},{_getBounds:function(t,e){var i=e.handle?"getHandleBounds":e.stroke?"getStrokeBounds":"getBounds";return L[i](this._segments,this._closed,this,t,e)},statics:{getBounds:function(t,e,i,n,r,s){function a(t){t._transformCoordinates(n,h);for(var e=0;e<2;e++)z._addBounds(u[e],u[e+4],h[e+2],h[e],e,s?s[e]:0,l,c,d);var i=u;u=h,h=i}var o=t[0];if(!o)return new g;for(var h=new Array(6),u=o._transformCoordinates(n,new Array(6)),l=u.slice(0,2),c=l.slice(),d=new Array(2),f=1,_=t.length;f<_;f++)a(t[f]);return e&&a(o),new g(l[0],l[1],c[0]-l[0],c[1]-l[1])},getStrokeBounds:function(t,e,i,n,r){function s(t){v=v.include(t)}function a(t){v=v.unite(x.setCenter(t._point.transform(n)))}function o(t,e){var i=t._handleIn,r=t._handleOut;"round"===e||!i.isZero()&&!r.isZero()&&i.isCollinear(r)?a(t):L._addBevelJoin(t,e,p,w,n,d,s)}function h(t,e){"round"===e?a(t):L._addSquareCap(t,e,p,n,d,s)}var u=i.getStyle(),l=u.hasStroke(),c=u.getStrokeWidth(),d=l&&i._getStrokeMatrix(n,r),_=l&&L._getStrokePadding(c,d),v=L.getBounds(t,e,i,n,r,_);if(!l)return v;for(var p=c/2,m=u.getStrokeJoin(),y=u.getStrokeCap(),w=p*u.getMiterLimit(),x=new g(new f(_)),b=t.length-(e?0:1),C=1;C<b;C++)o(t[C],m);return e?o(t[0],m):b>0&&(h(t[0],y),h(t[t.length-1],y)),v},_getStrokePadding:function(t,e){if(!e)return[t,t];
-var i=new c(t,0).transform(e),n=new c(0,t).transform(e),r=i.getAngleInRadians(),s=i.getLength(),a=n.getLength(),o=Math.sin(r),h=Math.cos(r),u=Math.tan(r),l=Math.atan2(a*u,s),d=Math.atan2(a,u*s);return[Math.abs(s*Math.cos(l)*h+a*Math.sin(l)*o),Math.abs(a*Math.sin(d)*h+s*Math.cos(d)*o)]},_addBevelJoin:function(t,e,i,n,r,s,a,o){var h=t.getCurve(),u=h.getPrevious(),l=h.getPointAtTime(0),d=u.getNormalAtTime(1),f=h.getNormalAtTime(0),_=d.getDirectedAngle(f)<0?-i:i;if(d.setLength(_),f.setLength(_),r&&r._transformPoint(l,l),s&&(s._transformPoint(d,d),s._transformPoint(f,f)),o&&(a(l),a(l.add(d))),"miter"===e){var g=new m(l.add(d),new c((-d.y),d.x),(!0)).intersect(new m(l.add(f),new c((-f.y),f.x),(!0)),!0);if(g&&l.getDistance(g)<=n&&(a(g),!o))return}o||a(l.add(d)),a(l.add(f))},_addSquareCap:function(t,e,i,n,r,s,a){var o=t._point,h=t.getLocation(),u=h.getNormal().multiply(i);n&&n._transformPoint(o,o),r&&r._transformPoint(u,u),a&&(s(o.subtract(u)),s(o.add(u))),"square"===e&&(o=o.add(u.rotate(0===h.getTime()?-90:90))),s(o.add(u)),s(o.subtract(u))},getHandleBounds:function(t,e,i,n,r){var s,a,o=i.getStyle(),h=r.stroke&&o.hasStroke();if(h){var u=i._getStrokeMatrix(n,r),l=o.getStrokeWidth()/2,c=l;"miter"===o.getStrokeJoin()&&(c=l*o.getMiterLimit()),"square"===o.getStrokeCap()&&(c=Math.max(c,l*Math.sqrt(2))),s=L._getStrokePadding(l,u),a=L._getStrokePadding(c,u)}for(var d=new Array(6),f=1/0,_=-f,v=f,p=_,m=0,y=t.length;m<y;m++){var w=t[m];w._transformCoordinates(n,d);for(var x=0;x<6;x+=2){var b=0===x?a:s,C=b?b[0]:0,S=b?b[1]:0,P=d[x],I=d[x+1],M=P-C,T=P+C,k=I-S,z=I+S;M<f&&(f=M),T>_&&(_=T),k<v&&(v=k),z>p&&(p=z)}}return new g(f,v,_-f,p-v)}}});L.inject({statics:new function(){function t(t,e,i){var n=r.getNamed(i),s=new L(n&&n.insert===!1&&w.NO_INSERT);return s._add(t),s._closed=e,s.set(n)}function e(e,i,r){for(var s=new Array(4),a=0;a<4;a++){var o=n[a];s[a]=new T(o._point.multiply(i).add(e),o._handleIn.multiply(i),o._handleOut.multiply(i))}return t(s,!0,r)}var i=.5522847498307936,n=[new T([-1,0],[0,i],[0,-i]),new T([0,-1],[-i,0],[i,0]),new T([1,0],[0,-i],[0,i]),new T([0,1],[i,0],[-i,0])];return{Line:function(){return t([new T(c.readNamed(arguments,"from")),new T(c.readNamed(arguments,"to"))],!1,arguments)},Circle:function(){var t=c.readNamed(arguments,"center"),i=r.readNamed(arguments,"radius");return e(t,new f(i),arguments)},Rectangle:function(){var e,n=g.readNamed(arguments,"rectangle"),r=f.readNamed(arguments,"radius",0,{readNull:!0}),s=n.getBottomLeft(!0),a=n.getTopLeft(!0),o=n.getTopRight(!0),h=n.getBottomRight(!0);if(!r||r.isZero())e=[new T(s),new T(a),new T(o),new T(h)];else{r=f.min(r,n.getSize(!0).divide(2));var u=r.width,l=r.height,c=u*i,d=l*i;e=[new T(s.add(u,0),null,[-c,0]),new T(s.subtract(0,l),[0,d]),new T(a.add(0,l),null,[0,-d]),new T(a.add(u,0),[-c,0],null),new T(o.subtract(u,0),null,[c,0]),new T(o.add(0,l),[0,-d],null),new T(h.subtract(0,l),null,[0,d]),new T(h.subtract(u,0),[c,0])]}return t(e,!0,arguments)},RoundRectangle:"#Rectangle",Ellipse:function(){var t=C._readEllipse(arguments);return e(t.center,t.radius,arguments)},Oval:"#Ellipse",Arc:function(){var t=c.readNamed(arguments,"from"),e=c.readNamed(arguments,"through"),i=c.readNamed(arguments,"to"),n=r.getNamed(arguments),s=new L(n&&n.insert===!1&&w.NO_INSERT);return s.moveTo(t),s.arcTo(e,i),s.set(n)},RegularPolygon:function(){for(var e=c.readNamed(arguments,"center"),i=r.readNamed(arguments,"sides"),n=r.readNamed(arguments,"radius"),s=360/i,a=i%3===0,o=new c(0,a?-n:n),h=a?-1:.5,u=new Array(i),l=0;l<i;l++)u[l]=new T(e.add(o.rotate((l+h)*s)));return t(u,!0,arguments)},Star:function(){for(var e=c.readNamed(arguments,"center"),i=2*r.readNamed(arguments,"points"),n=r.readNamed(arguments,"radius1"),s=r.readNamed(arguments,"radius2"),a=360/i,o=new c(0,(-1)),h=new Array(i),u=0;u<i;u++)h[u]=new T(e.add(o.rotate(a*u).multiply(u%2?s:n)));return t(h,!0,arguments)}}}});var N=A.extend({_class:"CompoundPath",_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||("string"==typeof t?this.setPathData(t):this.addChildren(Array.isArray(t)?t:arguments))},insertChildren:function pt(t,i,n){for(var r=i.length-1;r>=0;r--){var s=i[r];s instanceof N&&(i=i.slice(),i.splice.apply(i,[r,1].concat(s.removeChildren())),s.remove())}i=pt.base.call(this,t,i,n,L);for(var r=0,a=!n&&i&&i.length;r<a;r++){var s=i[r];s._clockwise===e&&s.setClockwise(0===s._index)}return i},reduce:function mt(t){for(var e=this._children,i=e.length-1;i>=0;i--){var n=e[i].reduce(t);n.isEmpty()&&n.remove()}if(0===e.length){var n=new L(w.NO_INSERT);return n.copyAttributes(this),n.insertAbove(this),this.remove(),n}return mt.base.call(this)},isClockwise:function(){var t=this.getFirstChild();return t&&t.isClockwise()},setClockwise:function(t){this.isClockwise()^!!t&&this.reverse()},getFirstSegment:function(){var t=this.getFirstChild();return t&&t.getFirstSegment()},getLastSegment:function(){var t=this.getLastChild();return t&&t.getLastSegment()},getCurves:function(){for(var t=this._children,e=[],i=0,n=t.length;i<n;i++)e.push.apply(e,t[i].getCurves());return e},getFirstCurve:function(){var t=this.getFirstChild();return t&&t.getFirstCurve()},getLastCurve:function(){var t=this.getLastChild();return t&&t.getFirstCurve()},getArea:function(){for(var t=this._children,e=0,i=0,n=t.length;i<n;i++)e+=t[i].getArea();return e}},{beans:!0,getPathData:function(t,e){for(var i=this._children,n=[],r=0,s=i.length;r<s;r++){var a=i[r],o=a._matrix;n.push(a.getPathData(t&&!o.isIdentity()?t.appended(o):t,e))}return n.join(" ")}},{_hitTestChildren:function yt(t,e,i){return yt.base.call(this,t,e["class"]===L||"path"===e.type?e:r.set({},e,{fill:!1}),i)},_draw:function(t,e,i,n){var r=this._children;if(0!==r.length){e=e.extend({dontStart:!0,dontFinish:!0}),t.beginPath();for(var s=0,a=r.length;s<a;s++)r[s].draw(t,e,n);if(!e.clip){this._setStyles(t,e,i);var o=this._style;o.hasFill()&&(t.fill(o.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),o.hasStroke()&&t.stroke()}}},_drawSelected:function(t,e,i){for(var n=this._children,r=0,s=n.length;r<s;r++){var a=n[r],o=a._matrix;i[a._id]||a._drawSelected(t,o.isIdentity()?e:e.appended(o))}}},new function(){function t(t,e){var i=t._children;if(e&&0===i.length)throw new Error("Use a moveTo() command first");return i[i.length-1]}return r.each(["lineTo","cubicCurveTo","quadraticCurveTo","curveTo","arcTo","lineBy","cubicCurveBy","quadraticCurveBy","curveBy","arcBy"],function(e){this[e]=function(){var i=t(this,!0);i[e].apply(i,arguments)}},{moveTo:function(){var e=t(this),i=e&&e.isEmpty()?e:new L(w.NO_INSERT);i!==e&&this.addChild(i),i.moveTo.apply(i,arguments)},moveBy:function(){var e=t(this,!0),i=e&&e.getLastSegment(),n=c.read(arguments);this.moveTo(i?n.add(i._point):n)},closePath:function(e){t(this,!0).closePath(e)}})},r.each(["reverse","flatten","simplify","smooth"],function(t){this[t]=function(e){for(var i,n=this._children,r=0,s=n.length;r<s;r++)i=n[r][t](e)||i;return i}},{}));A.inject(new function(){function t(t,e){var i=t.clone(!1).reduce({simplify:!0}).transform(null,!0,!0);return e?i.resolveCrossings():i}function e(t,e,i,n,r){var s=new t(w.NO_INSERT);return s.addChildren(e,!0),i&&(s=s.reduce({simplify:!0})),s.insertAbove(r&&n.isSibling(r)&&n.getIndex()<r.getIndex()?r:n),s.copyAttributes(n,!0),s}function i(i,r,s){function o(t){for(var e=0,i=t.length;e<i;e++){var n=t[e];g.push.apply(g,n._segments),v.push.apply(v,n._getMonoCurves()),n._overlapsOnly=n._validOverlapsOnly=!0}}var u=d[s];if(u[s]=!0,!i._children&&!i._closed)return n(i,r,u);var c=t(i,!0),f=r&&i!==r&&t(r,!0);f&&(u.subtract||u.exclude)^(f.isClockwise()^c.isClockwise())&&f.reverse();var _=a(O.expand(c.getCrossings(f))),g=[],v=[];o(c._children||[c]),f&&o(f._children||[f]);for(var p=0,m=_.length;p<m;p++)h(_[p]._segment,c,f,v,u);for(var p=0,m=g.length;p<m;p++){var y=g[p],w=y._intersection;if(null==y._winding&&h(y,c,f,v,u),!w||!w._overlap){var x=y._path;x._overlapsOnly=!1,u[y._winding]&&(x._validOverlapsOnly=!1)}}return e(N,l(g,u),!0,i,r)}function n(i,n,r){function s(t){if(o.contains(t.getPointAt(t.getLength()/2))^u)return l.unshift(t),!0}if(!n||!n._children&&!n._closed||!r.subtract&&!r.intersect)return null;for(var a=t(i,!1),o=t(n,!1),h=a.getCrossings(o),u=r.subtract,l=[],c=h.length-1;c>=0;c--){var d=h[c].split();d&&(s(d)&&d.getFirstSegment().setHandleIn(0,0),a.getLastSegment().setHandleOut(0,0))}return s(a),e(x,l,!1,i,n)}function s(t,e){for(var i=t;i;){if(i===e)return;i=i._previous}for(;t._next&&t._next!==e;)t=t._next;if(!t._next){for(;e._previous;)e=e._previous;t._next=e,e._previous=t}}function a(t,e){for(var i,n,r=e&&[],a=4e-7,o=1-a,h=!1,u=[],l=t.length-1;l>=0;l--){var c=t[l];if(e){if(!e(c))continue;r.unshift(c)}var d,f=c._curve,_=c._time,g=_;if(f!==i?h=!f.hasHandles():n>=a&&n<=o&&(_/=n),_<a)d=f._segment1;else if(_>o)d=f._segment2;else{var v=f.divideAtTime(_,!0);h&&u.push(f,v),d=v._segment1}c._setSegment(d);var p=d._intersection,m=c._intersection;if(p){s(p,m);for(var y=p;y;)s(y._intersection,p),y=y._next}else d._intersection=m;i=f,n=g}for(var l=0,w=u.length;l<w;l++)u[l].clearHandles();return r||t}function o(t,e,i){var n=2e-7,r=t.x,s=t.y,a=0,h=0,u=e.length,l=[],d=Math.abs;if(i){for(var f=-(1/0),_=1/0,g=s-n,v=s+n,p=0;p<u;p++)for(var m=e[p].values,y=z.solveCubic(m,0,r,l,0,1),w=y-1;w>=0;w--){var x=z.getPoint(m,l[w]).y;x<g&&x>f?f=x:x>v&&x<_&&(_=x)}f=(f+s)/2,_=(_+s)/2,f>-(1/0)&&(a=o(new c(r,f),e).winding),_<1/0&&(h=o(new c(r,_),e).winding)}else{for(var b,C,S=r-n,P=r+n,I=0,M=0,T=!1,p=0;p<u;p++){var k=e[p],O=k.winding,m=k.values,A=m[1],L=m[7];if(k.last&&(b=k.last.winding,C=k.last.values[6],T=!1),s>=A&&s<=L||s>=L&&s<=A)if(O){var N=s===A?m[0]:s===L?m[6]:1===z.solveCubic(m,1,s,l,0,1)?z.getPoint(m,l[0]).x:null;null!=N&&(N>=S&&N<=P?T=!0:s===A&&O===b||s===A&&(r-N)*(r-C)<0||(N<S?a+=O:N>P&&(h+=O))),b=O,C=m[6]}else(r-m[0])*(r-m[6])<=0&&(T=!0);T&&(p>=u-1||e[p+1].last)&&(I+=1,M-=1)}0===a&&0===h&&(a=I,h=M)}return{winding:Math.max(d(a),d(h)),contour:!a^!h}}function h(t,e,i,n,r){var s,a=[],h=t,u=0;do{var l=t.getCurve(),c=l.getLength();a.push({segment:t,curve:l,length:c}),u+=c,t=t.getNext()}while(t&&!t._intersection&&t!==h);for(var c=u/2,d=0,f=a.length;d<f;d++){var _=a[d],g=_.length;if(c<=g){var l=_.curve,v=l._path,p=v._parent,m=l.getTimeAt(c),y=l.getPointAtTime(m),w=Math.abs(l.getTangentAtTime(m).y)<1e-7;p instanceof N&&(v=p),s=r.subtract&&i&&(v===e&&i._getWinding(y,w)||v===i&&!e._getWinding(y,w))?{winding:0}:o(y,n,w);break}c-=g}for(var d=a.length-1;d>=0;d--){var x=a[d].segment;x._winding=s.winding,x._contour=s.contour}}function l(t,e){function i(t,i){return!(!t||t._visited||!(!e||e[t._winding]||!i&&e.unite&&t._contour))}function n(t){return t===a||t===o}function s(t,r){if(!t._next)return t;for(;t;){var s=t._segment,a=s.getNext(),o=a&&a._intersection;if(s!==r&&(n(s)||n(a)||!s._visited&&!a._visited&&(!e||i(s)&&(i(a)||o&&i(o._segment)))))return t;t=t._next}return null}for(var a,o,h=[],l=0,c=t.length;l<c;l++){var d,f=null,_=!1,g=t[l],v=g._intersection;if(!g._visited&&g._path._overlapsOnly){var p=g._path,m=v._segment._path,y=p._segments,x=m._segments;if(r.equals(y,x)){(e.unite||e.intersect)&&p.getArea()&&h.push(p.clone(!1));for(var b=0,C=y.length;b<C;b++)y[b]._visited=x[b]._visited=!0}}if(i(g,!0)&&(g._path._validOverlapsOnly||!v||!v._overlap)){for(a=o=null;;){v=v&&s(v,g)||v;var S=v&&v._segment;if(n(g)?_=!0:S&&(n(S)?(_=!0,g=S):i(S,i(g,!0))&&(e&&(e.intersect||e.subtract)&&(g._visited=!0),g=S)),_||g._visited){g._visited=!0;break}if(g._path._validOverlapsOnly&&!i(g))break;f||(f=new L(w.NO_INSERT),a=g,o=S);var P=g.getNext();f.add(new T(g._point,d,P&&g._handleOut)),g._visited=!0,g=P||g._path.getFirstSegment(),d=P&&P._handleIn,v=g._intersection}if(_)f.firstSegment.setHandleIn(d),f.setClosed(!0);else if(f){var I=f.getArea(!0);Math.abs(I)>=2e-7&&console.error("Boolean operation resulted in open path","segments =",f._segments.length,"length =",f.getLength(),"area=",I),f=null}f&&(f._segments.length>8||!u.isZero(f.getArea()))&&(h.push(f),f=null)}}return h}var d={unite:{1:!0},intersect:{2:!0},subtract:{1:!0},exclude:{1:!0}};return{_getWinding:function(t,e){return o(t,this._getMonoCurves(),e).winding},unite:function(t){return i(this,t,"unite")},intersect:function(t){return i(this,t,"intersect")},subtract:function(t){return i(this,t,"subtract")},exclude:function(t){return i(this,t,"exclude")},divide:function(t){return e(x,[this.subtract(t),this.intersect(t)],!0,this,t)},resolveCrossings:function(){function t(t){var e=t&&t._intersection;return e&&e._overlap}var e=this._children,i=e||[this],n=!1,s=!1,o=this.getIntersections(null,function(t){return t._overlap&&(n=!0)||t.isCrossing()&&(s=!0)});if(o=O.expand(o),n)for(var h=a(o,function(t){return t._overlap}),u=h.length-1;u>=0;u--){var c=h[u]._segment,d=c.getPrevious(),f=c.getNext();if(c._path&&t(d)&&t(f)){c.remove(),d._handleOut.set(0,0),f._handleIn.set(0,0);var _=d.getCurve();_.isStraight()&&0===_.getLength()&&d.remove()}}s&&(a(o,n&&function(t){var e=t.getCurve(),i=t._intersection._curve,n=t._segment;return!!(e&&i&&e._path&&i._path)||void(n&&(n._intersection=null))}),i=l(r.each(i,function(t){this.push.apply(this,t._segments)},[])));var g,v=i.length;if(v>1){i=i.slice().sort(function(t,e){return e.getBounds().getArea()-t.getBounds().getArea()});for(var p=i[0],m=[p],y={},x="nonzero"===this.getFillRule(),b=x&&r.each(i,function(t){this.push(t.isClockwise()?1:-1)},[]),u=1;u<v;u++){for(var C=i[u],S=C.getInteriorPoint(),P=!1,I=null,M=!1,T=u-1;T>=0&&!I;T--)if(i[T].contains(S)){if(x&&!P&&(b[u]+=b[T],b[u]&&b[T])){M=y[u]=!0;break}P=!0,I=!y[T]&&i[T]}M||(C.setClockwise(I?!I.isClockwise():p.isClockwise()),m.push(C))}i=m,v=m.length}return v>1&&e?(i!==e&&this.setChildren(i,!0),g=this):1!==v||e||(i[0]!==this&&this.setSegments(i[0].removeSegments()),g=this),g||(g=new N(w.NO_INSERT),g.addChildren(i,!0),g=g.reduce(),g.copyAttributes(this),this.replaceWith(g)),g}}}),L.inject({_getMonoCurves:function(){function t(t){var e=t[1],r=t[7],s=Math.abs((e-r)/(t[0]-t[6]))<2e-7?0:e>r?-1:1,a={values:t,winding:s};n.push(a),s&&(i=a)}function e(e){if(0!==z.getLength(e)){var i=e[1],n=e[3],r=e[5],s=e[7];if(z.isStraight(e)||i>=n==n>=r&&n>=r==r>=s)t(e);else{var a=3*(n-r)-i+s,o=2*(i+r)-4*n,h=n-i,l=4e-7,c=1-l,d=[],f=u.solveQuadratic(a,o,h,d,l,c);if(f<1)t(e);else{d.sort();var _=d[0],g=z.subdivide(e,_);t(g[0]),f>1&&(_=(d[1]-_)/(1-_),g=z.subdivide(g[1],_),t(g[0])),t(g[1])}}}}var i,n=this._monoCurves;if(!n){n=this._monoCurves=[];for(var r=this.getCurves(),s=this._segments,a=0,o=r.length;a<o;a++)e(r[a].getValues());if(!this._closed&&s.length>1){var h=s[s.length-1]._point,l=s[0]._point,c=h._x,d=h._y,f=l._x,_=l._y;e([c,d,c,d,f,_,f,_])}n.length>0&&(n[0].last=i)}return n},getInteriorPoint:function(){var t=this.getBounds(),e=t.getCenter(!0);if(!this.contains(e)){for(var i=this._getMonoCurves(),n=[],r=e.y,s=[],a=0,o=i.length;a<o;a++){var h=i[a].values;if(1===i[a].winding&&r>h[1]&&r<=h[7]||r>=h[7]&&r<h[1])for(var u=z.solveCubic(h,1,r,n,0,1),l=u-1;l>=0;l--)s.push(z.getPoint(h,n[l]).x)}s.sort(function(t,e){return t-e}),e.x=(s[0]+s[1])/2}return e}}),N.inject({_getMonoCurves:function(){for(var t=this._children,e=[],i=0,n=t.length;i<n;i++)e.push.apply(e,t[i]._getMonoCurves());return e}});var B=r.extend({_class:"PathIterator",initialize:function(t,e,i,n,r){function s(t,e){var i=z.getValues(t,e,r);h.push(i),a(i,t._index,0,1)}function a(t,i,r,s){if(!(s-r>c)||n&&z.isStraight(t)||z.isFlatEnough(t,e||.25)){var o=t[6]-t[0],h=t[7]-t[1],d=Math.sqrt(o*o+h*h);d>0&&(l+=d,u.push({offset:l,curve:t,index:i,time:s}))}else{var f=z.subdivide(t,.5),_=(r+s)/2;a(f[0],i,r,_),a(f[1],i,_,s)}}for(var o,h=[],u=[],l=0,c=1/(i||32),d=t._segments,f=d[0],_=1,g=d.length;_<g;_++)o=d[_],s(f,o),f=o;t._closed&&s(o,d[0]),this.curves=h,this.parts=u,this.length=l,this.index=0},_get:function(t){for(var e,i=this.index;e=i,!(0===i||this.parts[--i].offset<t););for(var n=this.parts.length;e<n;e++){var r=this.parts[e];if(r.offset>=t){this.index=e;var s=this.parts[e-1],a=s&&s.index===r.index?s.time:0,o=s?s.offset:0;return{index:r.index,time:a+(r.time-a)*(t-o)/(r.offset-o)}}}var r=this.parts[this.parts.length-1];return{index:r.index,time:1}},drawPart:function(t,e,i){for(var n=this._get(e),r=this._get(i),s=n.index,a=r.index;s<=a;s++){var o=z.getPart(this.curves[s],s===n.index?n.time:0,s===r.index?r.time:1);s===n.index&&t.moveTo(o[0],o[1]),t.bezierCurveTo.apply(t,o.slice(2))}}},r.each(z._evaluateMethods,function(t){this[t+"At"]=function(e){var i=this._get(e);return z[t](this.curves[i.index],i.time)}},{})),E=r.extend({initialize:function(t){for(var e,i=this.points=[],n=t._segments,r=t._closed,s=0,a=n.length;s<a;s++){var o=n[s].point;e&&e.equals(o)||i.push(e=o.clone())}r&&(i.unshift(i[i.length-1]),i.push(i[1])),this.closed=r},fit:function(t){var e=this.points,i=e.length,n=null;return i>0&&(n=[new T(e[0])],i>1&&(this.fitCubic(n,t,0,i-1,e[1].subtract(e[0]),e[i-2].subtract(e[i-1])),this.closed&&(n.shift(),n.pop()))),n},fitCubic:function(t,e,i,n,r,s){var a=this.points;if(n-i===1){var o=a[i],h=a[n],u=o.getDistance(h)/3;return void this.addCurve(t,[o,o.add(r.normalize(u)),h.add(s.normalize(u)),h])}for(var l,c=this.chordLengthParameterize(i,n),d=Math.max(e,e*e),f=!0,_=0;_<=4;_++){var g=this.generateBezier(i,n,c,r,s),v=this.findMaxError(i,n,g,c);if(v.error<e&&f)return void this.addCurve(t,g);if(l=v.index,v.error>=d)break;f=this.reparameterize(i,n,c,g),d=v.error}var p=a[l-1].subtract(a[l+1]);this.fitCubic(t,e,i,l,r,p),this.fitCubic(t,e,l,n,p.negate(),s)},addCurve:function(t,e){var i=t[t.length-1];i.setHandleOut(e[1].subtract(e[0])),t.push(new T(e[3],e[2].subtract(e[3])))},generateBezier:function(t,e,i,n,r){for(var s=1e-12,a=Math.abs,o=this.points,h=o[t],u=o[e],l=[[0,0],[0,0]],c=[0,0],d=0,f=e-t+1;d<f;d++){var _=i[d],g=1-_,v=3*_*g,p=g*g*g,m=v*g,y=v*_,w=_*_*_,x=n.normalize(m),b=r.normalize(y),C=o[t+d].subtract(h.multiply(p+m)).subtract(u.multiply(y+w));l[0][0]+=x.dot(x),l[0][1]+=x.dot(b),l[1][0]=l[0][1],l[1][1]+=b.dot(b),c[0]+=x.dot(C),c[1]+=b.dot(C)}var S,P,I=l[0][0]*l[1][1]-l[1][0]*l[0][1];if(a(I)>s){var M=l[0][0]*c[1]-l[1][0]*c[0],T=c[0]*l[1][1]-c[1]*l[0][1];S=T/I,P=M/I}else{var k=l[0][0]+l[0][1],z=l[1][0]+l[1][1];S=P=a(k)>s?c[0]/k:a(z)>s?c[1]/z:0}var O,A,L=u.getDistance(h),N=s*L;if(S<N||P<N)S=P=L/3;else{var B=u.subtract(h);O=n.normalize(S),A=r.normalize(P),O.dot(B)-A.dot(B)>L*L&&(S=P=L/3,O=A=null)}return[h,h.add(O||n.normalize(S)),u.add(A||r.normalize(P)),u]},reparameterize:function(t,e,i,n){for(var r=t;r<=e;r++)i[r-t]=this.findRoot(n,this.points[r],i[r-t]);for(var r=1,s=i.length;r<s;r++)if(i[r]<=i[r-1])return!1;return!0},findRoot:function(t,e,i){for(var n=[],r=[],s=0;s<=2;s++)n[s]=t[s+1].subtract(t[s]).multiply(3);for(var s=0;s<=1;s++)r[s]=n[s+1].subtract(n[s]).multiply(2);var a=this.evaluate(3,t,i),o=this.evaluate(2,n,i),h=this.evaluate(1,r,i),u=a.subtract(e),l=o.dot(o)+u.dot(h);return Math.abs(l)<1e-6?i:i-u.dot(o)/l},evaluate:function(t,e,i){for(var n=e.slice(),r=1;r<=t;r++)for(var s=0;s<=t-r;s++)n[s]=n[s].multiply(1-i).add(n[s+1].multiply(i));return n[0]},chordLengthParameterize:function(t,e){for(var i=[0],n=t+1;n<=e;n++)i[n-t]=i[n-t-1]+this.points[n].getDistance(this.points[n-1]);for(var n=1,r=e-t;n<=r;n++)i[n]/=i[r];return i},findMaxError:function(t,e,i,n){for(var r=Math.floor((e-t+1)/2),s=0,a=t+1;a<e;a++){var o=this.evaluate(3,i,n[a-t]),h=o.subtract(this.points[a]),u=h.x*h.x+h.y*h.y;u>=s&&(s=u,r=a)}return{error:s,index:r}}}),D=w.extend({_class:"TextItem",_applyMatrix:!1,_canApplyMatrix:!1,_serializeFields:{content:null},_boundsOptions:{stroke:!1,handle:!1},initialize:function(t){this._content="",this._lines=[];var i=t&&r.isPlainObject(t)&&t.x===e&&t.y===e;this._initialize(i&&t,!i&&c.read(arguments))},_equals:function(t){return this._content===t._content},copyContent:function(t){this.setContent(t._content)},getContent:function(){return this._content},setContent:function(t){this._content=""+t,this._lines=this._content.split(/\r\n|\n|\r/gm),this._changed(265)},isEmpty:function(){return!this._content},getCharacterStyle:"#getStyle",setCharacterStyle:"#setStyle",getParagraphStyle:"#getStyle",setParagraphStyle:"#setStyle"}),j=D.extend({_class:"PointText",initialize:function(){D.apply(this,arguments)},getPoint:function(){var t=this._matrix.getTranslation();return new d(t.x,t.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.translate(t.subtract(this._matrix.getTranslation()))},_draw:function(t,e,i){if(this._content){this._setStyles(t,e,i);var n=this._lines,r=this._style,s=r.hasFill(),a=r.hasStroke(),o=r.getLeading(),h=t.shadowColor;t.font=r.getFontStyle(),t.textAlign=r.getJustification();for(var u=0,l=n.length;u<l;u++){t.shadowColor=h;var c=n[u];s&&(t.fillText(c,0,0),t.shadowColor="rgba(0,0,0,0)"),a&&t.strokeText(c,0,0),t.translate(0,o)}}},_getBounds:function(t,e){var i=this._style,n=this._lines,r=n.length,s=i.getJustification(),a=i.getLeading(),o=this.getView().getTextWidth(i.getFontStyle(),n),h=0;"left"!==s&&(h-=o/("center"===s?2:1));var u=new g(h,r?-.75*a:0,o,r*a);return t?t._transformBounds(u,u):u}}),F=r.extend(new function(){function t(t){var n,r=t.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/);if(r){n=[0,0,0];for(var s=0;s<3;s++){var o=r[s+1];n[s]=parseInt(1==o.length?o+o:o,16)/255}}else if(r=t.match(/^rgba?\((.*)\)$/)){n=r[1].split(",");for(var s=0,h=n.length;s<h;s++){var o=+n[s];n[s]=s<3?o/255:o}}else if(i){var u=a[t];if(!u){e||(e=Q.getContext(1,1),e.globalCompositeOperation="copy"),e.fillStyle="rgba(0,0,0,0)",e.fillStyle=t,e.fillRect(0,0,1,1);var l=e.getImageData(0,0,1,1).data;u=a[t]=[l[0]/255,l[1]/255,l[2]/255]}n=u.slice()}else n=[0,0,0];return n}var e,n={gray:["gray"],rgb:["red","green","blue"],hsb:["hue","saturation","brightness"],hsl:["hue","saturation","lightness"],gradient:["gradient","origin","destination","highlight"]},s={},a={},o=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]],u={"rgb-hsb":function(t,e,i){var n=Math.max(t,e,i),r=Math.min(t,e,i),s=n-r,a=0===s?0:60*(n==t?(e-i)/s+(e<i?6:0):n==e?(i-t)/s+2:(t-e)/s+4);return[a,0===n?0:s/n,n]},"hsb-rgb":function(t,e,i){t=(t/60%6+6)%6;var n=Math.floor(t),r=t-n,n=o[n],s=[i,i*(1-e),i*(1-e*r),i*(1-e*(1-r))];return[s[n[0]],s[n[1]],s[n[2]]]},"rgb-hsl":function(t,e,i){var n=Math.max(t,e,i),r=Math.min(t,e,i),s=n-r,a=0===s,o=a?0:60*(n==t?(e-i)/s+(e<i?6:0):n==e?(i-t)/s+2:(t-e)/s+4),h=(n+r)/2,u=a?0:h<.5?s/(n+r):s/(2-n-r);return[o,u,h]},"hsl-rgb":function(t,e,i){if(t=(t/360%1+1)%1,0===e)return[i,i,i];for(var n=[t+1/3,t,t-1/3],r=i<.5?i*(1+e):i+e-i*e,s=2*i-r,a=[],o=0;o<3;o++){var h=n[o];h<0&&(h+=1),h>1&&(h-=1),a[o]=6*h<1?s+6*(r-s)*h:2*h<1?r:3*h<2?s+(r-s)*(2/3-h)*6:s}return a},"rgb-gray":function(t,e,i){return[.2989*t+.587*e+.114*i]},"gray-rgb":function(t){return[t,t,t]},"gray-hsb":function(t){return[0,0,t]},"gray-hsl":function(t){return[0,0,t]},"gradient-rgb":function(){return[]},"rgb-gradient":function(){return[]}};return r.each(n,function(t,e){s[e]=[],r.each(t,function(t,i){var a=r.capitalize(t),o=/^(hue|saturation)$/.test(t),h=s[e][i]="gradient"===t?function(t){var e=this._components[0];return t=R.read(Array.isArray(t)?t:arguments,0,{readNull:!0}),e!==t&&(e&&e._removeOwner(this),t&&t._addOwner(this)),t}:"gradient"===e?function(){return c.read(arguments,0,{readNull:"highlight"===t,clone:!0})}:function(t){return null==t||isNaN(t)?0:t};this["get"+a]=function(){return this._type===e||o&&/^hs[bl]$/.test(this._type)?this._components[i]:this._convert(e)[i]},this["set"+a]=function(t){this._type===e||o&&/^hs[bl]$/.test(this._type)||(this._components=this._convert(e),this._properties=n[e],this._type=e),this._components[i]=h.call(this,t),this._changed()}},this)},{_class:"Color",_readIndex:!0,initialize:function l(e){var i,r,a,o,h=Array.prototype.slice,u=arguments,c=this.__read,d=0;Array.isArray(e)&&(u=e,e=u[0]);var f=null!=e&&typeof e;if("string"===f&&e in n&&(i=e,e=u[1],Array.isArray(e)?(r=e,a=u[2]):(c&&(d=1),u=h.call(u,1),f=typeof e)),!r){if(o="number"===f?u:"object"===f&&null!=e.length?e:null){i||(i=o.length>=3?"rgb":"gray");var _=n[i].length;a=o[_],c&&(d+=o===arguments?_+(null!=a?1:0):1),o.length>_&&(o=h.call(o,0,_))}else if("string"===f)i="rgb",r=t(e),4===r.length&&(a=r[3],r.length--);else if("object"===f)if(e.constructor===l){if(i=e._type,r=e._components.slice(),a=e._alpha,"gradient"===i)for(var g=1,v=r.length;g<v;g++){var p=r[g];p&&(r[g]=p.clone())}}else if(e.constructor===R)i="gradient",o=u;else{i="hue"in e?"lightness"in e?"hsl":"hsb":"gradient"in e||"stops"in e||"radial"in e?"gradient":"gray"in e?"gray":"rgb";var m=n[i],y=s[i];this._components=r=[];for(var g=0,v=m.length;g<v;g++){var w=e[m[g]];null==w&&0===g&&"gradient"===i&&"stops"in e&&(w={stops:e.stops,radial:e.radial}),w=y[g].call(this,w),null!=w&&(r[g]=w)}a=e.alpha}c&&i&&(d=1)}if(this._type=i||"rgb",!r){this._components=r=[];for(var y=s[this._type],g=0,v=y.length;g<v;g++){var w=y[g].call(this,o&&o[g]);null!=w&&(r[g]=w)}}this._components=r,this._properties=n[this._type],this._alpha=a,c&&(this.__read=d)},_set:"#initialize",_serialize:function(t,e){var i=this.getComponents();return r.serialize(/^(gray|rgb)$/.test(this._type)?i:[this._type].concat(i),t,!0,e)},_changed:function(){this._canvasStyle=null,this._owner&&this._owner._changed(65)},_convert:function(t){var e;return this._type===t?this._components.slice():(e=u[this._type+"-"+t])?e.apply(this,this._components):u["rgb-"+t].apply(this,u[this._type+"-rgb"].apply(this,this._components))},convert:function(t){return new F(t,this._convert(t),this._alpha)},getType:function(){return this._type},setType:function(t){this._components=this._convert(t),this._properties=n[t],this._type=t},getComponents:function(){var t=this._components.slice();return null!=this._alpha&&t.push(this._alpha),t},getAlpha:function(){return null!=this._alpha?this._alpha:1},setAlpha:function(t){this._alpha=null==t?null:Math.min(Math.max(t,0),1),this._changed()},hasAlpha:function(){return null!=this._alpha},equals:function(t){var e=r.isPlainValue(t,!0)?F.read(arguments):t;return e===this||e&&this._class===e._class&&this._type===e._type&&this._alpha===e._alpha&&r.equals(this._components,e._components)||!1},toString:function(){for(var t=this._properties,e=[],i="gradient"===this._type,n=h.instance,r=0,s=t.length;r<s;r++){var a=this._components[r];null!=a&&e.push(t[r]+": "+(i?a:n.number(a)))}return null!=this._alpha&&e.push("alpha: "+n.number(this._alpha)),"{ "+e.join(", ")+" }"},toCSS:function(t){function e(t){return Math.round(255*(t<0?0:t>1?1:t))}var i=this._convert("rgb"),n=t||null==this._alpha?1:this._alpha;return i=[e(i[0]),e(i[1]),e(i[2])],n<1&&i.push(n<0?0:n),t?"#"+((1<<24)+(i[0]<<16)+(i[1]<<8)+i[2]).toString(16).slice(1):(4==i.length?"rgba(":"rgb(")+i.join(",")+")"},toCanvasStyle:function(t){if(this._canvasStyle)return this._canvasStyle;if("gradient"!==this._type)return this._canvasStyle=this.toCSS();var e,i=this._components,n=i[0],r=n._stops,s=i[1],a=i[2];if(n._radial){var o=a.getDistance(s),h=i[3];if(h){var u=h.subtract(s);u.getLength()>o&&(h=s.add(u.normalize(o-.1)))}var l=h||s;e=t.createRadialGradient(l.x,l.y,0,s.x,s.y,o)}else e=t.createLinearGradient(s.x,s.y,a.x,a.y);for(var c=0,d=r.length;c<d;c++){var f=r[c];e.addColorStop(f._offset||c/(d-1),f._color.toCanvasStyle())}return this._canvasStyle=e},transform:function(t){if("gradient"===this._type){for(var e=this._components,i=1,n=e.length;i<n;i++){var r=e[i];t._transformPoint(r,r,!0)}this._changed()}},statics:{_types:n,random:function(){var t=Math.random;return new F(t(),t(),t())}}})},new function(){var t={add:function(t,e){return t+e},subtract:function(t,e){return t-e},multiply:function(t,e){return t*e},divide:function(t,e){return t/e}};return r.each(t,function(t,e){this[e]=function(e){e=F.read(arguments);for(var i=this._type,n=this._components,r=e._convert(i),s=0,a=n.length;s<a;s++)r[s]=t(n[s],r[s]);return new F(i,r,null!=this._alpha?t(this._alpha,e.getAlpha()):null)}},{})}),R=r.extend({_class:"Gradient",initialize:function(t,e){this._id=l.get(),t&&this._set(t)&&(t=e=null),this._stops||this.setStops(t||["white","black"]),null==this._radial&&this.setRadial("string"==typeof e&&"radial"===e||e||!1)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._stops,this._radial],t,!0,e)})},_changed:function(){for(var t=0,e=this._owners&&this._owners.length;t<e;t++)this._owners[t]._changed()},_addOwner:function(t){this._owners||(this._owners=[]),this._owners.push(t)},_removeOwner:function(t){var i=this._owners?this._owners.indexOf(t):-1;i!=-1&&(this._owners.splice(i,1),0===this._owners.length&&(this._owners=e))},clone:function(){for(var t=[],e=0,i=this._stops.length;e<i;e++)t[e]=this._stops[e].clone();return new R(t,this._radial)},getStops:function(){return this._stops},setStops:function(t){if(t.length<2)throw new Error("Gradient stop list needs to contain at least two stops.");var i=this._stops;if(i)for(var n=0,r=i.length;n<r;n++)i[n]._owner=e;i=this._stops=q.readAll(t,0,{clone:!0});for(var n=0,r=i.length;n<r;n++)i[n]._owner=this;this._changed()},getRadial:function(){return this._radial},setRadial:function(t){this._radial=t,this._changed()},equals:function(t){if(t===this)return!0;if(t&&this._class===t._class){var e=this._stops,i=t._stops,n=e.length;if(n===i.length){for(var r=0;r<n;r++)if(!e[r].equals(i[r]))return!1;return!0}}return!1}}),q=r.extend({_class:"GradientStop",initialize:function(t,i){var n=t,r=i;"object"==typeof t&&i===e&&(Array.isArray(t)&&"number"!=typeof t[0]?(n=t[0],r=t[1]):("color"in t||"offset"in t||"rampPoint"in t)&&(n=t.color,r=t.offset||t.rampPoint||0)),this.setColor(n),this.setOffset(r)},clone:function(){return new q(this._color.clone(),this._offset)},_serialize:function(t,e){var i=this._color,n=this._offset;return r.serialize(null==n?[i]:[i,n],t,!0,e)},_changed:function(){this._owner&&this._owner._changed(65)},getOffset:function(){return this._offset},setOffset:function(t){this._offset=t,this._changed()},getRampPoint:"#getOffset",setRampPoint:"#setOffset",getColor:function(){return this._color},setColor:function(){var t=F.read(arguments,0,{clone:!0});t&&(t._owner=this),this._color=t,this._changed()},equals:function(t){return t===this||t&&this._class===t._class&&this._color.equals(t._color)&&this._offset==t._offset||!1}}),V=r.extend(new function(){var t={fillColor:null,fillRule:"nonzero",strokeColor:null,strokeWidth:1,strokeCap:"butt",strokeJoin:"miter",strokeScaling:!0,miterLimit:10,dashOffset:0,dashArray:[],shadowColor:null,shadowBlur:0,shadowOffset:new c,selectedColor:null},i=r.set({},t,{fontFamily:"sans-serif",fontWeight:"normal",fontSize:12,leading:null,justification:"left"}),n=r.set({},i,{fillColor:new F}),s={strokeWidth:97,strokeCap:97,strokeJoin:97,strokeScaling:105,miterLimit:97,fontFamily:9,fontWeight:9,fontSize:9,font:9,leading:9,justification:9},a={beans:!0},o={_class:"Style",beans:!0,initialize:function(e,r,s){this._values={},this._owner=r,this._project=r&&r._project||s||paper.project,this._defaults=!r||r instanceof x?i:r instanceof D?n:t,e&&this.set(e)}};return r.each(i,function(t,i){var n=/Color$/.test(i),h="shadowOffset"===i,u=r.capitalize(i),l=s[i],d="set"+u,f="get"+u;o[d]=function(t){var r=this._owner,s=r&&r._children;if(s&&s.length>0&&!(r instanceof N))for(var a=0,o=s.length;a<o;a++)s[a]._style[d](t);else if(i in this._defaults){var h=this._values[i];h!==t&&(n&&(h&&h._owner!==e&&(h._owner=e),t&&t.constructor===F&&(t._owner&&(t=t.clone()),t._owner=r)),this._values[i]=t,r&&r._changed(l||65))}},o[f]=function(t){var s,a=this._owner,o=a&&a._children;if(i in this._defaults&&(!o||0===o.length||t||a instanceof N)){var s=this._values[i];if(s===e)s=this._defaults[i],s&&s.clone&&(s=s.clone());else{var u=n?F:h?c:null;!u||s&&s.constructor===u||(this._values[i]=s=u.read([s],0,{readNull:!0,clone:!0}),s&&n&&(s._owner=a))}}else if(o)for(var l=0,d=o.length;l<d;l++){var _=o[l]._style[f]();if(0===l)s=_;else if(!r.equals(s,_))return e}return s},a[f]=function(t){return this._style[f](t)},a[d]=function(t){this._style[d](t)}}),r.each({Font:"FontFamily",WindingRule:"FillRule"},function(t,e){var i="get"+e,n="set"+e;o[i]=a[i]="#get"+t,o[n]=a[n]="#set"+t}),w.inject(a),o},{set:function(t){var e=t instanceof V,i=e?t._values:t;if(i)for(var n in i)if(n in this._defaults){var r=i[n];
-this[n]=r&&e&&r.clone?r.clone():r}},equals:function(t){return t===this||t&&this._class===t._class&&r.equals(this._values,t._values)||!1},hasFill:function(){var t=this.getFillColor();return!!t&&t.alpha>0},hasStroke:function(){var t=this.getStrokeColor();return!!t&&t.alpha>0&&this.getStrokeWidth()>0},hasShadow:function(){var t=this.getShadowColor();return!!t&&t.alpha>0&&(this.getShadowBlur()>0||!this.getShadowOffset().isZero())},getView:function(){return this._project._view},getFontStyle:function(){var t=this.getFontSize();return this.getFontWeight()+" "+t+(/[a-z]/i.test(t+"")?" ":"px ")+this.getFontFamily()},getFont:"#getFontFamily",setFont:"#setFontFamily",getLeading:function wt(){var t=wt.base.call(this),e=this.getFontSize();return/pt|em|%|px/.test(e)&&(e=this.getView().getPixelSize(e)),null!=t?t:1.2*e}}),H=new function(){function t(t,e,i,n){for(var r=["","webkit","moz","Moz","ms","o"],s=e[0].toUpperCase()+e.substring(1),a=0;a<6;a++){var o=r[a],h=o?o+s:e;if(h in t){if(!i)return t[h];t[h]=n;break}}}return{getStyles:function(t){var e=t&&9!==t.nodeType?t.ownerDocument:t,i=e&&e.defaultView;return i&&i.getComputedStyle(t,"")},getBounds:function(t,e){var i,n=t.ownerDocument,r=n.body,s=n.documentElement;try{i=t.getBoundingClientRect()}catch(a){i={left:0,top:0,width:0,height:0}}var o=i.left-(s.clientLeft||r.clientLeft||0),h=i.top-(s.clientTop||r.clientTop||0);if(!e){var u=n.defaultView;o+=u.pageXOffset||s.scrollLeft||r.scrollLeft,h+=u.pageYOffset||s.scrollTop||r.scrollTop}return new g(o,h,i.width,i.height)},getViewportBounds:function(t){var e=t.ownerDocument,i=e.defaultView,n=e.documentElement;return new g(0,0,i.innerWidth||n.clientWidth,i.innerHeight||n.clientHeight)},getOffset:function(t,e){return H.getBounds(t,e).getPoint()},getSize:function(t){return H.getBounds(t,!0).getSize()},isInvisible:function(t){return H.getSize(t).equals(new f(0,0))},isInView:function(t){return!H.isInvisible(t)&&H.getViewportBounds(t).intersects(H.getBounds(t,!0))},isInserted:function(t){return n.body.contains(t)},getPrefixed:function(e,i){return e&&t(e,i)},setPrefixed:function(e,i,n){if("object"==typeof i)for(var r in i)t(e,r,!0,i[r]);else t(e,i,!0,n)}}},Z={add:function(t,e){if(t)for(var i in e)for(var n=e[i],r=i.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.addEventListener(r[s],n,!1)},remove:function(t,e){if(t)for(var i in e)for(var n=e[i],r=i.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.removeEventListener(r[s],n,!1)},getPoint:function(t){var e=t.targetTouches?t.targetTouches.length?t.targetTouches[0]:t.changedTouches[0]:t;return new c(e.pageX||e.clientX+n.documentElement.scrollLeft,e.pageY||e.clientY+n.documentElement.scrollTop)},getTarget:function(t){return t.target||t.srcElement},getRelatedTarget:function(t){return t.relatedTarget||t.toElement},getOffset:function(t,e){return Z.getPoint(t).subtract(H.getOffset(e||Z.getTarget(t)))}};Z.requestAnimationFrame=new function(){function t(){var e=s;s=[];for(var i=0,a=e.length;i<a;i++)e[i]();r=n&&s.length,r&&n(t)}var e,n=H.getPrefixed(i,"requestAnimationFrame"),r=!1,s=[];return function(i){s.push(i),n?r||(n(t),r=!0):e||(e=setInterval(t,1e3/60))}};var U=r.extend(s,{_class:"View",initialize:function xt(t,e){function r(t){return e[t]||parseInt(e.getAttribute(t),10)}function s(){var t=H.getSize(e);return t.isNaN()||t.isZero()?new f(r("width"),r("height")):t}var o;if(i&&e){this._id=e.getAttribute("id"),null==this._id&&e.setAttribute("id",this._id="view-"+xt._id++),Z.add(e,this._viewEvents);var h="none";if(H.setPrefixed(e.style,{userDrag:h,userSelect:h,touchCallout:h,contentZooming:h,tapHighlightColor:"rgba(0,0,0,0)"}),a.hasAttribute(e,"resize")){var u=this;Z.add(i,this._windowEvents={resize:function(){u.setViewSize(s())}})}if(o=s(),a.hasAttribute(e,"stats")&&"undefined"!=typeof Stats){this._stats=new Stats;var l=this._stats.domElement,c=l.style,d=H.getOffset(e);c.position="absolute",c.left=d.x+"px",c.top=d.y+"px",n.body.appendChild(l)}}else o=new f(e),e=null;this._project=t,this._scope=t._scope,this._element=e,this._pixelRatio||(this._pixelRatio=i&&i.devicePixelRatio||1),this._setElementSize(o.width,o.height),this._viewSize=o,xt._views.push(this),xt._viewsById[this._id]=this,(this._matrix=new p)._owner=this,this._zoom=1,xt._focused||(xt._focused=this),this._frameItems={},this._frameItemCount=0,this._itemEvents={"native":{},virtual:{}},this._autoUpdate=!paper.agent.node,this._needsUpdate=!1},remove:function(){if(!this._project)return!1;U._focused===this&&(U._focused=null),U._views.splice(U._views.indexOf(this),1),delete U._viewsById[this._id];var t=this._project;return t._view===this&&(t._view=null),Z.remove(this._element,this._viewEvents),Z.remove(i,this._windowEvents),this._element=this._project=null,this.off("frame"),this._animate=!1,this._frameItems={},!0},_events:r.each(w._itemHandlers.concat(["onResize","onKeyDown","onKeyUp"]),function(t){this[t]={}},{onFrame:{install:function(){this.play()},uninstall:function(){this.pause()}}}),_animate:!1,_time:0,_count:0,getAutoUpdate:function(){return this._autoUpdate},setAutoUpdate:function(t){this._autoUpdate=t,t&&this.requestUpdate()},update:function(){},draw:function(){this.update()},requestUpdate:function(){if(!this._requested){var t=this;Z.requestAnimationFrame(function(){if(t._requested=!1,t._animate){t.requestUpdate();var e=t._element;H.getPrefixed(n,"hidden")&&"true"!==a.getAttribute(e,"keepalive")||!H.isInView(e)||t._handleFrame()}t._autoUpdate&&t.update()}),this._requested=!0}},play:function(){this._animate=!0,this.requestUpdate()},pause:function(){this._animate=!1},_handleFrame:function(){paper=this._scope;var t=Date.now()/1e3,e=this._last?t-this._last:0;this._last=t,this.emit("frame",new r({delta:e,time:this._time+=e,count:this._count++})),this._stats&&this._stats.update()},_animateItem:function(t,e){var i=this._frameItems;e?(i[t._id]={item:t,time:0,count:0},1===++this._frameItemCount&&this.on("frame",this._handleFrameItems)):(delete i[t._id],0===--this._frameItemCount&&this.off("frame",this._handleFrameItems))},_handleFrameItems:function(t){for(var e in this._frameItems){var i=this._frameItems[e];i.item.emit("frame",new r(t,{time:i.time+=t.delta,count:i.count++}))}},_changed:function(){this._project._changed(2049),this._bounds=null},getElement:function(){return this._element},getPixelRatio:function(){return this._pixelRatio},getResolution:function(){return 72*this._pixelRatio},getViewSize:function(){var t=this._viewSize;return new _(t.width,t.height,this,"setViewSize")},setViewSize:function(){var t=f.read(arguments),e=t.width,i=t.height,n=t.subtract(this._viewSize);n.isZero()||(this._setElementSize(e,i),this._viewSize.set(e,i),this.emit("resize",{size:t,delta:n}),this._changed(),this._autoUpdate&&this.requestUpdate())},_setElementSize:function(t,e){var i=this._element;i&&(i.width!==t&&(i.width=t),i.height!==e&&(i.height=e))},getBounds:function(){return this._bounds||(this._bounds=this._matrix.inverted()._transformBounds(new g(new c,this._viewSize))),this._bounds},getSize:function(){return this.getBounds().getSize()},getCenter:function(){return this.getBounds().getCenter()},setCenter:function(){var t=c.read(arguments);this.translate(this.getCenter().subtract(t))},getZoom:function(){return this._zoom},setZoom:function(t){this.transform((new p).scale(t/this._zoom,this.getCenter())),this._zoom=t},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},isVisible:function(){return H.isInView(this._element)},isInserted:function(){return H.isInserted(this._element)},getPixelSize:function(t){var e,i=this._element;if(i){var r=i.parentNode,s=n.createElement("div");s.style.fontSize=t,r.appendChild(s),e=parseFloat(H.getStyles(s).fontSize),r.removeChild(s)}else e=parseFloat(e);return e},getTextWidth:function(t,e){return 0}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var i=(e?r:c).read(arguments),n=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](i,n||this.getCenter(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t){this._matrix.append(t)},scrollBy:function(){this.translate(c.read(arguments).negate())}}),{projectToView:function(){return this._matrix._transformPoint(c.read(arguments))},viewToProject:function(){return this._matrix._inverseTransform(c.read(arguments))},getEventPoint:function(t){return this.viewToProject(Z.getOffset(t,this._element))}},{statics:{_views:[],_viewsById:{},_id:0,create:function(t,e){n&&"string"==typeof e&&(e=n.getElementById(e));var r=i?W:U;return new r(t,e)}}},new function(){function t(t){var e=Z.getTarget(t);return e.getAttribute&&U._viewsById[e.getAttribute("id")]}function e(){var t=U._focused;if(!t||!t.isVisible())for(var e=0,i=U._views.length;e<i;e++)if((t=U._views[e]).isVisible()){U._focused=h=t;break}}function r(t,e,i){t._handleMouseEvent("mousemove",e,i)}function s(t,e,i,n,r,s,a){function o(t,i){if(t.responds(i)){if(h||(h=new Y(i,n,r,e||t,s?r.subtract(s):null)),t.emit(i,h)&&(I=!0,h.prevented&&(M=!0),h.stopped))return u=!0}else{var a=T[i];if(a)return o(t,a)}}for(var h,u=!1;t&&t!==a&&!o(t,i);)t=t._parent;return u}function a(t,e,i,n,r,a){return t._project.removeOn(i),M=I=!1,b&&s(b,null,i,n,r,a)||e&&e!==b&&!e.isDescendant(b)&&s(e,null,T[i]||i,n,r,a,b)||s(t,b||e||t,i,n,r,a)}if(i){var o,h,u,l,c,d=!1,f=!1,_=i.navigator;_.pointerEnabled||_.msPointerEnabled?(u="pointerdown MSPointerDown",l="pointermove MSPointerMove",c="pointerup pointercancel MSPointerUp MSPointerCancel"):(u="touchstart",l="touchmove",c="touchend touchcancel","ontouchstart"in i&&_.userAgent.match(/mobile|tablet|ip(ad|hone|od)|android|silk/i)||(u+=" mousedown",l+=" mousemove",c+=" mouseup"));var g={},v={mouseout:function(t){var e=U._focused,i=Z.getRelatedTarget(t);if(e&&(!i||"HTML"===i.nodeName)){var n=Z.getOffset(t,e._element),s=n.x,a=Math.abs,o=a(s),h=1<<25,u=o-h;n.x=a(u)<o?u*(s<0?-1:1):s,r(e,t,e.viewToProject(n))}},scroll:e};g[u]=function(e){var i=U._focused=t(e);d||(d=!0,i._handleMouseEvent("mousedown",e))},v[l]=function(i){var n=U._focused;if(!f){var s=t(i);s?n!==s&&(n&&r(n,i),o||(o=n),n=U._focused=h=s):h&&h===n&&(o&&!o.isInserted()&&(o=null),n=U._focused=o,o=null,e())}n&&r(n,i)},v[u]=function(){f=!0},v[c]=function(t){var e=U._focused;e&&d&&e._handleMouseEvent("mouseup",t),f=d=!1},Z.add(n,v),Z.add(i,{load:e});var p,m,y,w,x,b,C,S,P,I=!1,M=!1,T={doubleclick:"click",mousedrag:"mousemove"},k=!1,z={mousedown:{mousedown:1,mousedrag:1,click:1,doubleclick:1},mouseup:{mouseup:1,mousedrag:1,click:1,doubleclick:1},mousemove:{mousedrag:1,mousemove:1,mouseenter:1,mouseleave:1}};return{_viewEvents:g,_handleMouseEvent:function(t,e,i){function n(t){return r.virtual[t]||l.responds(t)||u&&u.responds(t)}var r=this._itemEvents,o=r["native"][t],h="mousemove"===t,u=this._scope.tool,l=this;h&&d&&n("mousedrag")&&(t="mousedrag"),i||(i=this.getEventPoint(e));var c=this.getBounds().contains(i),f=o&&c&&l._project.hitTest(i,{tolerance:0,fill:!0,stroke:!0}),_=f&&f.item||null,g=!1,v={};v[t.substr(5)]=!0,o&&_!==x&&(x&&s(x,null,"mouseleave",e,i),_&&s(_,null,"mouseenter",e,i),x=_),k^c&&(s(this,null,c?"mouseenter":"mouseleave",e,i),p=c?this:null,g=!0),!c&&!v.drag||i.equals(y)||(a(this,_,h?t:"mousemove",e,i,y),g=!0),k=c,(v.down&&c||v.up&&m)&&(a(this,_,t,e,i,m),v.down?(P=_===C&&Date.now()-S<300,w=C=_,b=!M&&_,m=i):v.up&&(M||_!==w||(S=Date.now(),a(this,_,P?"doubleclick":"click",e,i,m),P=!1),w=b=null),k=!1,g=!0),y=i,g&&u&&(I=u._handleMouseEvent(t,e,i,v)||I),(I&&!v.move||v.down&&n("mouseup"))&&e.preventDefault()},_handleKeyEvent:function(t,e,i,n){function r(r){r.responds(t)&&(paper=a,r.emit(t,s=s||new J(t,e,i,n)))}var s,a=this._scope,o=a.tool;this.isVisible()&&(r(this),o&&o.responds(t)&&r(o))},_countItemEvent:function(t,e){var i=this._itemEvents,n=i["native"],r=i.virtual;for(var s in z)n[s]=(n[s]||0)+(z[s][t]||0)*e;r[t]=(r[t]||0)+e},statics:{updateFocus:e}}}}),W=U.extend({_class:"CanvasView",initialize:function(t,e){if(!(e instanceof i.HTMLCanvasElement)){var n=f.read(arguments,1);if(n.isZero())throw new Error("Cannot create CanvasView with the provided argument: "+[].slice.call(arguments,1));e=Q.getCanvas(n)}var r=this._context=e.getContext("2d");if(r.save(),this._pixelRatio=1,!/^off|false$/.test(a.getAttribute(e,"hidpi"))){var s=i.devicePixelRatio||1,o=H.getPrefixed(r,"backingStorePixelRatio")||1;this._pixelRatio=s/o}U.call(this,t,e),this._needsUpdate=!0},remove:function bt(){return this._context.restore(),bt.base.call(this)},_setElementSize:function Ct(t,e){var i=this._pixelRatio;if(Ct.base.call(this,t*i,e*i),1!==i){var n=this._element,r=this._context;if(!a.hasAttribute(n,"resize")){var s=n.style;s.width=t+"px",s.height=e+"px"}r.restore(),r.save(),r.scale(i,i)}},getPixelSize:function St(t){var e,i=paper.agent;if(i&&i.firefox)e=St.base.call(this,t);else{var n=this._context,r=n.font;n.font=t+" serif",e=parseFloat(n.font),n.font=r}return e},getTextWidth:function(t,e){var i=this._context,n=i.font,r=0;i.font=t;for(var s=0,a=e.length;s<a;s++)r=Math.max(r,i.measureText(e[s]).width);return i.font=n,r},update:function(){if(!this._needsUpdate)return!1;var t=this._project,e=this._context,i=this._viewSize;return e.clearRect(0,0,i.width+1,i.height+1),t&&t.draw(e,this._matrix,this._pixelRatio),this._needsUpdate=!1,!0}}),G=r.extend({_class:"Event",initialize:function(t){this.event=t,this.type=t&&t.type},prevented:!1,stopped:!1,preventDefault:function(){this.prevented=!0,this.event.preventDefault()},stopPropagation:function(){this.stopped=!0,this.event.stopPropagation()},stop:function(){this.stopPropagation(),this.preventDefault()},getTimeStamp:function(){return this.event.timeStamp},getModifiers:function(){return X.modifiers}}),J=G.extend({_class:"KeyEvent",initialize:function(t,e,i,n){this.type=t,this.event=e,this.key=i,this.character=n},toString:function(){return"{ type: '"+this.type+"', key: '"+this.key+"', character: '"+this.character+"', modifiers: "+this.getModifiers()+" }"}}),X=new function(){function t(t){var e=t.key||t.keyIdentifier;return e=/^U\+/.test(e)?String.fromCharCode(parseInt(e.substr(2),16)):/^Arrow[A-Z]/.test(e)?e.substr(5):"Unidentified"===e?String.fromCharCode(t.keyCode):e,o[e]||(e.length>1?r.hyphenate(e):e.toLowerCase())}function e(t,i,n,a){var o,h=U._focused;if(u[i]=t,t?l[i]=n:delete l[i],i.length>1&&(o=r.camelize(i))in c){c[o]=t;var d=paper&&paper.agent;if("meta"===o&&d&&d.mac)if(t)s={};else{for(var f in s)f in l&&e(!1,f,s[f],a);s=null}}else t&&s&&(s[i]=n);h&&h._handleKeyEvent(t?"keydown":"keyup",a,i,n)}var s,a,o={"\t":"tab"," ":"space","\b":"backspace","\x7f":"delete",Spacebar:"space",Del:"delete",Win:"meta",Esc:"escape"},h={tab:"\t",space:" ",enter:"\r"},u={},l={},c=new r({shift:!1,control:!1,alt:!1,meta:!1,capsLock:!1,space:!1}).inject({option:{get:function(){return this.alt}},command:{get:function(){var t=paper&&paper.agent;return t&&t.mac?this.meta:this.control}}});return Z.add(n,{keydown:function(i){var n=t(i),r=paper&&paper.agent;n.length>1||r&&r.chrome&&(i.altKey||r.mac&&i.metaKey||!r.mac&&i.ctrlKey)?e(!0,n,h[n]||(n.length>1?"":n),i):a=n},keypress:function(i){if(a){var n=t(i),r=i.charCode,s=r>=32?String.fromCharCode(r):n.length>1?"":n;n!==a&&(n=s.toLowerCase()),e(!0,n,s,i),a=null}},keyup:function(i){var n=t(i);n in l&&e(!1,n,l[n],i)}}),Z.add(i,{blur:function(t){for(var i in l)e(!1,i,l[i],t)}}),{modifiers:c,isDown:function(t){return!!u[t]}}},Y=G.extend({_class:"MouseEvent",initialize:function(t,e,i,n,r){this.type=t,this.event=e,this.point=i,this.target=n,this.delta=r},toString:function(){return"{ type: '"+this.type+"', point: "+this.point+", target: "+this.target+(this.delta?", delta: "+this.delta:"")+", modifiers: "+this.getModifiers()+" }"}}),$=G.extend({_class:"ToolEvent",_item:null,initialize:function(t,e,i){this.tool=t,this.type=e,this.event=i},_choosePoint:function(t,e){return t?t:e?e.clone():null},getPoint:function(){return this._choosePoint(this._point,this.tool._point)},setPoint:function(t){this._point=t},getLastPoint:function(){return this._choosePoint(this._lastPoint,this.tool._lastPoint)},setLastPoint:function(t){this._lastPoint=t},getDownPoint:function(){return this._choosePoint(this._downPoint,this.tool._downPoint)},setDownPoint:function(t){this._downPoint=t},getMiddlePoint:function(){return!this._middlePoint&&this.tool._lastPoint?this.tool._point.add(this.tool._lastPoint).divide(2):this._middlePoint},setMiddlePoint:function(t){this._middlePoint=t},getDelta:function(){return!this._delta&&this.tool._lastPoint?this.tool._point.subtract(this.tool._lastPoint):this._delta},setDelta:function(t){this._delta=t},getCount:function(){return this.tool[/^mouse(down|up)$/.test(this.type)?"_downCount":"_moveCount"]},setCount:function(t){this.tool[/^mouse(down|up)$/.test(this.type)?"downCount":"count"]=t},getItem:function(){if(!this._item){var t=this.tool._scope.project.hitTest(this.getPoint());if(t){for(var e=t.item,i=e._parent;/^(Group|CompoundPath)$/.test(i._class);)e=i,i=i._parent;this._item=e}}return this._item},setItem:function(t){this._item=t},toString:function(){return"{ type: "+this.type+", point: "+this.getPoint()+", count: "+this.getCount()+", modifiers: "+this.getModifiers()+" }"}}),K=(o.extend({_class:"Tool",_list:"tools",_reference:"tool",_events:["onMouseDown","onMouseUp","onMouseDrag","onMouseMove","onActivate","onDeactivate","onEditOptions","onKeyDown","onKeyUp"],initialize:function(t){o.call(this),this._moveCount=-1,this._downCount=-1,this._set(t)},getMinDistance:function(){return this._minDistance},setMinDistance:function(t){this._minDistance=t,null!=t&&null!=this._maxDistance&&t>this._maxDistance&&(this._maxDistance=t)},getMaxDistance:function(){return this._maxDistance},setMaxDistance:function(t){this._maxDistance=t,null!=this._minDistance&&null!=t&&t<this._minDistance&&(this._minDistance=t)},getFixedDistance:function(){return this._minDistance==this._maxDistance?this._minDistance:null},setFixedDistance:function(t){this._minDistance=this._maxDistance=t},_handleMouseEvent:function(t,e,i,n){function r(t,e){var r=i,s=a?c._point:c._downPoint||r;if(a){if(c._moveCount&&r.equals(s))return!1;if(s&&(null!=t||null!=e)){var o=r.subtract(s),h=o.getLength();if(h<(t||0))return!1;e&&(r=s.add(o.normalize(Math.min(h,e))))}c._moveCount++}return c._point=r,c._lastPoint=s||r,n.down&&(c._moveCount=-1,c._downPoint=r,c._downCount++),!0}function s(){o&&(l=c.emit(t,new $(c,t,e))||l)}paper=this._scope,n.drag&&!this.responds(t)&&(t="mousemove");var a=n.move||n.drag,o=this.responds(t),h=this.minDistance,u=this.maxDistance,l=!1,c=this;if(n.down)r(),s();else if(n.up)r(null,u),s();else if(o)for(;r(h,u);)s();return l}}),{request:function(t){var e=new i.XMLHttpRequest;return e.open((t.method||"get").toUpperCase(),t.url,r.pick(t.async,!0)),t.mimeType&&e.overrideMimeType(t.mimeType),e.onload=function(){var i=e.status;0===i||200===i?t.onLoad&&t.onLoad.call(e,e.responseText):e.onerror()},e.onerror=function(){var i=e.status,n='Could not load "'+t.url+'" (Status: '+i+")";if(!t.onError)throw new Error(n);t.onError(n,i)},e.send(null)}}),Q={canvases:[],getCanvas:function(t,e){if(!i)return null;var r,s=!0;"object"==typeof t&&(e=t.height,t=t.width),this.canvases.length?r=this.canvases.pop():(r=n.createElement("canvas"),s=!1);var a=r.getContext("2d");if(!a)throw new Error("Canvas "+r+" is unable toprovide a 2D context.");return r.width===t&&r.height===e?s&&a.clearRect(0,0,t+1,e+1):(r.width=t,r.height=e),a.save(),r},getContext:function(t,e){var i=this.getCanvas(t,e);return i?i.getContext("2d"):null},release:function(t){var e=t&&t.canvas?t.canvas:t;e&&e.getContext&&(e.getContext("2d").restore(),this.canvases.push(e))}},tt=new function(){function t(t,e,i){return.2989*t+.587*e+.114*i}function e(e,i,n,r){var s=r-t(e,i,n);f=e+s,_=i+s,g=n+s;var r=t(f,_,g),a=v(f,_,g),o=p(f,_,g);if(a<0){var h=r-a;f=r+(f-r)*r/h,_=r+(_-r)*r/h,g=r+(g-r)*r/h}if(o>255){var u=255-r,l=o-r;f=r+(f-r)*u/l,_=r+(_-r)*u/l,g=r+(g-r)*u/l}}function i(t,e,i){return p(t,e,i)-v(t,e,i)}function n(t,e,i,n){var r,s=[t,e,i],a=p(t,e,i),o=v(t,e,i);o=o===t?0:o===e?1:2,a=a===t?0:a===e?1:2,r=0===v(o,a)?1===p(o,a)?2:1:0,s[a]>s[o]?(s[r]=(s[r]-s[o])*n/(s[a]-s[o]),s[a]=n):s[r]=s[a]=0,s[o]=0,f=s[0],_=s[1],g=s[2]}var s,a,o,h,u,l,c,d,f,_,g,v=Math.min,p=Math.max,m=Math.abs,y={multiply:function(){f=u*s/255,_=l*a/255,g=c*o/255},screen:function(){f=u+s-u*s/255,_=l+a-l*a/255,g=c+o-c*o/255},overlay:function(){f=u<128?2*u*s/255:255-2*(255-u)*(255-s)/255,_=l<128?2*l*a/255:255-2*(255-l)*(255-a)/255,g=c<128?2*c*o/255:255-2*(255-c)*(255-o)/255},"soft-light":function(){var t=s*u/255;f=t+u*(255-(255-u)*(255-s)/255-t)/255,t=a*l/255,_=t+l*(255-(255-l)*(255-a)/255-t)/255,t=o*c/255,g=t+c*(255-(255-c)*(255-o)/255-t)/255},"hard-light":function(){f=s<128?2*s*u/255:255-2*(255-s)*(255-u)/255,_=a<128?2*a*l/255:255-2*(255-a)*(255-l)/255,g=o<128?2*o*c/255:255-2*(255-o)*(255-c)/255},"color-dodge":function(){f=0===u?0:255===s?255:v(255,255*u/(255-s)),_=0===l?0:255===a?255:v(255,255*l/(255-a)),g=0===c?0:255===o?255:v(255,255*c/(255-o))},"color-burn":function(){f=255===u?255:0===s?0:p(0,255-255*(255-u)/s),_=255===l?255:0===a?0:p(0,255-255*(255-l)/a),g=255===c?255:0===o?0:p(0,255-255*(255-c)/o)},darken:function(){f=u<s?u:s,_=l<a?l:a,g=c<o?c:o},lighten:function(){f=u>s?u:s,_=l>a?l:a,g=c>o?c:o},difference:function(){f=u-s,f<0&&(f=-f),_=l-a,_<0&&(_=-_),g=c-o,g<0&&(g=-g)},exclusion:function(){f=u+s*(255-u-u)/255,_=l+a*(255-l-l)/255,g=c+o*(255-c-c)/255},hue:function(){n(s,a,o,i(u,l,c)),e(f,_,g,t(u,l,c))},saturation:function(){n(u,l,c,i(s,a,o)),e(f,_,g,t(u,l,c))},luminosity:function(){e(u,l,c,t(s,a,o))},color:function(){e(s,a,o,t(u,l,c))},add:function(){f=v(u+s,255),_=v(l+a,255),g=v(c+o,255)},subtract:function(){f=p(u-s,0),_=p(l-a,0),g=p(c-o,0)},average:function(){f=(u+s)/2,_=(l+a)/2,g=(c+o)/2},negation:function(){f=255-m(255-s-u),_=255-m(255-a-l),g=255-m(255-o-c)}},w=this.nativeModes=r.each(["source-over","source-in","source-out","source-atop","destination-over","destination-in","destination-out","destination-atop","lighter","darker","copy","xor"],function(t){this[t]=!0},{}),x=Q.getContext(1,1);x&&(r.each(y,function(t,e){var i="darken"===e,n=!1;x.save();try{x.fillStyle=i?"#300":"#a00",x.fillRect(0,0,1,1),x.globalCompositeOperation=e,x.globalCompositeOperation===e&&(x.fillStyle=i?"#a00":"#300",x.fillRect(0,0,1,1),n=x.getImageData(0,0,1,1).data[0]!==i?170:51)}catch(r){}x.restore(),w[e]=n}),Q.release(x)),this.process=function(t,e,i,n,r){var v=e.canvas,p="normal"===t;if(p||w[t])i.save(),i.setTransform(1,0,0,1,0,0),i.globalAlpha=n,p||(i.globalCompositeOperation=t),i.drawImage(v,r.x,r.y),i.restore();else{var m=y[t];if(!m)return;for(var x=i.getImageData(r.x,r.y,v.width,v.height),b=x.data,C=e.getImageData(0,0,v.width,v.height).data,S=0,P=b.length;S<P;S+=4){s=C[S],u=b[S],a=C[S+1],l=b[S+1],o=C[S+2],c=b[S+2],h=C[S+3],d=b[S+3],m();var I=h*n/255,M=1-I;b[S]=I*f+M*u,b[S+1]=I*_+M*l,b[S+2]=I*g+M*c,b[S+3]=h*n+M*d}i.putImageData(x,r.x,r.y)}}},et=new function(){function t(t,e,s){return i(n.createElementNS(r,t),e,s)}function e(t,e){var i=o[e],n=i?t.getAttributeNS(i,e):t.getAttribute(e);return"null"===n?null:n}function i(t,e,i){for(var n in e){var r=e[n],s=o[n];"number"==typeof r&&i&&(r=i.number(r)),s?t.setAttributeNS(s,n,r):t.setAttribute(n,r)}return t}var r="http://www.w3.org/2000/svg",s="http://www.w3.org/2000/xmlns",a="http://www.w3.org/1999/xlink",o={href:a,xlink:s,xmlns:s+"/","xmlns:xlink":s+"/"};return{svg:r,xmlns:s,xlink:a,create:t,get:e,set:i}},it=r.each({fillColor:["fill","color"],fillRule:["fill-rule","string"],strokeColor:["stroke","color"],strokeWidth:["stroke-width","number"],strokeCap:["stroke-linecap","string"],strokeJoin:["stroke-linejoin","string"],strokeScaling:["vector-effect","lookup",{"true":"none","false":"non-scaling-stroke"},function(t,e){return!e&&(t instanceof A||t instanceof C||t instanceof D)}],miterLimit:["stroke-miterlimit","number"],dashArray:["stroke-dasharray","array"],dashOffset:["stroke-dashoffset","number"],fontFamily:["font-family","string"],fontWeight:["font-weight","string"],fontSize:["font-size","number"],justification:["text-anchor","lookup",{left:"start",center:"middle",right:"end"}],opacity:["opacity","number"],blendMode:["mix-blend-mode","style"]},function(t,e){var i=r.capitalize(e),n=t[2];this[e]={type:t[1],property:e,attribute:t[0],toSVG:n,fromSVG:n&&r.each(n,function(t,e){this[t]=e},{}),exportFilter:t[3],get:"get"+i,set:"set"+i}},{});return new function(){function t(t,e,i){var n=new r,s=t.getTranslation();if(e){t=t._shiftless();var a=t._inverseTransform(s);n[i?"cx":"x"]=a.x,n[i?"cy":"y"]=a.y,s=null}if(!t.isIdentity()){var o=t.decompose();if(o){var h=[],l=o.rotation,c=o.scaling,d=o.skewing;s&&!s.isZero()&&h.push("translate("+S.point(s)+")"),l&&h.push("rotate("+S.number(l)+")"),u.isZero(c.x-1)&&u.isZero(c.y-1)||h.push("scale("+S.point(c)+")"),d&&d.x&&h.push("skewX("+S.number(d.x)+")"),d&&d.y&&h.push("skewY("+S.number(d.y)+")"),n.transform=h.join(" ")}else n.transform="matrix("+t.getValues().join(",")+")"}return n}function e(e,i){for(var n=t(e._matrix),r=e._children,s=et.create("g",n,S),a=0,o=r.length;a<o;a++){var h=r[a],u=b(h,i);if(u)if(h.isClipMask()){var l=et.create("clipPath");l.appendChild(u),m(h,l,"clip"),et.set(s,{"clip-path":"url(#"+l.id+")"})}else s.appendChild(u)}return s}function n(e,i){var n=t(e._matrix,!0),r=e.getSize(),s=e.getImage();return n.x-=r.width/2,n.y-=r.height/2,n.width=r.width,n.height=r.height,n.href=i.embedImages===!1&&s&&s.src||e.toDataURL(),et.create("image",n,S)}function s(e,i){var n=i.matchShapes;if(n){var r=e.toShape(!1);if(r)return a(r,i)}var s,o=e._segments,h=o.length,u=t(e._matrix);if(n&&h>=2&&!e.hasHandles())if(h>2){s=e._closed?"polygon":"polyline";for(var l=[],c=0;c<h;c++)l.push(S.point(o[c]._point));u.points=l.join(" ")}else{s="line";var d=o[0]._point,f=o[1]._point;u.set({x1:d.x,y1:d.y,x2:f.x,y2:f.y})}else s="path",u.d=e.getPathData(null,i.precision);return et.create(s,u,S)}function a(e){var i=e._type,n=e._radius,r=t(e._matrix,!0,"rectangle"!==i);if("rectangle"===i){i="rect";var s=e._size,a=s.width,o=s.height;r.x-=a/2,r.y-=o/2,r.width=a,r.height=o,n.isZero()&&(n=null)}return n&&("circle"===i?r.r=n:(r.rx=n.width,r.ry=n.height)),et.create(i,r,S)}function o(e,i){var n=t(e._matrix),r=e.getPathData(null,i.precision);return r&&(n.d=r),et.create("path",n,S)}function c(e,i){var n=t(e._matrix,!0),r=e._definition,s=v(r,"symbol"),a=r._item,o=a.getBounds();return s||(s=et.create("symbol",{viewBox:S.rectangle(o)}),s.appendChild(b(a,i)),m(r,s,"symbol")),n.href="#"+s.id,n.x+=o.x,n.y+=o.y,n.width=o.width,n.height=o.height,n.overflow="visible",et.create("use",n,S)}function d(t){var e=v(t,"color");if(!e){var i,n=t.getGradient(),r=n._radial,s=t.getOrigin(),a=t.getDestination();if(r){i={cx:s.x,cy:s.y,r:s.getDistance(a)};var o=t.getHighlight();o&&(i.fx=o.x,i.fy=o.y)}else i={x1:s.x,y1:s.y,x2:a.x,y2:a.y};i.gradientUnits="userSpaceOnUse",e=et.create((r?"radial":"linear")+"Gradient",i,S);for(var h=n._stops,u=0,l=h.length;u<l;u++){var c=h[u],d=c._color,f=d.getAlpha();i={offset:c._offset||u/(l-1)},d&&(i["stop-color"]=d.toCSS(!0)),f<1&&(i["stop-opacity"]=f),e.appendChild(et.create("stop",i,S))}m(t,e,"color")}return"url(#"+e.id+")"}function f(e){var i=et.create("text",t(e._matrix,!0),S);return i.textContent=e._content,i}function _(t,e,i){var n={},s=!i&&t.getParent(),a=[];return null!=t._name&&(n.id=t._name),r.each(it,function(e){var i=e.get,o=e.type,h=t[i]();if(e.exportFilter?e.exportFilter(t,h):!s||!r.equals(s[i](),h)){if("color"===o&&null!=h){var u=h.getAlpha();u<1&&(n[e.attribute+"-opacity"]=u)}"style"===o?a.push(e.attribute+": "+h):n[e.attribute]=null==h?"none":"color"===o?h.gradient?d(h,t):h.toCSS(!0):"array"===o?h.join(","):"lookup"===o?e.toSVG[h]:h}}),a.length&&(n.style=a.join(";")),1===n.opacity&&delete n.opacity,t._visible||(n.visibility="hidden"),et.set(e,n,S)}function v(t,e){P||(P={ids:{},svgs:{}});var i=t._id||t.__id||(t.__id=l.get("svg"));return t&&P.svgs[e+"-"+i]}function m(t,e,i){P||v();var n=P.ids[i]=(P.ids[i]||0)+1;e.id=i+"-"+n,P.svgs[i+"-"+(t._id||t.__id)]=e}function x(t,e){var n=t,r=null;if(P){n="svg"===t.nodeName.toLowerCase()&&t;for(var s in P.svgs)r||(n||(n=et.create("svg"),n.appendChild(t)),r=n.insertBefore(et.create("defs"),n.firstChild)),r.appendChild(P.svgs[s]);P=null}return e.asString?(new i.XMLSerializer).serializeToString(n):n}function b(t,e,i){var n=I[t._class],r=n&&n(t,e);if(r){var s=e.onExport;s&&(r=s(t,r,e)||r);var a=JSON.stringify(t._data);a&&"{}"!==a&&"null"!==a&&r.setAttribute("data-paper-data",a)}return r&&_(t,r,i)}function C(t){return t||(t={}),S=new h(t.precision),t}var S,P,I={Group:e,Layer:e,Raster:n,Path:s,Shape:a,CompoundPath:o,SymbolItem:c,PointText:f};w.inject({exportSVG:function(t){return t=C(t),x(b(this,t,!0),t)}}),y.inject({exportSVG:function(e){e=C(e);var i=this._children,n=this.getView(),s=r.pick(e.bounds,"view"),a=e.matrix||"view"===s&&n._matrix,o=a&&p.read([a]),h="view"===s?new g([0,0],n.getViewSize()):"content"===s?w._getBounds(i,o,{stroke:!0}):g.read([s],0,{readNull:!0}),u={version:"1.1",xmlns:et.svg,"xmlns:xlink":et.xlink};h&&(u.width=h.width,u.height=h.height,(h.x||h.y)&&(u.viewBox=S.rectangle(h)));var l=et.create("svg",u,S),c=l;o&&!o.isIdentity()&&(c=l.appendChild(et.create("g",t(o),S)));for(var d=0,f=i.length;d<f;d++)c.appendChild(b(i[d],e,!0));return x(l,e)}})},new function(){function t(t,e,i,n,r){var s=et.get(t,e),a=null==s?n?null:i?"":0:i?s:parseFloat(s);return/%\s*$/.test(s)?a/100*(r?1:k[/x|^width/.test(e)?"width":"height"]):a}function s(e,i,n,r,s){return i=t(e,i||"x",!1,r,s),n=t(e,n||"y",!1,r,s),!r||null!=i&&null!=n?new c(i,n):null}function a(e,i,n,r,s){return i=t(e,i||"width",!1,r,s),n=t(e,n||"height",!1,r,s),!r||null!=i&&null!=n?new f(i,n):null}function o(t,e,i){return"none"===t?null:"number"===e?parseFloat(t):"array"===e?t?t.split(/[\s,]+/g).map(parseFloat):[]:"color"===e?P(t)||t:"lookup"===e?i[t]:t}function h(t,e,i,n){var r=t.childNodes,s="clippath"===e,a="defs"===e,o=new x,h=o._project,u=h._currentStyle,l=[];if(s||a||(o=b(o,t,n),h._currentStyle=o._style.clone()),n)for(var c=t.querySelectorAll("defs"),d=0,f=c.length;d<f;d++)M(c[d],i,!1);for(var d=0,f=r.length;d<f;d++){var _,g=r[d];1!==g.nodeType||/^defs$/i.test(g.nodeName)||!(_=M(g,i,!1))||_ instanceof I||l.push(_)}return o.addChildren(l),s&&(o=b(o.reduce(),t,n)),h._currentStyle=u,(s||a)&&(o.remove(),o=null),o}function u(t,e){for(var i=t.getAttribute("points").match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),n=[],r=0,s=i.length;r<s;r+=2)n.push(new c(parseFloat(i[r]),parseFloat(i[r+1])));var a=new L(n);return"polygon"===e&&a.closePath(),a}function l(t){return A.create(t.getAttribute("d"))}function d(e,i){var n,r=(t(e,"href",!0)||"").substring(1),a="radialgradient"===i;if(r)n=z[r].getGradient(),n._radial^a&&(n=n.clone(),n._radial=a);else{for(var o=e.childNodes,h=[],u=0,l=o.length;u<l;u++){var c=o[u];1===c.nodeType&&h.push(b(new q,c))}n=new R(h,a)}var d,f,_,g="userSpaceOnUse"!==t(e,"gradientUnits",!0);a?(d=s(e,"cx","cy",!1,g),f=d.add(t(e,"r",!1,!1,g),0),_=s(e,"fx","fy",!0,g)):(d=s(e,"x1","y1",!1,g),f=s(e,"x2","y2",!1,g));var v=b(new F(n,d,f,_),e);return v._scaleToBounds=g,null}function _(t,e,i,n){if(t.transform){for(var r=(n.getAttribute(i)||"").split(/\)\s*/g),s=new p,a=0,o=r.length;a<o;a++){var h=r[a];if(!h)break;for(var u=h.split(/\(\s*/),l=u[0],c=u[1].split(/[\s,]+/g),d=0,f=c.length;d<f;d++)c[d]=parseFloat(c[d]);switch(l){case"matrix":s.append(new p(c[0],c[1],c[2],c[3],c[4],c[5]));break;case"rotate":s.rotate(c[0],c[1],c[2]);break;case"translate":s.translate(c[0],c[1]);break;case"scale":s.scale(c);break;case"skewX":s.skew(c[0],0);break;case"skewY":s.skew(0,c[0])}}t.transform(s)}}function v(t,e,i){var n="fill-opacity"===i?"getFillColor":"getStrokeColor",r=t[n]&&t[n]();r&&r.setAlpha(parseFloat(e))}function m(t,i,n){var s=t.attributes[i],a=s&&s.value;if(!a){var o=r.camelize(i);a=t.style[o],a||n.node[o]===n.parent[o]||(a=n.node[o])}return a?"none"===a?null:a:e}function b(t,i,n){var s=i.parentNode,a={node:H.getStyles(i)||{},parent:!n&&!/^defs$/i.test(s.tagName)&&H.getStyles(s)||{}};return r.each(N,function(n,r){var s=m(i,r,a);t=s!==e&&n(t,s,r,i,a)||t;
-}),t}function P(t){var e=t&&t.match(/\((?:["'#]*)([^"')]+)/),n=e&&z[e[1].replace(i.location.href.split("#")[0]+"#","")];return n&&n._scaleToBounds&&(n=n.clone(),n._scaleToBounds=!0),n}function M(t,e,i){var s,o,h,u=t.nodeName.toLowerCase(),l="#document"!==u,c=n.body;i&&l&&(k=a(t,null,null,!0)||paper.getView().getSize(),s=et.create("svg",{style:"stroke-width: 1px; stroke-miterlimit: 10"}),o=t.parentNode,h=t.nextSibling,s.appendChild(t),c.appendChild(s));var d=paper.settings,f=d.applyMatrix,_=d.insertItems;d.applyMatrix=!1,d.insertItems=!1;var g=O[u],v=g&&g(t,u,e,i)||null;if(d.insertItems=_,d.applyMatrix=f,v){!l||v instanceof x||(v=b(v,t,i));var p=e.onImport,m=l&&t.getAttribute("data-paper-data");p&&(v=p(t,v,e)||v),e.expandShapes&&v instanceof C&&(v.remove(),v=v.toPath()),m&&(v._data=JSON.parse(m))}return s&&(c.removeChild(s),o&&(h?o.insertBefore(t,h):o.appendChild(t))),i&&(z={},v&&r.pick(e.applyMatrix,f)&&v.matrix.apply(!0,!0)),v}function T(t,r,s){function a(n){try{var a="object"==typeof n?n:(new i.DOMParser).parseFromString(n,"image/svg+xml");if(!a.nodeName)throw a=null,new Error("Unsupported SVG source: "+t);paper=h,u=M(a,r,!0),r&&r.insert===!1||s._insertItem(e,u);var l=r.onLoad;l&&l(u,n)}catch(c){o(c)}}function o(t,e){var i=r.onError;if(!i)throw new Error(t);i(t,e)}if(!t)return null;r="function"==typeof r?{onLoad:r}:r||{};var h=paper,u=null;if("string"!=typeof t||/^.*</.test(t)){if("undefined"!=typeof File&&t instanceof File){var l=new FileReader;return l.onload=function(){a(l.result)},l.onerror=function(){o(l.error)},l.readAsText(t)}a(t)}else{var c=n.getElementById(t);c?a(c):K.request({url:t,async:!0,onLoad:a,onError:o})}return u}var k,z={},O={"#document":function(t,e,i,n){for(var r=t.childNodes,s=0,a=r.length;s<a;s++){var o=r[s];if(1===o.nodeType)return M(o,i,n)}},g:h,svg:h,clippath:h,polygon:u,polyline:u,path:l,lineargradient:d,radialgradient:d,image:function(e){var i=new S(t(e,"href",!0));return i.on("load",function(){var t=a(e);this.setSize(t);var i=this._matrix._transformPoint(s(e).add(t.divide(2)));this.translate(i)}),i},symbol:function(t,e,i,n){return new I(h(t,e,i,n),(!0))},defs:h,use:function(e){var i=(t(e,"href",!0)||"").substring(1),n=z[i],r=s(e);return n?n instanceof I?n.place(r):n.clone().translate(r):null},circle:function(e){return new C.Circle(s(e,"cx","cy"),t(e,"r"))},ellipse:function(t){return new C.Ellipse({center:s(t,"cx","cy"),radius:a(t,"rx","ry")})},rect:function(t){return new C.Rectangle(new g(s(t),a(t)),a(t,"rx","ry"))},line:function(t){return new L.Line(s(t,"x1","y1"),s(t,"x2","y2"))},text:function(t){var e=new j(s(t).add(s(t,"dx","dy")));return e.setContent(t.textContent.trim()||""),e}},N=r.set(r.each(it,function(t){this[t.attribute]=function(e,i){if(e[t.set]&&(e[t.set](o(i,t.type,t.fromSVG)),"color"===t.type)){var n=e[t.get]();if(n){if(n._scaleToBounds){var r=e.getBounds();n.transform((new p).translate(r.getPoint()).scale(r.getSize()))}e instanceof C&&n.transform((new p).translate(e.getPosition(!0).negate()))}}}},{}),{id:function(t,e){z[e]=t,t.setName&&t.setName(e)},"clip-path":function(t,e){var i=P(e);if(i){if(i=i.clone(),i.setClipMask(!0),!(t instanceof x))return new x(i,t);t.insertChild(0,i)}},gradientTransform:_,transform:_,"fill-opacity":v,"stroke-opacity":v,visibility:function(t,e){t.setVisible&&t.setVisible("visible"===e)},display:function(t,e){t.setVisible&&t.setVisible(null!==e)},"stop-color":function(t,e){t.setColor&&t.setColor(e)},"stop-opacity":function(t,e){t._color&&t._color.setAlpha(parseFloat(e))},offset:function(t,e){if(t.setOffset){var i=e.match(/(.*)%$/);t.setOffset(i?i[1]/100:parseFloat(e))}},viewBox:function(t,e,i,n,r){var s,h,u=new g(o(e,"array")),l=a(n,null,null,!0);if(t instanceof x){var c=l?l.divide(u.getSize()):1,h=(new p).scale(c).translate(u.getPoint().negate());s=t}else t instanceof I&&(l&&u.setSize(l),s=t._item);if(s){if("visible"!==m(n,"overflow",r)){var d=new C.Rectangle(u);d.setClipMask(!0),s.addChild(d)}h&&s.transform(h)}}});w.inject({importSVG:function(t,e){return T(t,e,this)}}),y.inject({importSVG:function(t,e){return this.activate(),T(t,e,this)}})},paper=new(a.inject(r.exports,{enumerable:!0,Base:r,Numerical:u,Key:X,DomEvent:Z,DomElement:H,document:n,window:i,Symbol:I,PlacedSymbol:P})),paper.agent.node&&require("./node/extend")(paper),"function"==typeof define&&define.amd?define("paper",paper):"object"==typeof module&&module&&(module.exports=paper),paper}.call(this,"object"==typeof self?self:null);
\ No newline at end of file
diff --git a/dist/paper-full.js b/dist/paper-full.js
deleted file mode 100644
index ccf6965c..00000000
--- a/dist/paper-full.js
+++ /dev/null
@@ -1,14623 +0,0 @@
-/*!
- * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
- * http://paperjs.org/
- *
- * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
- * http://scratchdisk.com/ & http://jonathanpuckey.com/
- *
- * Distributed under the MIT license. See LICENSE file for details.
- *
- * All rights reserved.
- *
- * Date: Sat Jul 9 20:56:58 2016 +0200
- *
- ***
- *
- * Straps.js - Class inheritance library with support for bean-style accessors
- *
- * Copyright (c) 2006 - 2016 Juerg Lehni
- * http://scratchdisk.com/
- *
- * Distributed under the MIT license.
- *
- ***
- *
- * Acorn.js
- * http://marijnhaverbeke.nl/acorn/
- *
- * Acorn is a tiny, fast JavaScript parser written in JavaScript,
- * created by Marijn Haverbeke and released under an MIT license.
- *
- */
-
-var paper = function(self, undefined) {
-
-var window = self ? self.window : require('./node/window'),
-	document = window && window.document;
-
-self = self || window;
-
-var Base = new function() {
-	var hidden = /^(statics|enumerable|beans|preserve)$/,
-
-		forEach = [].forEach || function(iter, bind) {
-			for (var i = 0, l = this.length; i < l; i++)
-				iter.call(bind, this[i], i, this);
-		},
-
-		forIn = function(iter, bind) {
-			for (var i in this)
-				if (this.hasOwnProperty(i))
-					iter.call(bind, this[i], i, this);
-		},
-
-		create = Object.create || function(proto) {
-			return { __proto__: proto };
-		},
-
-		describe = Object.getOwnPropertyDescriptor || function(obj, name) {
-			var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
-			return get
-					? { get: get, set: obj.__lookupSetter__(name),
-						enumerable: true, configurable: true }
-					: obj.hasOwnProperty(name)
-						? { value: obj[name], enumerable: true,
-							configurable: true, writable: true }
-						: null;
-		},
-
-		_define = Object.defineProperty || function(obj, name, desc) {
-			if ((desc.get || desc.set) && obj.__defineGetter__) {
-				if (desc.get)
-					obj.__defineGetter__(name, desc.get);
-				if (desc.set)
-					obj.__defineSetter__(name, desc.set);
-			} else {
-				obj[name] = desc.value;
-			}
-			return obj;
-		},
-
-		define = function(obj, name, desc) {
-			delete obj[name];
-			return _define(obj, name, desc);
-		};
-
-	function inject(dest, src, enumerable, beans, preserve) {
-		var beansNames = {};
-
-		function field(name, val) {
-			val = val || (val = describe(src, name))
-					&& (val.get ? val : val.value);
-			if (typeof val === 'string' && val[0] === '#')
-				val = dest[val.substring(1)] || val;
-			var isFunc = typeof val === 'function',
-				res = val,
-				prev = preserve || isFunc && !val.base
-						? (val && val.get ? name in dest : dest[name])
-						: null,
-				bean;
-			if (!preserve || !prev) {
-				if (isFunc && prev)
-					val.base = prev;
-				if (isFunc && beans !== false
-						&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
-					beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
-				if (!res || isFunc || !res.get || typeof res.get !== 'function'
-						|| !Base.isPlainObject(res))
-					res = { value: res, writable: true };
-				if ((describe(dest, name)
-						|| { configurable: true }).configurable) {
-					res.configurable = true;
-					res.enumerable = enumerable;
-				}
-				define(dest, name, res);
-			}
-		}
-		if (src) {
-			for (var name in src) {
-				if (src.hasOwnProperty(name) && !hidden.test(name))
-					field(name);
-			}
-			for (var name in beansNames) {
-				var part = beansNames[name],
-					set = dest['set' + part],
-					get = dest['get' + part] || set && dest['is' + part];
-				if (get && (beans === true || get.length === 0))
-					field(name, { get: get, set: set });
-			}
-		}
-		return dest;
-	}
-
-	function each(obj, iter, bind) {
-		if (obj)
-			('length' in obj && !obj.getLength
-					&& typeof obj.length === 'number'
-				? forEach
-				: forIn).call(obj, iter, bind = bind || obj);
-		return bind;
-	}
-
-	function set(obj, args, start) {
-		for (var i = start, l = args.length; i < l; i++) {
-			var props = args[i];
-			for (var key in props)
-				if (props.hasOwnProperty(key))
-					obj[key] = props[key];
-		}
-		return obj;
-	}
-
-	return inject(function Base() {
-		set(this, arguments, 0);
-	}, {
-		inject: function(src) {
-			if (src) {
-				var statics = src.statics === true ? src : src.statics,
-					beans = src.beans,
-					preserve = src.preserve;
-				if (statics !== src)
-					inject(this.prototype, src, src.enumerable, beans, preserve);
-				inject(this, statics, true, beans, preserve);
-			}
-			for (var i = 1, l = arguments.length; i < l; i++)
-				this.inject(arguments[i]);
-			return this;
-		},
-
-		extend: function() {
-			var base = this,
-				ctor,
-				proto;
-			for (var i = 0, obj, l = arguments.length;
-					i < l && !(ctor && proto); i++) {
-				obj = arguments[i];
-				ctor = ctor || obj.initialize;
-				proto = proto || obj.prototype;
-			}
-			ctor = ctor || function() {
-				base.apply(this, arguments);
-			};
-			proto = ctor.prototype = proto || create(this.prototype);
-			define(proto, 'constructor',
-					{ value: ctor, writable: true, configurable: true });
-			inject(ctor, this, true);
-			if (arguments.length)
-				this.inject.apply(ctor, arguments);
-			ctor.base = base;
-			return ctor;
-		}
-	}, true).inject({
-		inject: function() {
-			for (var i = 0, l = arguments.length; i < l; i++) {
-				var src = arguments[i];
-				if (src)
-					inject(this, src, src.enumerable, src.beans, src.preserve);
-			}
-			return this;
-		},
-
-		extend: function() {
-			var res = create(this);
-			return res.inject.apply(res, arguments);
-		},
-
-		each: function(iter, bind) {
-			return each(this, iter, bind);
-		},
-
-		set: function() {
-			return set(this, arguments, 0);
-		},
-
-		clone: function() {
-			return new this.constructor(this);
-		},
-
-		statics: {
-			each: each,
-			create: create,
-			define: define,
-			describe: describe,
-
-			set: function(obj) {
-				return set(obj, arguments, 1);
-			},
-
-			clone: function(obj) {
-				return set(new obj.constructor(), arguments, 0);
-			},
-
-			isPlainObject: function(obj) {
-				var ctor = obj != null && obj.constructor;
-				return ctor && (ctor === Object || ctor === Base
-						|| ctor.name === 'Object');
-			},
-
-			pick: function(a, b) {
-				return a !== undefined ? a : b;
-			}
-		}
-	});
-};
-
-if (typeof module !== 'undefined')
-	module.exports = Base;
-
-Base.inject({
-	toString: function() {
-		return this._id != null
-			?  (this._class || 'Object') + (this._name
-				? " '" + this._name + "'"
-				: ' @' + this._id)
-			: '{ ' + Base.each(this, function(value, key) {
-				if (!/^_/.test(key)) {
-					var type = typeof value;
-					this.push(key + ': ' + (type === 'number'
-							? Formatter.instance.number(value)
-							: type === 'string' ? "'" + value + "'" : value));
-				}
-			}, []).join(', ') + ' }';
-	},
-
-	getClassName: function() {
-		return this._class || '';
-	},
-
-	importJSON: function(json) {
-		return Base.importJSON(json, this);
-	},
-
-	exportJSON: function(options) {
-		return Base.exportJSON(this, options);
-	},
-
-	toJSON: function() {
-		return Base.serialize(this);
-	},
-
-	_set: function(props) {
-		if (props && Base.isPlainObject(props))
-			return Base.filter(this, props);
-	},
-
-	statics: {
-
-		exports: {
-			enumerable: true
-		},
-
-		extend: function extend() {
-			var res = extend.base.apply(this, arguments),
-				name = res.prototype._class;
-			if (name && !Base.exports[name])
-				Base.exports[name] = res;
-			return res;
-		},
-
-		equals: function(obj1, obj2) {
-			if (obj1 === obj2)
-				return true;
-			if (obj1 && obj1.equals)
-				return obj1.equals(obj2);
-			if (obj2 && obj2.equals)
-				return obj2.equals(obj1);
-			if (obj1 && obj2
-					&& typeof obj1 === 'object' && typeof obj2 === 'object') {
-				if (Array.isArray(obj1) && Array.isArray(obj2)) {
-					var length = obj1.length;
-					if (length !== obj2.length)
-						return false;
-					while (length--) {
-						if (!Base.equals(obj1[length], obj2[length]))
-							return false;
-					}
-				} else {
-					var keys = Object.keys(obj1),
-						length = keys.length;
-					if (length !== Object.keys(obj2).length)
-						return false;
-					while (length--) {
-						var key = keys[length];
-						if (!(obj2.hasOwnProperty(key)
-								&& Base.equals(obj1[key], obj2[key])))
-							return false;
-					}
-				}
-				return true;
-			}
-			return false;
-		},
-
-		read: function(list, start, options, length) {
-			if (this === Base) {
-				var value = this.peek(list, start);
-				list.__index++;
-				return value;
-			}
-			var proto = this.prototype,
-				readIndex = proto._readIndex,
-				index = start || readIndex && list.__index || 0;
-			if (!length)
-				length = list.length - index;
-			var obj = list[index];
-			if (obj instanceof this
-				|| options && options.readNull && obj == null && length <= 1) {
-				if (readIndex)
-					list.__index = index + 1;
-				return obj && options && options.clone ? obj.clone() : obj;
-			}
-			obj = Base.create(this.prototype);
-			if (readIndex)
-				obj.__read = true;
-			obj = obj.initialize.apply(obj, index > 0 || length < list.length
-				? Array.prototype.slice.call(list, index, index + length)
-				: list) || obj;
-			if (readIndex) {
-				list.__index = index + obj.__read;
-				obj.__read = undefined;
-			}
-			return obj;
-		},
-
-		peek: function(list, start) {
-			return list[list.__index = start || list.__index || 0];
-		},
-
-		remain: function(list) {
-			return list.length - (list.__index || 0);
-		},
-
-		readAll: function(list, start, options) {
-			var res = [],
-				entry;
-			for (var i = start || 0, l = list.length; i < l; i++) {
-				res.push(Array.isArray(entry = list[i])
-						? this.read(entry, 0, options)
-						: this.read(list, i, options, 1));
-			}
-			return res;
-		},
-
-		readNamed: function(list, name, start, options, length) {
-			var value = this.getNamed(list, name),
-				hasObject = value !== undefined;
-			if (hasObject) {
-				var filtered = list._filtered;
-				if (!filtered) {
-					filtered = list._filtered = Base.create(list[0]);
-					filtered._filtering = list[0];
-				}
-				filtered[name] = undefined;
-			}
-			return this.read(hasObject ? [value] : list, start, options, length);
-		},
-
-		getNamed: function(list, name) {
-			var arg = list[0];
-			if (list._hasObject === undefined)
-				list._hasObject = list.length === 1 && Base.isPlainObject(arg);
-			if (list._hasObject)
-				return name ? arg[name] : list._filtered || arg;
-		},
-
-		hasNamed: function(list, name) {
-			return !!this.getNamed(list, name);
-		},
-
-		filter: function(dest, source, exclude) {
-			var keys = Object.keys(source._filtering || source);
-			for (var i = 0, l = keys.length; i < l; i++) {
-				var key = keys[i];
-				if (!(exclude && exclude[key])) {
-					var value = source[key];
-					if (value !== undefined)
-						dest[key] = value;
-				}
-			}
-			return dest;
-		},
-
-		isPlainValue: function(obj, asString) {
-			return this.isPlainObject(obj) || Array.isArray(obj)
-					|| asString && typeof obj === 'string';
-		},
-
-		serialize: function(obj, options, compact, dictionary) {
-			options = options || {};
-
-			var isRoot = !dictionary,
-				res;
-			if (isRoot) {
-				options.formatter = new Formatter(options.precision);
-				dictionary = {
-					length: 0,
-					definitions: {},
-					references: {},
-					add: function(item, create) {
-						var id = '#' + item._id,
-							ref = this.references[id];
-						if (!ref) {
-							this.length++;
-							var res = create.call(item),
-								name = item._class;
-							if (name && res[0] !== name)
-								res.unshift(name);
-							this.definitions[id] = res;
-							ref = this.references[id] = [id];
-						}
-						return ref;
-					}
-				};
-			}
-			if (obj && obj._serialize) {
-				res = obj._serialize(options, dictionary);
-				var name = obj._class;
-				if (name && !obj._compactSerialize && (isRoot || !compact)
-						&& res[0] !== name) {
-					res.unshift(name);
-				}
-			} else if (Array.isArray(obj)) {
-				res = [];
-				for (var i = 0, l = obj.length; i < l; i++)
-					res[i] = Base.serialize(obj[i], options, compact,
-							dictionary);
-			} else if (Base.isPlainObject(obj)) {
-				res = {};
-				var keys = Object.keys(obj);
-				for (var i = 0, l = keys.length; i < l; i++) {
-					var key = keys[i];
-					res[key] = Base.serialize(obj[key], options, compact,
-							dictionary);
-				}
-			} else if (typeof obj === 'number') {
-				res = options.formatter.number(obj, options.precision);
-			} else {
-				res = obj;
-			}
-			return isRoot && dictionary.length > 0
-					? [['dictionary', dictionary.definitions], res]
-					: res;
-		},
-
-		deserialize: function(json, create, _data, _setDictionary, _isRoot) {
-			var res = json,
-				isFirst = !_data,
-				hasDictionary = isFirst && json && json.length
-					&& json[0][0] === 'dictionary';
-			_data = _data || {};
-			if (Array.isArray(json)) {
-				var type = json[0],
-					isDictionary = type === 'dictionary';
-				if (json.length == 1 && /^#/.test(type)) {
-					return _data.dictionary[type];
-				}
-				type = Base.exports[type];
-				res = [];
-				for (var i = type ? 1 : 0, l = json.length; i < l; i++) {
-					res.push(Base.deserialize(json[i], create, _data,
-							isDictionary, hasDictionary));
-				}
-				if (type) {
-					var args = res;
-					if (create) {
-						res = create(type, args, isFirst || _isRoot);
-					} else {
-						res = Base.create(type.prototype);
-						type.apply(res, args);
-					}
-				}
-			} else if (Base.isPlainObject(json)) {
-				res = {};
-				if (_setDictionary)
-					_data.dictionary = res;
-				for (var key in json)
-					res[key] = Base.deserialize(json[key], create, _data);
-			}
-			return hasDictionary ? res[1] : res;
-		},
-
-		exportJSON: function(obj, options) {
-			var json = Base.serialize(obj, options);
-			return options && options.asString === false
-					? json
-					: JSON.stringify(json);
-		},
-
-		importJSON: function(json, target) {
-			return Base.deserialize(
-					typeof json === 'string' ? JSON.parse(json) : json,
-					function(ctor, args, isRoot) {
-						var useTarget = isRoot && target
-								&& target.constructor === ctor,
-							obj = useTarget ? target
-								: Base.create(ctor.prototype);
-						if (args.length === 1 && obj instanceof Item
-								&& (useTarget || !(obj instanceof Layer))) {
-							var arg = args[0];
-							if (Base.isPlainObject(arg))
-								arg.insert = false;
-						}
-						(useTarget ? obj._set : ctor).apply(obj, args);
-						if (useTarget)
-							target = null;
-						return obj;
-					});
-		},
-
-		splice: function(list, items, index, remove) {
-			var amount = items && items.length,
-				append = index === undefined;
-			index = append ? list.length : index;
-			if (index > list.length)
-				index = list.length;
-			for (var i = 0; i < amount; i++)
-				items[i]._index = index + i;
-			if (append) {
-				list.push.apply(list, items);
-				return [];
-			} else {
-				var args = [index, remove];
-				if (items)
-					args.push.apply(args, items);
-				var removed = list.splice.apply(list, args);
-				for (var i = 0, l = removed.length; i < l; i++)
-					removed[i]._index = undefined;
-				for (var i = index + amount, l = list.length; i < l; i++)
-					list[i]._index = i;
-				return removed;
-			}
-		},
-
-		capitalize: function(str) {
-			return str.replace(/\b[a-z]/g, function(match) {
-				return match.toUpperCase();
-			});
-		},
-
-		camelize: function(str) {
-			return str.replace(/-(.)/g, function(all, chr) {
-				return chr.toUpperCase();
-			});
-		},
-
-		hyphenate: function(str) {
-			return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
-		}
-	}
-});
-
-var Emitter = {
-	on: function(type, func) {
-		if (typeof type !== 'string') {
-			Base.each(type, function(value, key) {
-				this.on(key, value);
-			}, this);
-		} else {
-			var types = this._eventTypes,
-				entry = types && types[type],
-				handlers = this._callbacks = this._callbacks || {};
-			handlers = handlers[type] = handlers[type] || [];
-			if (handlers.indexOf(func) === -1) {
-				handlers.push(func);
-				if (entry && entry.install && handlers.length === 1)
-					entry.install.call(this, type);
-			}
-		}
-		return this;
-	},
-
-	off: function(type, func) {
-		if (typeof type !== 'string') {
-			Base.each(type, function(value, key) {
-				this.off(key, value);
-			}, this);
-			return;
-		}
-		var types = this._eventTypes,
-			entry = types && types[type],
-			handlers = this._callbacks && this._callbacks[type],
-			index;
-		if (handlers) {
-			if (!func || (index = handlers.indexOf(func)) !== -1
-					&& handlers.length === 1) {
-				if (entry && entry.uninstall)
-					entry.uninstall.call(this, type);
-				delete this._callbacks[type];
-			} else if (index !== -1) {
-				handlers.splice(index, 1);
-			}
-		}
-		return this;
-	},
-
-	once: function(type, func) {
-		return this.on(type, function() {
-			func.apply(this, arguments);
-			this.off(type, func);
-		});
-	},
-
-	emit: function(type, event) {
-		var handlers = this._callbacks && this._callbacks[type];
-		if (!handlers)
-			return false;
-		var args = [].slice.call(arguments, 1),
-			setTarget = event && event.target && !event.currentTarget;
-		handlers = handlers.slice();
-		if (setTarget)
-			event.currentTarget = this;
-		for (var i = 0, l = handlers.length; i < l; i++) {
-			if (handlers[i].apply(this, args) === false) {
-				if (event && event.stop)
-					event.stop();
-				break;
-		   }
-		}
-		if (setTarget)
-			delete event.currentTarget;
-		return true;
-	},
-
-	responds: function(type) {
-		return !!(this._callbacks && this._callbacks[type]);
-	},
-
-	attach: '#on',
-	detach: '#off',
-	fire: '#emit',
-
-	_installEvents: function(install) {
-		var types = this._eventTypes,
-			handlers = this._callbacks,
-			key = install ? 'install' : 'uninstall';
-		if (types) {
-			for (var type in handlers) {
-				if (handlers[type].length > 0) {
-					var entry = types[type],
-						func = entry && entry[key];
-					if (func)
-						func.call(this, type);
-				}
-		}
-		}
-	},
-
-	statics: {
-		inject: function inject(src) {
-			var events = src._events;
-			if (events) {
-				var types = {};
-				Base.each(events, function(entry, key) {
-					var isString = typeof entry === 'string',
-						name = isString ? entry : key,
-						part = Base.capitalize(name),
-						type = name.substring(2).toLowerCase();
-					types[type] = isString ? {} : entry;
-					name = '_' + name;
-					src['get' + part] = function() {
-						return this[name];
-					};
-					src['set' + part] = function(func) {
-						var prev = this[name];
-						if (prev)
-							this.off(type, prev);
-						if (func)
-							this.on(type, func);
-						this[name] = func;
-					};
-				});
-				src._eventTypes = types;
-			}
-			return inject.base.apply(this, arguments);
-		}
-	}
-};
-
-var PaperScope = Base.extend({
-	_class: 'PaperScope',
-
-	initialize: function PaperScope() {
-		paper = this;
-		this.settings = new Base({
-			applyMatrix: true,
-			insertItems: true,
-			handleSize: 4,
-			hitTolerance: 0
-		});
-		this.project = null;
-		this.projects = [];
-		this.tools = [];
-		this.palettes = [];
-		this._id = PaperScope._id++;
-		PaperScope._scopes[this._id] = this;
-		var proto = PaperScope.prototype;
-		if (!this.support) {
-			var ctx = CanvasProvider.getContext(1, 1) || {};
-			proto.support = {
-				nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
-				nativeBlendModes: BlendMode.nativeModes
-			};
-			CanvasProvider.release(ctx);
-		}
-		if (!this.agent) {
-			var user = self.navigator.userAgent.toLowerCase(),
-				os = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],
-				platform = os === 'darwin' ? 'mac' : os,
-				agent = proto.agent = proto.browser = { platform: platform };
-			if (platform)
-				agent[platform] = true;
-			user.replace(
-				/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,
-				function(all, n, v1, v2, rv) {
-					if (!agent.chrome) {
-						var v = n === 'opera' ? v2 :
-								/^(node|trident)$/.test(n) ? rv : v1;
-						agent.version = v;
-						agent.versionNumber = parseFloat(v);
-						n = n === 'trident' ? 'msie' : n;
-						agent.name = n;
-						agent[n] = true;
-					}
-				}
-			);
-			if (agent.chrome)
-				delete agent.webkit;
-			if (agent.atom)
-				delete agent.chrome;
-		}
-	},
-
-	version: "0.10.2",
-
-	getView: function() {
-		var project = this.project;
-		return project && project._view;
-	},
-
-	getPaper: function() {
-		return this;
-	},
-
-	execute: function(code, options) {
-		paper.PaperScript.execute(code, this, options);
-		View.updateFocus();
-	},
-
-	install: function(scope) {
-		var that = this;
-		Base.each(['project', 'view', 'tool'], function(key) {
-			Base.define(scope, key, {
-				configurable: true,
-				get: function() {
-					return that[key];
-				}
-			});
-		});
-		for (var key in this)
-			if (!/^_/.test(key) && this[key])
-				scope[key] = this[key];
-	},
-
-	setup: function(element) {
-		paper = this;
-		this.project = new Project(element);
-		return this;
-	},
-
-	createCanvas: function(width, height) {
-		return CanvasProvider.getCanvas(width, height);
-	},
-
-	activate: function() {
-		paper = this;
-	},
-
-	clear: function() {
-		var projects = this.projects,
-			tools = this.tools,
-			palettes = this.palettes;
-		for (var i = projects.length - 1; i >= 0; i--)
-			projects[i].remove();
-		for (var i = tools.length - 1; i >= 0; i--)
-			tools[i].remove();
-		for (var i = palettes.length - 1; i >= 0; i--)
-			palettes[i].remove();
-	},
-
-	remove: function() {
-		this.clear();
-		delete PaperScope._scopes[this._id];
-	},
-
-	statics: new function() {
-		function handleAttribute(name) {
-			name += 'Attribute';
-			return function(el, attr) {
-				return el[name](attr) || el[name]('data-paper-' + attr);
-			};
-		}
-
-		return {
-			_scopes: {},
-			_id: 0,
-
-			get: function(id) {
-				return this._scopes[id] || null;
-			},
-
-			getAttribute: handleAttribute('get'),
-			hasAttribute: handleAttribute('has')
-		};
-	}
-});
-
-var PaperScopeItem = Base.extend(Emitter, {
-
-	initialize: function(activate) {
-		this._scope = paper;
-		this._index = this._scope[this._list].push(this) - 1;
-		if (activate || !this._scope[this._reference])
-			this.activate();
-	},
-
-	activate: function() {
-		if (!this._scope)
-			return false;
-		var prev = this._scope[this._reference];
-		if (prev && prev !== this)
-			prev.emit('deactivate');
-		this._scope[this._reference] = this;
-		this.emit('activate', prev);
-		return true;
-	},
-
-	isActive: function() {
-		return this._scope[this._reference] === this;
-	},
-
-	remove: function() {
-		if (this._index == null)
-			return false;
-		Base.splice(this._scope[this._list], null, this._index, 1);
-		if (this._scope[this._reference] == this)
-			this._scope[this._reference] = null;
-		this._scope = null;
-		return true;
-	},
-
-	getView: function() {
-		return this._scope.getView();
-	}
-});
-
-var Formatter = Base.extend({
-	initialize: function(precision) {
-		this.precision = Base.pick(precision, 5);
-		this.multiplier = Math.pow(10, this.precision);
-	},
-
-	number: function(val) {
-		return this.precision < 16
-				? Math.round(val * this.multiplier) / this.multiplier : val;
-	},
-
-	pair: function(val1, val2, separator) {
-		return this.number(val1) + (separator || ',') + this.number(val2);
-	},
-
-	point: function(val, separator) {
-		return this.number(val.x) + (separator || ',') + this.number(val.y);
-	},
-
-	size: function(val, separator) {
-		return this.number(val.width) + (separator || ',')
-				+ this.number(val.height);
-	},
-
-	rectangle: function(val, separator) {
-		return this.point(val, separator) + (separator || ',')
-				+ this.size(val, separator);
-	}
-});
-
-Formatter.instance = new Formatter();
-
-var Numerical = new function() {
-
-	var abscissas = [
-		[  0.5773502691896257645091488],
-		[0,0.7745966692414833770358531],
-		[  0.3399810435848562648026658,0.8611363115940525752239465],
-		[0,0.5384693101056830910363144,0.9061798459386639927976269],
-		[  0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],
-		[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],
-		[  0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],
-		[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],
-		[  0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],
-		[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],
-		[  0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],
-		[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],
-		[  0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],
-		[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],
-		[  0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]
-	];
-
-	var weights = [
-		[1],
-		[0.8888888888888888888888889,0.5555555555555555555555556],
-		[0.6521451548625461426269361,0.3478548451374538573730639],
-		[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],
-		[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],
-		[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],
-		[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],
-		[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],
-		[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],
-		[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],
-		[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],
-		[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],
-		[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],
-		[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],
-		[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]
-	];
-
-	var abs = Math.abs,
-		sqrt = Math.sqrt,
-		pow = Math.pow,
-		log2 = Math.log2 || function(x) {
-			return Math.log(x) * Math.LOG2E;
-		},
-		EPSILON = 1e-12,
-		MACHINE_EPSILON = 1.12e-16;
-
-	function clamp(value, min, max) {
-		return value < min ? min : value > max ? max : value;
-	}
-
-	function getDiscriminant(a, b, c) {
-		function split(v) {
-			var x = v * 134217729,
-				y = v - x,
-				hi = y + x,
-				lo = v - hi;
-			return [hi, lo];
-		}
-
-		var D = b * b - a * c,
-			E = b * b + a * c;
-		if (abs(D) * 3 < E) {
-			var ad = split(a),
-				bd = split(b),
-				cd = split(c),
-				p = b * b,
-				dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
-				q = a * c,
-				dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
-						+ ad[1] * cd[1];
-			D = (p - q) + (dp - dq);
-		}
-		return D;
-	}
-
-	function getNormalizationFactor() {
-		var norm = Math.max.apply(Math, arguments);
-		return norm && (norm < 1e-8 || norm > 1e8)
-				? pow(2, -Math.round(log2(norm)))
-				: 0;
-	}
-
-	return {
-		TOLERANCE: 1e-6,
-		EPSILON: EPSILON,
-		MACHINE_EPSILON: MACHINE_EPSILON,
-		CURVETIME_EPSILON: 4e-7,
-		GEOMETRIC_EPSILON: 2e-7,
-		WINDING_EPSILON: 2e-7,
-		TRIGONOMETRIC_EPSILON: 1e-7,
-		CLIPPING_EPSILON: 1e-9,
-		KAPPA: 4 * (sqrt(2) - 1) / 3,
-
-		isZero: function(val) {
-			return val >= -EPSILON && val <= EPSILON;
-		},
-
-		clamp: clamp,
-
-		integrate: function(f, a, b, n) {
-			var x = abscissas[n - 2],
-				w = weights[n - 2],
-				A = (b - a) * 0.5,
-				B = A + a,
-				i = 0,
-				m = (n + 1) >> 1,
-				sum = n & 1 ? w[i++] * f(B) : 0;
-			while (i < m) {
-				var Ax = A * x[i];
-				sum += w[i++] * (f(B + Ax) + f(B - Ax));
-			}
-			return A * sum;
-		},
-
-		findRoot: function(f, df, x, a, b, n, tolerance) {
-			for (var i = 0; i < n; i++) {
-				var fx = f(x),
-					dx = fx / df(x),
-					nx = x - dx;
-				if (abs(dx) < tolerance)
-					return nx;
-				if (fx > 0) {
-					b = x;
-					x = nx <= a ? (a + b) * 0.5 : nx;
-				} else {
-					a = x;
-					x = nx >= b ? (a + b) * 0.5 : nx;
-				}
-			}
-			return x;
-		},
-
-		solveQuadratic: function(a, b, c, roots, min, max) {
-			var x1, x2 = Infinity;
-			if (abs(a) < EPSILON) {
-				if (abs(b) < EPSILON)
-					return abs(c) < EPSILON ? -1 : 0;
-				x1 = -c / b;
-			} else {
-				b *= -0.5;
-				var D = getDiscriminant(a, b, c);
-				if (D && abs(D) < MACHINE_EPSILON) {
-					var f = getNormalizationFactor(abs(a), abs(b), abs(c));
-					if (f) {
-						a *= f;
-						b *= f;
-						c *= f;
-						D = getDiscriminant(a, b, c);
-					}
-				}
-				if (D >= -MACHINE_EPSILON) {
-					var Q = D < 0 ? 0 : sqrt(D),
-						R = b + (b < 0 ? -Q : Q);
-					if (R === 0) {
-						x1 = c / a;
-						x2 = -x1;
-					} else {
-						x1 = R / a;
-						x2 = c / R;
-					}
-				}
-			}
-			var count = 0,
-				boundless = min == null,
-				minB = min - EPSILON,
-				maxB = max + EPSILON;
-			if (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))
-				roots[count++] = boundless ? x1 : clamp(x1, min, max);
-			if (x2 !== x1
-					&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))
-				roots[count++] = boundless ? x2 : clamp(x2, min, max);
-			return count;
-		},
-
-		solveCubic: function(a, b, c, d, roots, min, max) {
-			var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),
-				x, b1, c2, qd, q;
-			if (f) {
-				a *= f;
-				b *= f;
-				c *= f;
-				d *= f;
-			}
-
-			function evaluate(x0) {
-				x = x0;
-				var tmp = a * x;
-				b1 = tmp + b;
-				c2 = b1 * x + c;
-				qd = (tmp + b1) * x + c2;
-				q = c2 * x + d;
-			}
-
-			if (abs(a) < EPSILON) {
-				a = b;
-				b1 = c;
-				c2 = d;
-				x = Infinity;
-			} else if (abs(d) < EPSILON) {
-				b1 = b;
-				c2 = c;
-				x = 0;
-			} else {
-				evaluate(-(b / a) / 3);
-				var t = q / a,
-					r = pow(abs(t), 1/3),
-					s = t < 0 ? -1 : 1,
-					td = -qd / a,
-					rd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,
-					x0 = x - s * rd;
-				if (x0 !== x) {
-					do {
-						evaluate(x0);
-						x0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);
-					} while (s * x0 > s * x);
-					if (abs(a) * x * x > abs(d / x)) {
-						c2 = -d / x;
-						b1 = (c2 - c) / x;
-					}
-				}
-			}
-			var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),
-				boundless = min == null;
-			if (isFinite(x) && (count === 0
-					|| count > 0 && x !== roots[0] && x !== roots[1])
-					&& (boundless || x > min - EPSILON && x < max + EPSILON))
-				roots[count++] = boundless ? x : clamp(x, min, max);
-			return count;
-		}
-	};
-};
-
-var UID = {
-	_id: 1,
-	_pools: {},
-
-	get: function(name) {
-		if (name) {
-			var pool = this._pools[name];
-			if (!pool)
-				pool = this._pools[name] = { _id: 1 };
-			return pool._id++;
-		} else {
-			return this._id++;
-		}
-	}
-};
-
-var Point = Base.extend({
-	_class: 'Point',
-	_readIndex: true,
-
-	initialize: function Point(arg0, arg1) {
-		var type = typeof arg0;
-		if (type === 'number') {
-			var hasY = typeof arg1 === 'number';
-			this.x = arg0;
-			this.y = hasY ? arg1 : arg0;
-			if (this.__read)
-				this.__read = hasY ? 2 : 1;
-		} else if (type === 'undefined' || arg0 === null) {
-			this.x = this.y = 0;
-			if (this.__read)
-				this.__read = arg0 === null ? 1 : 0;
-		} else {
-			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
-			if (Array.isArray(obj)) {
-				this.x = obj[0];
-				this.y = obj.length > 1 ? obj[1] : obj[0];
-			} else if ('x' in obj) {
-				this.x = obj.x;
-				this.y = obj.y;
-			} else if ('width' in obj) {
-				this.x = obj.width;
-				this.y = obj.height;
-			} else if ('angle' in obj) {
-				this.x = obj.length;
-				this.y = 0;
-				this.setAngle(obj.angle);
-			} else {
-				this.x = this.y = 0;
-				if (this.__read)
-					this.__read = 0;
-			}
-			if (this.__read)
-				this.__read = 1;
-		}
-	},
-
-	set: function(x, y) {
-		this.x = x;
-		this.y = y;
-		return this;
-	},
-
-	equals: function(point) {
-		return this === point || point
-				&& (this.x === point.x && this.y === point.y
-					|| Array.isArray(point)
-						&& this.x === point[0] && this.y === point[1])
-				|| false;
-	},
-
-	clone: function() {
-		return new Point(this.x, this.y);
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';
-	},
-
-	_serialize: function(options) {
-		var f = options.formatter;
-		return [f.number(this.x), f.number(this.y)];
-	},
-
-	getLength: function() {
-		return Math.sqrt(this.x * this.x + this.y * this.y);
-	},
-
-	setLength: function(length) {
-		if (this.isZero()) {
-			var angle = this._angle || 0;
-			this.set(
-				Math.cos(angle) * length,
-				Math.sin(angle) * length
-			);
-		} else {
-			var scale = length / this.getLength();
-			if (Numerical.isZero(scale))
-				this.getAngle();
-			this.set(
-				this.x * scale,
-				this.y * scale
-			);
-		}
-	},
-	getAngle: function() {
-		return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;
-	},
-
-	setAngle: function(angle) {
-		this.setAngleInRadians.call(this, angle * Math.PI / 180);
-	},
-
-	getAngleInDegrees: '#getAngle',
-	setAngleInDegrees: '#setAngle',
-
-	getAngleInRadians: function() {
-		if (!arguments.length) {
-			return this.isZero()
-					? this._angle || 0
-					: this._angle = Math.atan2(this.y, this.x);
-		} else {
-			var point = Point.read(arguments),
-				div = this.getLength() * point.getLength();
-			if (Numerical.isZero(div)) {
-				return NaN;
-			} else {
-				var a = this.dot(point) / div;
-				return Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);
-			}
-		}
-	},
-
-	setAngleInRadians: function(angle) {
-		this._angle = angle;
-		if (!this.isZero()) {
-			var length = this.getLength();
-			this.set(
-				Math.cos(angle) * length,
-				Math.sin(angle) * length
-			);
-		}
-	},
-
-	getQuadrant: function() {
-		return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
-	}
-}, {
-	beans: false,
-
-	getDirectedAngle: function() {
-		var point = Point.read(arguments);
-		return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;
-	},
-
-	getDistance: function() {
-		var point = Point.read(arguments),
-			x = point.x - this.x,
-			y = point.y - this.y,
-			d = x * x + y * y,
-			squared = Base.read(arguments);
-		return squared ? d : Math.sqrt(d);
-	},
-
-	normalize: function(length) {
-		if (length === undefined)
-			length = 1;
-		var current = this.getLength(),
-			scale = current !== 0 ? length / current : 0,
-			point = new Point(this.x * scale, this.y * scale);
-		if (scale >= 0)
-			point._angle = this._angle;
-		return point;
-	},
-
-	rotate: function(angle, center) {
-		if (angle === 0)
-			return this.clone();
-		angle = angle * Math.PI / 180;
-		var point = center ? this.subtract(center) : this,
-			sin = Math.sin(angle),
-			cos = Math.cos(angle);
-		point = new Point(
-			point.x * cos - point.y * sin,
-			point.x * sin + point.y * cos
-		);
-		return center ? point.add(center) : point;
-	},
-
-	transform: function(matrix) {
-		return matrix ? matrix._transformPoint(this) : this;
-	},
-
-	add: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x + point.x, this.y + point.y);
-	},
-
-	subtract: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x - point.x, this.y - point.y);
-	},
-
-	multiply: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x * point.x, this.y * point.y);
-	},
-
-	divide: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x / point.x, this.y / point.y);
-	},
-
-	modulo: function() {
-		var point = Point.read(arguments);
-		return new Point(this.x % point.x, this.y % point.y);
-	},
-
-	negate: function() {
-		return new Point(-this.x, -this.y);
-	},
-
-	isInside: function() {
-		return Rectangle.read(arguments).contains(this);
-	},
-
-	isClose: function() {
-		var point = Point.read(arguments),
-			tolerance = Base.read(arguments);
-		return this.getDistance(point) <= tolerance;
-	},
-
-	isCollinear: function() {
-		var point = Point.read(arguments);
-		return Point.isCollinear(this.x, this.y, point.x, point.y);
-	},
-
-	isColinear: '#isCollinear',
-
-	isOrthogonal: function() {
-		var point = Point.read(arguments);
-		return Point.isOrthogonal(this.x, this.y, point.x, point.y);
-	},
-
-	isZero: function() {
-		return Numerical.isZero(this.x) && Numerical.isZero(this.y);
-	},
-
-	isNaN: function() {
-		return isNaN(this.x) || isNaN(this.y);
-	},
-
-	dot: function() {
-		var point = Point.read(arguments);
-		return this.x * point.x + this.y * point.y;
-	},
-
-	cross: function() {
-		var point = Point.read(arguments);
-		return this.x * point.y - this.y * point.x;
-	},
-
-	project: function() {
-		var point = Point.read(arguments),
-			scale = point.isZero() ? 0 : this.dot(point) / point.dot(point);
-		return new Point(
-			point.x * scale,
-			point.y * scale
-		);
-	},
-
-	statics: {
-		min: function() {
-			var point1 = Point.read(arguments),
-				point2 = Point.read(arguments);
-			return new Point(
-				Math.min(point1.x, point2.x),
-				Math.min(point1.y, point2.y)
-			);
-		},
-
-		max: function() {
-			var point1 = Point.read(arguments),
-				point2 = Point.read(arguments);
-			return new Point(
-				Math.max(point1.x, point2.x),
-				Math.max(point1.y, point2.y)
-			);
-		},
-
-		random: function() {
-			return new Point(Math.random(), Math.random());
-		},
-
-		isCollinear: function(x1, y1, x2, y2) {
-			return Math.abs(x1 * y2 - y1 * x2)
-					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
-						* 1e-7;
-		},
-
-		isOrthogonal: function(x1, y1, x2, y2) {
-			return Math.abs(x1 * x2 + y1 * y2)
-					<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
-						* 1e-7;
-		}
-	}
-}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
-	var op = Math[key];
-	this[key] = function() {
-		return new Point(op(this.x), op(this.y));
-	};
-}, {}));
-
-var LinkedPoint = Point.extend({
-	initialize: function Point(x, y, owner, setter) {
-		this._x = x;
-		this._y = y;
-		this._owner = owner;
-		this._setter = setter;
-	},
-
-	set: function(x, y, _dontNotify) {
-		this._x = x;
-		this._y = y;
-		if (!_dontNotify)
-			this._owner[this._setter](this);
-		return this;
-	},
-
-	getX: function() {
-		return this._x;
-	},
-
-	setX: function(x) {
-		this._x = x;
-		this._owner[this._setter](this);
-	},
-
-	getY: function() {
-		return this._y;
-	},
-
-	setY: function(y) {
-		this._y = y;
-		this._owner[this._setter](this);
-	},
-
-	isSelected: function() {
-		return !!(this._owner._selection & this._getSelection());
-	},
-
-	setSelected: function(selected) {
-		this._owner.changeSelection(this._getSelection(), selected);
-	},
-
-	_getSelection: function() {
-		return this._setter === 'setPosition' ? 4 : 0;
-	}
-});
-
-var Size = Base.extend({
-	_class: 'Size',
-	_readIndex: true,
-
-	initialize: function Size(arg0, arg1) {
-		var type = typeof arg0;
-		if (type === 'number') {
-			var hasHeight = typeof arg1 === 'number';
-			this.width = arg0;
-			this.height = hasHeight ? arg1 : arg0;
-			if (this.__read)
-				this.__read = hasHeight ? 2 : 1;
-		} else if (type === 'undefined' || arg0 === null) {
-			this.width = this.height = 0;
-			if (this.__read)
-				this.__read = arg0 === null ? 1 : 0;
-		} else {
-			var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
-			if (Array.isArray(obj)) {
-				this.width = obj[0];
-				this.height = obj.length > 1 ? obj[1] : obj[0];
-			} else if ('width' in obj) {
-				this.width = obj.width;
-				this.height = obj.height;
-			} else if ('x' in obj) {
-				this.width = obj.x;
-				this.height = obj.y;
-			} else {
-				this.width = this.height = 0;
-				if (this.__read)
-					this.__read = 0;
-			}
-			if (this.__read)
-				this.__read = 1;
-		}
-	},
-
-	set: function(width, height) {
-		this.width = width;
-		this.height = height;
-		return this;
-	},
-
-	equals: function(size) {
-		return size === this || size && (this.width === size.width
-				&& this.height === size.height
-				|| Array.isArray(size) && this.width === size[0]
-					&& this.height === size[1]) || false;
-	},
-
-	clone: function() {
-		return new Size(this.width, this.height);
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '{ width: ' + f.number(this.width)
-				+ ', height: ' + f.number(this.height) + ' }';
-	},
-
-	_serialize: function(options) {
-		var f = options.formatter;
-		return [f.number(this.width),
-				f.number(this.height)];
-	},
-
-	add: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width + size.width, this.height + size.height);
-	},
-
-	subtract: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width - size.width, this.height - size.height);
-	},
-
-	multiply: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width * size.width, this.height * size.height);
-	},
-
-	divide: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width / size.width, this.height / size.height);
-	},
-
-	modulo: function() {
-		var size = Size.read(arguments);
-		return new Size(this.width % size.width, this.height % size.height);
-	},
-
-	negate: function() {
-		return new Size(-this.width, -this.height);
-	},
-
-	isZero: function() {
-		return Numerical.isZero(this.width) && Numerical.isZero(this.height);
-	},
-
-	isNaN: function() {
-		return isNaN(this.width) || isNaN(this.height);
-	},
-
-	statics: {
-		min: function(size1, size2) {
-			return new Size(
-				Math.min(size1.width, size2.width),
-				Math.min(size1.height, size2.height));
-		},
-
-		max: function(size1, size2) {
-			return new Size(
-				Math.max(size1.width, size2.width),
-				Math.max(size1.height, size2.height));
-		},
-
-		random: function() {
-			return new Size(Math.random(), Math.random());
-		}
-	}
-}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
-	var op = Math[key];
-	this[key] = function() {
-		return new Size(op(this.width), op(this.height));
-	};
-}, {}));
-
-var LinkedSize = Size.extend({
-	initialize: function Size(width, height, owner, setter) {
-		this._width = width;
-		this._height = height;
-		this._owner = owner;
-		this._setter = setter;
-	},
-
-	set: function(width, height, _dontNotify) {
-		this._width = width;
-		this._height = height;
-		if (!_dontNotify)
-			this._owner[this._setter](this);
-		return this;
-	},
-
-	getWidth: function() {
-		return this._width;
-	},
-
-	setWidth: function(width) {
-		this._width = width;
-		this._owner[this._setter](this);
-	},
-
-	getHeight: function() {
-		return this._height;
-	},
-
-	setHeight: function(height) {
-		this._height = height;
-		this._owner[this._setter](this);
-	}
-});
-
-var Rectangle = Base.extend({
-	_class: 'Rectangle',
-	_readIndex: true,
-	beans: true,
-
-	initialize: function Rectangle(arg0, arg1, arg2, arg3) {
-		var type = typeof arg0,
-			read = 0;
-		if (type === 'number') {
-			this.x = arg0;
-			this.y = arg1;
-			this.width = arg2;
-			this.height = arg3;
-			read = 4;
-		} else if (type === 'undefined' || arg0 === null) {
-			this.x = this.y = this.width = this.height = 0;
-			read = arg0 === null ? 1 : 0;
-		} else if (arguments.length === 1) {
-			if (Array.isArray(arg0)) {
-				this.x = arg0[0];
-				this.y = arg0[1];
-				this.width = arg0[2];
-				this.height = arg0[3];
-				read = 1;
-			} else if (arg0.x !== undefined || arg0.width !== undefined) {
-				this.x = arg0.x || 0;
-				this.y = arg0.y || 0;
-				this.width = arg0.width || 0;
-				this.height = arg0.height || 0;
-				read = 1;
-			} else if (arg0.from === undefined && arg0.to === undefined) {
-				this.x = this.y = this.width = this.height = 0;
-				this._set(arg0);
-				read = 1;
-			}
-		}
-		if (!read) {
-			var point = Point.readNamed(arguments, 'from'),
-				next = Base.peek(arguments);
-			this.x = point.x;
-			this.y = point.y;
-			if (next && next.x !== undefined || Base.hasNamed(arguments, 'to')) {
-				var to = Point.readNamed(arguments, 'to');
-				this.width = to.x - point.x;
-				this.height = to.y - point.y;
-				if (this.width < 0) {
-					this.x = to.x;
-					this.width = -this.width;
-				}
-				if (this.height < 0) {
-					this.y = to.y;
-					this.height = -this.height;
-				}
-			} else {
-				var size = Size.read(arguments);
-				this.width = size.width;
-				this.height = size.height;
-			}
-			read = arguments.__index;
-		}
-		if (this.__read)
-			this.__read = read;
-	},
-
-	set: function(x, y, width, height) {
-		this.x = x;
-		this.y = y;
-		this.width = width;
-		this.height = height;
-		return this;
-	},
-
-	clone: function() {
-		return new Rectangle(this.x, this.y, this.width, this.height);
-	},
-
-	equals: function(rect) {
-		var rt = Base.isPlainValue(rect)
-				? Rectangle.read(arguments)
-				: rect;
-		return rt === this
-				|| rt && this.x === rt.x && this.y === rt.y
-					&& this.width === rt.width && this.height === rt.height
-				|| false;
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '{ x: ' + f.number(this.x)
-				+ ', y: ' + f.number(this.y)
-				+ ', width: ' + f.number(this.width)
-				+ ', height: ' + f.number(this.height)
-				+ ' }';
-	},
-
-	_serialize: function(options) {
-		var f = options.formatter;
-		return [f.number(this.x),
-				f.number(this.y),
-				f.number(this.width),
-				f.number(this.height)];
-	},
-
-	getPoint: function(_dontLink) {
-		var ctor = _dontLink ? Point : LinkedPoint;
-		return new ctor(this.x, this.y, this, 'setPoint');
-	},
-
-	setPoint: function() {
-		var point = Point.read(arguments);
-		this.x = point.x;
-		this.y = point.y;
-	},
-
-	getSize: function(_dontLink) {
-		var ctor = _dontLink ? Size : LinkedSize;
-		return new ctor(this.width, this.height, this, 'setSize');
-	},
-
-	setSize: function() {
-		var size = Size.read(arguments);
-		if (this._fixX)
-			this.x += (this.width - size.width) * this._fixX;
-		if (this._fixY)
-			this.y += (this.height - size.height) * this._fixY;
-		this.width = size.width;
-		this.height = size.height;
-		this._fixW = 1;
-		this._fixH = 1;
-	},
-
-	getLeft: function() {
-		return this.x;
-	},
-
-	setLeft: function(left) {
-		if (!this._fixW)
-			this.width -= left - this.x;
-		this.x = left;
-		this._fixX = 0;
-	},
-
-	getTop: function() {
-		return this.y;
-	},
-
-	setTop: function(top) {
-		if (!this._fixH)
-			this.height -= top - this.y;
-		this.y = top;
-		this._fixY = 0;
-	},
-
-	getRight: function() {
-		return this.x + this.width;
-	},
-
-	setRight: function(right) {
-		if (this._fixX !== undefined && this._fixX !== 1)
-			this._fixW = 0;
-		if (this._fixW)
-			this.x = right - this.width;
-		else
-			this.width = right - this.x;
-		this._fixX = 1;
-	},
-
-	getBottom: function() {
-		return this.y + this.height;
-	},
-
-	setBottom: function(bottom) {
-		if (this._fixY !== undefined && this._fixY !== 1)
-			this._fixH = 0;
-		if (this._fixH)
-			this.y = bottom - this.height;
-		else
-			this.height = bottom - this.y;
-		this._fixY = 1;
-	},
-
-	getCenterX: function() {
-		return this.x + this.width * 0.5;
-	},
-
-	setCenterX: function(x) {
-		this.x = x - this.width * 0.5;
-		this._fixX = 0.5;
-	},
-
-	getCenterY: function() {
-		return this.y + this.height * 0.5;
-	},
-
-	setCenterY: function(y) {
-		this.y = y - this.height * 0.5;
-		this._fixY = 0.5;
-	},
-
-	getCenter: function(_dontLink) {
-		var ctor = _dontLink ? Point : LinkedPoint;
-		return new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');
-	},
-
-	setCenter: function() {
-		var point = Point.read(arguments);
-		this.setCenterX(point.x);
-		this.setCenterY(point.y);
-		return this;
-	},
-
-	getArea: function() {
-		return this.width * this.height;
-	},
-
-	isEmpty: function() {
-		return this.width === 0 || this.height === 0;
-	},
-
-	contains: function(arg) {
-		return arg && arg.width !== undefined
-				|| (Array.isArray(arg) ? arg : arguments).length === 4
-				? this._containsRectangle(Rectangle.read(arguments))
-				: this._containsPoint(Point.read(arguments));
-	},
-
-	_containsPoint: function(point) {
-		var x = point.x,
-			y = point.y;
-		return x >= this.x && y >= this.y
-				&& x <= this.x + this.width
-				&& y <= this.y + this.height;
-	},
-
-	_containsRectangle: function(rect) {
-		var x = rect.x,
-			y = rect.y;
-		return x >= this.x && y >= this.y
-				&& x + rect.width <= this.x + this.width
-				&& y + rect.height <= this.y + this.height;
-	},
-
-	intersects: function() {
-		var rect = Rectangle.read(arguments);
-		return rect.x + rect.width > this.x
-				&& rect.y + rect.height > this.y
-				&& rect.x < this.x + this.width
-				&& rect.y < this.y + this.height;
-	},
-
-	touches: function() {
-		var rect = Rectangle.read(arguments);
-		return rect.x + rect.width >= this.x
-				&& rect.y + rect.height >= this.y
-				&& rect.x <= this.x + this.width
-				&& rect.y <= this.y + this.height;
-	},
-
-	intersect: function() {
-		var rect = Rectangle.read(arguments),
-			x1 = Math.max(this.x, rect.x),
-			y1 = Math.max(this.y, rect.y),
-			x2 = Math.min(this.x + this.width, rect.x + rect.width),
-			y2 = Math.min(this.y + this.height, rect.y + rect.height);
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	},
-
-	unite: function() {
-		var rect = Rectangle.read(arguments),
-			x1 = Math.min(this.x, rect.x),
-			y1 = Math.min(this.y, rect.y),
-			x2 = Math.max(this.x + this.width, rect.x + rect.width),
-			y2 = Math.max(this.y + this.height, rect.y + rect.height);
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	},
-
-	include: function() {
-		var point = Point.read(arguments);
-		var x1 = Math.min(this.x, point.x),
-			y1 = Math.min(this.y, point.y),
-			x2 = Math.max(this.x + this.width, point.x),
-			y2 = Math.max(this.y + this.height, point.y);
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	},
-
-	expand: function() {
-		var amount = Size.read(arguments),
-			hor = amount.width,
-			ver = amount.height;
-		return new Rectangle(this.x - hor / 2, this.y - ver / 2,
-				this.width + hor, this.height + ver);
-	},
-
-	scale: function(hor, ver) {
-		return this.expand(this.width * hor - this.width,
-				this.height * (ver === undefined ? hor : ver) - this.height);
-	}
-}, Base.each([
-		['Top', 'Left'], ['Top', 'Right'],
-		['Bottom', 'Left'], ['Bottom', 'Right'],
-		['Left', 'Center'], ['Top', 'Center'],
-		['Right', 'Center'], ['Bottom', 'Center']
-	],
-	function(parts, index) {
-		var part = parts.join(''),
-			xFirst = /^[RL]/.test(part);
-		if (index >= 4)
-			parts[1] += xFirst ? 'Y' : 'X';
-		var x = parts[xFirst ? 0 : 1],
-			y = parts[xFirst ? 1 : 0],
-			getX = 'get' + x,
-			getY = 'get' + y,
-			setX = 'set' + x,
-			setY = 'set' + y,
-			get = 'get' + part,
-			set = 'set' + part;
-		this[get] = function(_dontLink) {
-			var ctor = _dontLink ? Point : LinkedPoint;
-			return new ctor(this[getX](), this[getY](), this, set);
-		};
-		this[set] = function() {
-			var point = Point.read(arguments);
-			this[setX](point.x);
-			this[setY](point.y);
-		};
-	}, {
-		beans: true
-	}
-));
-
-var LinkedRectangle = Rectangle.extend({
-	initialize: function Rectangle(x, y, width, height, owner, setter) {
-		this.set(x, y, width, height, true);
-		this._owner = owner;
-		this._setter = setter;
-	},
-
-	set: function(x, y, width, height, _dontNotify) {
-		this._x = x;
-		this._y = y;
-		this._width = width;
-		this._height = height;
-		if (!_dontNotify)
-			this._owner[this._setter](this);
-		return this;
-	}
-},
-new function() {
-	var proto = Rectangle.prototype;
-
-	return Base.each(['x', 'y', 'width', 'height'], function(key) {
-		var part = Base.capitalize(key),
-			internal = '_' + key;
-		this['get' + part] = function() {
-			return this[internal];
-		};
-
-		this['set' + part] = function(value) {
-			this[internal] = value;
-			if (!this._dontNotify)
-				this._owner[this._setter](this);
-		};
-	}, Base.each(['Point', 'Size', 'Center',
-			'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',
-			'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
-			'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],
-		function(key) {
-			var name = 'set' + key;
-			this[name] = function() {
-				this._dontNotify = true;
-				proto[name].apply(this, arguments);
-				this._dontNotify = false;
-				this._owner[this._setter](this);
-			};
-		}, {
-			isSelected: function() {
-				return !!(this._owner._selection & 2);
-			},
-
-			setSelected: function(selected) {
-				var owner = this._owner;
-				if (owner.changeSelection) {
-					owner.changeSelection(2, selected);
-				}
-			}
-		})
-	);
-});
-
-var Matrix = Base.extend({
-	_class: 'Matrix',
-
-	initialize: function Matrix(arg) {
-		var count = arguments.length,
-			ok = true;
-		if (count === 6) {
-			this.set.apply(this, arguments);
-		} else if (count === 1) {
-			if (arg instanceof Matrix) {
-				this.set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty);
-			} else if (Array.isArray(arg)) {
-				this.set.apply(this, arg);
-			} else {
-				ok = false;
-			}
-		} else if (count === 0) {
-			this.reset();
-		} else {
-			ok = false;
-		}
-		if (!ok) {
-			throw new Error('Unsupported matrix parameters');
-		}
-	},
-
-	set: function(a, b, c, d, tx, ty, _dontNotify) {
-		this._a = a;
-		this._b = b;
-		this._c = c;
-		this._d = d;
-		this._tx = tx;
-		this._ty = ty;
-		if (!_dontNotify)
-			this._changed();
-		return this;
-	},
-
-	_serialize: function(options, dictionary) {
-		return Base.serialize(this.getValues(), options, true, dictionary);
-	},
-
-	_changed: function() {
-		var owner = this._owner;
-		if (owner) {
-			if (owner._applyMatrix) {
-				owner.transform(null, true);
-			} else {
-				owner._changed(9);
-			}
-		}
-	},
-
-	clone: function() {
-		return new Matrix(this._a, this._b, this._c, this._d,
-				this._tx, this._ty);
-	},
-
-	equals: function(mx) {
-		return mx === this || mx && this._a === mx._a && this._b === mx._b
-				&& this._c === mx._c && this._d === mx._d
-				&& this._tx === mx._tx && this._ty === mx._ty;
-	},
-
-	toString: function() {
-		var f = Formatter.instance;
-		return '[[' + [f.number(this._a), f.number(this._c),
-					f.number(this._tx)].join(', ') + '], ['
-				+ [f.number(this._b), f.number(this._d),
-					f.number(this._ty)].join(', ') + ']]';
-	},
-
-	reset: function(_dontNotify) {
-		this._a = this._d = 1;
-		this._b = this._c = this._tx = this._ty = 0;
-		if (!_dontNotify)
-			this._changed();
-		return this;
-	},
-
-	apply: function(recursively, _setApplyMatrix) {
-		var owner = this._owner;
-		if (owner) {
-			owner.transform(null, true, Base.pick(recursively, true),
-					_setApplyMatrix);
-			return this.isIdentity();
-		}
-		return false;
-	},
-
-	translate: function() {
-		var point = Point.read(arguments),
-			x = point.x,
-			y = point.y;
-		this._tx += x * this._a + y * this._c;
-		this._ty += x * this._b + y * this._d;
-		this._changed();
-		return this;
-	},
-
-	scale: function() {
-		var scale = Point.read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		if (center)
-			this.translate(center);
-		this._a *= scale.x;
-		this._b *= scale.x;
-		this._c *= scale.y;
-		this._d *= scale.y;
-		if (center)
-			this.translate(center.negate());
-		this._changed();
-		return this;
-	},
-
-	rotate: function(angle ) {
-		angle *= Math.PI / 180;
-		var center = Point.read(arguments, 1),
-			x = center.x,
-			y = center.y,
-			cos = Math.cos(angle),
-			sin = Math.sin(angle),
-			tx = x - x * cos + y * sin,
-			ty = y - x * sin - y * cos,
-			a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d;
-		this._a = cos * a + sin * c;
-		this._b = cos * b + sin * d;
-		this._c = -sin * a + cos * c;
-		this._d = -sin * b + cos * d;
-		this._tx += tx * a + ty * c;
-		this._ty += tx * b + ty * d;
-		this._changed();
-		return this;
-	},
-
-	shear: function() {
-		var shear = Point.read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		if (center)
-			this.translate(center);
-		var a = this._a,
-			b = this._b;
-		this._a += shear.y * this._c;
-		this._b += shear.y * this._d;
-		this._c += shear.x * a;
-		this._d += shear.x * b;
-		if (center)
-			this.translate(center.negate());
-		this._changed();
-		return this;
-	},
-
-	skew: function() {
-		var skew = Point.read(arguments),
-			center = Point.read(arguments, 0, { readNull: true }),
-			toRadians = Math.PI / 180,
-			shear = new Point(Math.tan(skew.x * toRadians),
-				Math.tan(skew.y * toRadians));
-		return this.shear(shear, center);
-	},
-
-	append: function(mx) {
-		if (mx) {
-			var a1 = this._a,
-				b1 = this._b,
-				c1 = this._c,
-				d1 = this._d,
-				a2 = mx._a,
-				b2 = mx._c,
-				c2 = mx._b,
-				d2 = mx._d,
-				tx2 = mx._tx,
-				ty2 = mx._ty;
-			this._a = a2 * a1 + c2 * c1;
-			this._c = b2 * a1 + d2 * c1;
-			this._b = a2 * b1 + c2 * d1;
-			this._d = b2 * b1 + d2 * d1;
-			this._tx += tx2 * a1 + ty2 * c1;
-			this._ty += tx2 * b1 + ty2 * d1;
-			this._changed();
-		}
-		return this;
-	},
-
-	prepend: function(mx) {
-		if (mx) {
-			var a1 = this._a,
-				b1 = this._b,
-				c1 = this._c,
-				d1 = this._d,
-				tx1 = this._tx,
-				ty1 = this._ty,
-				a2 = mx._a,
-				b2 = mx._c,
-				c2 = mx._b,
-				d2 = mx._d,
-				tx2 = mx._tx,
-				ty2 = mx._ty;
-			this._a = a2 * a1 + b2 * b1;
-			this._c = a2 * c1 + b2 * d1;
-			this._b = c2 * a1 + d2 * b1;
-			this._d = c2 * c1 + d2 * d1;
-			this._tx = a2 * tx1 + b2 * ty1 + tx2;
-			this._ty = c2 * tx1 + d2 * ty1 + ty2;
-			this._changed();
-		}
-		return this;
-	},
-
-	appended: function(mx) {
-		return this.clone().append(mx);
-	},
-
-	prepended: function(mx) {
-		return this.clone().prepend(mx);
-	},
-
-	invert: function() {
-		var a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d,
-			tx = this._tx,
-			ty = this._ty,
-			det = a * d - b * c,
-			res = null;
-		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
-			this._a = d / det;
-			this._b = -b / det;
-			this._c = -c / det;
-			this._d = a / det;
-			this._tx = (c * ty - d * tx) / det;
-			this._ty = (b * tx - a * ty) / det;
-			res = this;
-		}
-		return res;
-	},
-
-	inverted: function() {
-		return this.clone().invert();
-	},
-
-	concatenate: '#append',
-	preConcatenate: '#prepend',
-	chain: '#appended',
-
-	_shiftless: function() {
-		return new Matrix(this._a, this._b, this._c, this._d, 0, 0);
-	},
-
-	_orNullIfIdentity: function() {
-		return this.isIdentity() ? null : this;
-	},
-
-	isIdentity: function() {
-		return this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1
-				&& this._tx === 0 && this._ty === 0;
-	},
-
-	isInvertible: function() {
-		var det = this._a * this._d - this._c * this._b;
-		return det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);
-	},
-
-	isSingular: function() {
-		return !this.isInvertible();
-	},
-
-	transform: function( src, dst, count) {
-		return arguments.length < 3
-			? this._transformPoint(Point.read(arguments))
-			: this._transformCoordinates(src, dst, count);
-	},
-
-	_transformPoint: function(point, dest, _dontNotify) {
-		var x = point.x,
-			y = point.y;
-		if (!dest)
-			dest = new Point();
-		return dest.set(
-				x * this._a + y * this._c + this._tx,
-				x * this._b + y * this._d + this._ty,
-				_dontNotify);
-	},
-
-	_transformCoordinates: function(src, dst, count) {
-		for (var i = 0, max = 2 * count; i < max; i += 2) {
-			var x = src[i],
-				y = src[i + 1];
-			dst[i] = x * this._a + y * this._c + this._tx;
-			dst[i + 1] = x * this._b + y * this._d + this._ty;
-		}
-		return dst;
-	},
-
-	_transformCorners: function(rect) {
-		var x1 = rect.x,
-			y1 = rect.y,
-			x2 = x1 + rect.width,
-			y2 = y1 + rect.height,
-			coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];
-		return this._transformCoordinates(coords, coords, 4);
-	},
-
-	_transformBounds: function(bounds, dest, _dontNotify) {
-		var coords = this._transformCorners(bounds),
-			min = coords.slice(0, 2),
-			max = min.slice();
-		for (var i = 2; i < 8; i++) {
-			var val = coords[i],
-				j = i & 1;
-			if (val < min[j]) {
-				min[j] = val;
-			} else if (val > max[j]) {
-				max[j] = val;
-			}
-		}
-		if (!dest)
-			dest = new Rectangle();
-		return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1],
-				_dontNotify);
-	},
-
-	inverseTransform: function() {
-		return this._inverseTransform(Point.read(arguments));
-	},
-
-	_inverseTransform: function(point, dest, _dontNotify) {
-		var a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d,
-			tx = this._tx,
-			ty = this._ty,
-			det = a * d - b * c,
-			res = null;
-		if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
-			var x = point.x - this._tx,
-				y = point.y - this._ty;
-			if (!dest)
-				dest = new Point();
-			res = dest.set(
-					(x * d - y * c) / det,
-					(y * a - x * b) / det,
-					_dontNotify);
-		}
-		return res;
-	},
-
-	decompose: function() {
-		var a = this._a,
-			b = this._b,
-			c = this._c,
-			d = this._d,
-			det = a * d - b * c,
-			sqrt = Math.sqrt,
-			atan2 = Math.atan2,
-			degrees = 180 / Math.PI,
-			rotate,
-			scale,
-			skew;
-		if (a !== 0 || b !== 0) {
-			var r = sqrt(a * a + b * b);
-			rotate = Math.acos(a / r) * (b > 0 ? 1 : -1);
-			scale = [r, det / r];
-			skew = [atan2(a * c + b * d, r * r), 0];
-		} else if (c !== 0 || d !== 0) {
-			var s = sqrt(c * c + d * d);
-			rotate = Math.asin(c / s)  * (d > 0 ? 1 : -1);
-			scale = [det / s, s];
-			skew = [0, atan2(a * c + b * d, s * s)];
-		} else {
-			rotate = 0;
-			skew = scale = [0, 0];
-		}
-		return {
-			translation: this.getTranslation(),
-			rotation: rotate * degrees,
-			scaling: new Point(scale),
-			skewing: new Point(skew[0] * degrees, skew[1] * degrees)
-		};
-	},
-
-	getValues: function() {
-		return [ this._a, this._b, this._c, this._d, this._tx, this._ty ];
-	},
-
-	getTranslation: function() {
-		return new Point(this._tx, this._ty);
-	},
-
-	getScaling: function() {
-		return (this.decompose() || {}).scaling;
-	},
-
-	getRotation: function() {
-		return (this.decompose() || {}).rotation;
-	},
-
-	applyToContext: function(ctx) {
-		if (!this.isIdentity()) {
-			ctx.transform(this._a, this._b, this._c, this._d,
-					this._tx, this._ty);
-		}
-	}
-}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {
-	var part = Base.capitalize(key),
-		prop = '_' + key;
-	this['get' + part] = function() {
-		return this[prop];
-	};
-	this['set' + part] = function(value) {
-		this[prop] = value;
-		this._changed();
-	};
-}, {}));
-
-var Line = Base.extend({
-	_class: 'Line',
-
-	initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
-		var asVector = false;
-		if (arguments.length >= 4) {
-			this._px = arg0;
-			this._py = arg1;
-			this._vx = arg2;
-			this._vy = arg3;
-			asVector = arg4;
-		} else {
-			this._px = arg0.x;
-			this._py = arg0.y;
-			this._vx = arg1.x;
-			this._vy = arg1.y;
-			asVector = arg2;
-		}
-		if (!asVector) {
-			this._vx -= this._px;
-			this._vy -= this._py;
-		}
-	},
-
-	getPoint: function() {
-		return new Point(this._px, this._py);
-	},
-
-	getVector: function() {
-		return new Point(this._vx, this._vy);
-	},
-
-	getLength: function() {
-		return this.getVector().getLength();
-	},
-
-	intersect: function(line, isInfinite) {
-		return Line.intersect(
-				this._px, this._py, this._vx, this._vy,
-				line._px, line._py, line._vx, line._vy,
-				true, isInfinite);
-	},
-
-	getSide: function(point, isInfinite) {
-		return Line.getSide(
-				this._px, this._py, this._vx, this._vy,
-				point.x, point.y, true, isInfinite);
-	},
-
-	getDistance: function(point) {
-		return Math.abs(Line.getSignedDistance(
-				this._px, this._py, this._vx, this._vy,
-				point.x, point.y, true));
-	},
-
-	isCollinear: function(line) {
-		return Point.isCollinear(this._vx, this._vy, line._vx, line._vy);
-	},
-
-	isOrthogonal: function(line) {
-		return Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);
-	},
-
-	statics: {
-		intersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,
-				isInfinite) {
-			if (!asVector) {
-				v1x -= p1x;
-				v1y -= p1y;
-				v2x -= p2x;
-				v2y -= p2y;
-			}
-			var cross = v1x * v2y - v1y * v2x;
-			if (!Numerical.isZero(cross)) {
-				var dx = p1x - p2x,
-					dy = p1y - p2y,
-					u1 = (v2x * dy - v2y * dx) / cross,
-					u2 = (v1x * dy - v1y * dx) / cross,
-					epsilon = 1e-12,
-					uMin = -epsilon,
-					uMax = 1 + epsilon;
-				if (isInfinite
-						|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {
-					if (!isInfinite) {
-						u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;
-					}
-					return new Point(
-							p1x + u1 * v1x,
-							p1y + u1 * v1y);
-				}
-			}
-		},
-
-		getSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {
-			if (!asVector) {
-				vx -= px;
-				vy -= py;
-			}
-			var v2x = x - px,
-				v2y = y - py,
-				ccw = v2x * vy - v2y * vx;
-			if (ccw === 0 && !isInfinite) {
-				ccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);
-				if (ccw >= 0 && ccw <= 1)
-					ccw = 0;
-			}
-			return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
-		},
-
-		getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
-			if (!asVector) {
-				vx -= px;
-				vy -= py;
-			}
-			return vx === 0 ? vy > 0 ? x - px : px - x
-				 : vy === 0 ? vx < 0 ? y - py : py - y
-				 : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);
-		}
-	}
-});
-
-var Project = PaperScopeItem.extend({
-	_class: 'Project',
-	_list: 'projects',
-	_reference: 'project',
-	_compactSerialize: true,
-
-	initialize: function Project(element) {
-		PaperScopeItem.call(this, true);
-		this._children = [];
-		this._namedChildren = {};
-		this._activeLayer = null;
-		this._currentStyle = new Style(null, null, this);
-		this._view = View.create(this,
-				element || CanvasProvider.getCanvas(1, 1));
-		this._selectionItems = {};
-		this._selectionCount = 0;
-		this._updateVersion = 0;
-	},
-
-	_serialize: function(options, dictionary) {
-		return Base.serialize(this._children, options, true, dictionary);
-	},
-
-	_changed: function(flags, item) {
-		if (flags & 1) {
-			var view = this._view;
-			if (view) {
-				view._needsUpdate = true;
-				if (!view._requested && view._autoUpdate)
-					view.requestUpdate();
-			}
-		}
-		var changes = this._changes;
-		if (changes && item) {
-			var changesById = this._changesById,
-				id = item._id,
-				entry = changesById[id];
-			if (entry) {
-				entry.flags |= flags;
-			} else {
-				changes.push(changesById[id] = { item: item, flags: flags });
-			}
-		}
-	},
-
-	clear: function() {
-		var children = this._children;
-		for (var i = children.length - 1; i >= 0; i--)
-			children[i].remove();
-	},
-
-	isEmpty: function() {
-		return this._children.length === 0;
-	},
-
-	remove: function remove() {
-		if (!remove.base.call(this))
-			return false;
-		if (this._view)
-			this._view.remove();
-		return true;
-	},
-
-	getView: function() {
-		return this._view;
-	},
-
-	getCurrentStyle: function() {
-		return this._currentStyle;
-	},
-
-	setCurrentStyle: function(style) {
-		this._currentStyle.initialize(style);
-	},
-
-	getIndex: function() {
-		return this._index;
-	},
-
-	getOptions: function() {
-		return this._scope.settings;
-	},
-
-	getLayers: function() {
-		return this._children;
-	},
-
-	getActiveLayer: function() {
-		return this._activeLayer || new Layer({ project: this, insert: true });
-	},
-
-	getSymbolDefinitions: function() {
-		var definitions = [],
-			ids = {};
-		this.getItems({
-			class: SymbolItem,
-			match: function(item) {
-				var definition = item._definition,
-					id = definition._id;
-				if (!ids[id]) {
-					ids[id] = true;
-					definitions.push(definition);
-				}
-				return false;
-			}
-		});
-		return definitions;
-	},
-
-	getSymbols: 'getSymbolDefinitions',
-
-	getSelectedItems: function() {
-		var selectionItems = this._selectionItems,
-			items = [];
-		for (var id in selectionItems) {
-			var item = selectionItems[id],
-				selection = item._selection;
-			if (selection & 1 && item.isInserted()) {
-				items.push(item);
-			} else if (!selection) {
-				this._updateSelection(item);
-			}
-		}
-		return items;
-	},
-
-	_updateSelection: function(item) {
-		var id = item._id,
-			selectionItems = this._selectionItems;
-		if (item._selection) {
-			if (selectionItems[id] !== item) {
-				this._selectionCount++;
-				selectionItems[id] = item;
-			}
-		} else if (selectionItems[id] === item) {
-			this._selectionCount--;
-			delete selectionItems[id];
-		}
-	},
-
-	selectAll: function() {
-		var children = this._children;
-		for (var i = 0, l = children.length; i < l; i++)
-			children[i].setFullySelected(true);
-	},
-
-	deselectAll: function() {
-		var selectionItems = this._selectionItems;
-		for (var i in selectionItems)
-			selectionItems[i].setFullySelected(false);
-	},
-
-	addLayer: function(layer) {
-		return this.insertLayer(undefined, layer);
-	},
-
-	insertLayer: function(index, layer) {
-		if (layer instanceof Layer) {
-			layer._remove(false, true);
-			Base.splice(this._children, [layer], index, 0);
-			layer._setProject(this, true);
-			var name = layer._name;
-			if (name)
-				layer.setName(name);
-			if (this._changes)
-				layer._changed(5);
-			if (!this._activeLayer)
-				this._activeLayer = layer;
-		} else {
-			layer = null;
-		}
-		return layer;
-	},
-
-	_insertItem: function(index, item, _preserve, _created) {
-		item = this.insertLayer(index, item)
-				|| (this._activeLayer || this._insertItem(undefined,
-						new Layer(Item.NO_INSERT), true, true))
-						.insertChild(index, item, _preserve);
-		if (_created && item.activate)
-			item.activate();
-		return item;
-	},
-
-	getItems: function(options) {
-		return Item._getItems(this, options);
-	},
-
-	getItem: function(options) {
-		return Item._getItems(this, options, null, null, true)[0] || null;
-	},
-
-	importJSON: function(json) {
-		this.activate();
-		var layer = this._activeLayer;
-		return Base.importJSON(json, layer && layer.isEmpty() && layer);
-	},
-
-	removeOn: function(type) {
-		var sets = this._removeSets;
-		if (sets) {
-			if (type === 'mouseup')
-				sets.mousedrag = null;
-			var set = sets[type];
-			if (set) {
-				for (var id in set) {
-					var item = set[id];
-					for (var key in sets) {
-						var other = sets[key];
-						if (other && other != set)
-							delete other[item._id];
-					}
-					item.remove();
-				}
-				sets[type] = null;
-			}
-		}
-	},
-
-	draw: function(ctx, matrix, pixelRatio) {
-		this._updateVersion++;
-		ctx.save();
-		matrix.applyToContext(ctx);
-		var children = this._children,
-			param = new Base({
-				offset: new Point(0, 0),
-				pixelRatio: pixelRatio,
-				viewMatrix: matrix.isIdentity() ? null : matrix,
-				matrices: [new Matrix()],
-				updateMatrix: true
-			});
-		for (var i = 0, l = children.length; i < l; i++) {
-			children[i].draw(ctx, param);
-		}
-		ctx.restore();
-
-		if (this._selectionCount > 0) {
-			ctx.save();
-			ctx.strokeWidth = 1;
-			var items = this._selectionItems,
-				size = this._scope.settings.handleSize,
-				version = this._updateVersion;
-			for (var id in items) {
-				items[id]._drawSelection(ctx, matrix, size, items, version);
-			}
-			ctx.restore();
-		}
-	}
-});
-
-var Item = Base.extend(Emitter, {
-	statics: {
-		extend: function extend(src) {
-			if (src._serializeFields)
-				src._serializeFields = Base.set({},
-					this.prototype._serializeFields, src._serializeFields);
-			return extend.base.apply(this, arguments);
-		},
-
-		NO_INSERT: { insert: false }
-	},
-
-	_class: 'Item',
-	_name: null,
-	_applyMatrix: true,
-	_canApplyMatrix: true,
-	_canScaleStroke: false,
-	_pivot: null,
-	_visible: true,
-	_blendMode: 'normal',
-	_opacity: 1,
-	_locked: false,
-	_guide: false,
-	_clipMask: false,
-	_selection: 0,
-	_selectBounds: true,
-	_selectChildren: false,
-	_serializeFields: {
-		name: null,
-		applyMatrix: null,
-		matrix: new Matrix(),
-		pivot: null,
-		visible: true,
-		blendMode: 'normal',
-		opacity: 1,
-		locked: false,
-		guide: false,
-		clipMask: false,
-		selected: false,
-		data: {}
-	}
-},
-new function() {
-	var handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
-			'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];
-	return Base.each(handlers,
-		function(name) {
-			this._events[name] = {
-				install: function(type) {
-					this.getView()._countItemEvent(type, 1);
-				},
-
-				uninstall: function(type) {
-					this.getView()._countItemEvent(type, -1);
-				}
-			};
-		}, {
-			_events: {
-				onFrame: {
-					install: function() {
-						this.getView()._animateItem(this, true);
-					},
-
-					uninstall: function() {
-						this.getView()._animateItem(this, false);
-					}
-				},
-
-				onLoad: {},
-				onError: {}
-			},
-			statics: {
-				_itemHandlers: handlers
-			}
-		}
-	);
-}, {
-	initialize: function Item() {
-	},
-
-	_initialize: function(props, point) {
-		var hasProps = props && Base.isPlainObject(props),
-			internal = hasProps && props.internal === true,
-			matrix = this._matrix = new Matrix(),
-			project = hasProps && props.project || paper.project,
-			settings = paper.settings;
-		this._id = internal ? null : UID.get();
-		this._parent = this._index = null;
-		this._applyMatrix = this._canApplyMatrix && settings.applyMatrix;
-		if (point)
-			matrix.translate(point);
-		matrix._owner = this;
-		this._style = new Style(project._currentStyle, this, project);
-		if (internal || hasProps && props.insert === false
-			|| !settings.insertItems && !(hasProps && props.insert === true)) {
-			this._setProject(project);
-		} else {
-			(hasProps && props.parent || project)
-					._insertItem(undefined, this, true, true);
-		}
-		if (hasProps && props !== Item.NO_INSERT) {
-			Base.filter(this, props, {
-				internal: true, insert: true, project: true, parent: true
-			});
-		}
-		return hasProps;
-	},
-
-	_serialize: function(options, dictionary) {
-		var props = {},
-			that = this;
-
-		function serialize(fields) {
-			for (var key in fields) {
-				var value = that[key];
-				if (!Base.equals(value, key === 'leading'
-						? fields.fontSize * 1.2 : fields[key])) {
-					props[key] = Base.serialize(value, options,
-							key !== 'data', dictionary);
-				}
-			}
-		}
-
-		serialize(this._serializeFields);
-		if (!(this instanceof Group))
-			serialize(this._style._defaults);
-		return [ this._class, props ];
-	},
-
-	_changed: function(flags) {
-		var symbol = this._symbol,
-			cacheParent = this._parent || symbol,
-			project = this._project;
-		if (flags & 8) {
-			this._bounds = this._position = this._decomposed =
-					this._globalMatrix = undefined;
-		}
-		if (cacheParent
-				&& (flags & 40)) {
-			Item._clearBoundsCache(cacheParent);
-		}
-		if (flags & 2) {
-			Item._clearBoundsCache(this);
-		}
-		if (project)
-			project._changed(flags, this);
-		if (symbol)
-			symbol._changed(flags);
-	},
-
-	set: function(props) {
-		if (props)
-			this._set(props);
-		return this;
-	},
-
-	getId: function() {
-		return this._id;
-	},
-
-	getName: function() {
-		return this._name;
-	},
-
-	setName: function(name) {
-
-		if (this._name)
-			this._removeNamed();
-		if (name === (+name) + '')
-			throw new Error(
-					'Names consisting only of numbers are not supported.');
-		var owner = this._getOwner();
-		if (name && owner) {
-			var children = owner._children,
-				namedChildren = owner._namedChildren;
-			(namedChildren[name] = namedChildren[name] || []).push(this);
-			if (!(name in children))
-				children[name] = this;
-		}
-		this._name = name || undefined;
-		this._changed(128);
-	},
-
-	getStyle: function() {
-		return this._style;
-	},
-
-	setStyle: function(style) {
-		this.getStyle().set(style);
-	}
-}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],
-	function(name) {
-		var part = Base.capitalize(name),
-			name = '_' + name;
-		this['get' + part] = function() {
-			return this[name];
-		};
-		this['set' + part] = function(value) {
-			if (value != this[name]) {
-				this[name] = value;
-				this._changed(name === '_locked'
-						? 128 : 129);
-			}
-		};
-	},
-{}), {
-	beans: true,
-
-	getSelection: function() {
-		return this._selection;
-	},
-
-	setSelection: function(selection) {
-		if (selection !== this._selection) {
-			this._selection = selection;
-			var project = this._project;
-			if (project) {
-				project._updateSelection(this);
-				this._changed(129);
-			}
-		}
-	},
-
-	changeSelection: function(flag, selected) {
-		var selection = this._selection;
-		this.setSelection(selected ? selection | flag : selection & ~flag);
-	},
-
-	isSelected: function() {
-		if (this._selectChildren) {
-			var children = this._children;
-			for (var i = 0, l = children.length; i < l; i++)
-				if (children[i].isSelected())
-					return true;
-		}
-		return !!(this._selection & 1);
-	},
-
-	setSelected: function(selected) {
-		if (this._selectChildren) {
-			var children = this._children;
-			for (var i = 0, l = children.length; i < l; i++)
-				children[i].setSelected(selected);
-		}
-		this.changeSelection(1, selected);
-	},
-
-	isFullySelected: function() {
-		var children = this._children,
-			selected = !!(this._selection & 1);
-		if (children && selected) {
-			for (var i = 0, l = children.length; i < l; i++)
-				if (!children[i].isFullySelected())
-					return false;
-			return true;
-		}
-		return selected;
-	},
-
-	setFullySelected: function(selected) {
-		var children = this._children;
-		if (children) {
-			for (var i = 0, l = children.length; i < l; i++)
-				children[i].setFullySelected(selected);
-		}
-		this.changeSelection(1, selected);
-	},
-
-	isClipMask: function() {
-		return this._clipMask;
-	},
-
-	setClipMask: function(clipMask) {
-		if (this._clipMask != (clipMask = !!clipMask)) {
-			this._clipMask = clipMask;
-			if (clipMask) {
-				this.setFillColor(null);
-				this.setStrokeColor(null);
-			}
-			this._changed(129);
-			if (this._parent)
-				this._parent._changed(1024);
-		}
-	},
-
-	getData: function() {
-		if (!this._data)
-			this._data = {};
-		return this._data;
-	},
-
-	setData: function(data) {
-		this._data = data;
-	},
-
-	getPosition: function(_dontLink) {
-		var position = this._position,
-			ctor = _dontLink ? Point : LinkedPoint;
-		if (!position) {
-			var pivot = this._pivot;
-			position = this._position = pivot
-					? this._matrix._transformPoint(pivot)
-					: this.getBounds().getCenter(true);
-		}
-		return new ctor(position.x, position.y, this, 'setPosition');
-	},
-
-	setPosition: function() {
-		this.translate(Point.read(arguments).subtract(this.getPosition(true)));
-	},
-
-	getPivot: function(_dontLink) {
-		var pivot = this._pivot;
-		if (pivot) {
-			var ctor = _dontLink ? Point : LinkedPoint;
-			pivot = new ctor(pivot.x, pivot.y, this, 'setPivot');
-		}
-		return pivot;
-	},
-
-	setPivot: function() {
-		this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
-		this._position = undefined;
-	}
-}, Base.each({
-		getStrokeBounds: { stroke: true },
-		getHandleBounds: { handle: true },
-		getInternalBounds: { internal: true }
-	},
-	function(options, key) {
-		this[key] = function(matrix) {
-			return this.getBounds(matrix, options);
-		};
-	},
-{
-	beans: true,
-
-	getBounds: function(matrix, options) {
-		var hasMatrix = options || matrix instanceof Matrix,
-			opts = Base.set({}, hasMatrix ? options : matrix,
-					this._boundsOptions);
-		if (!opts.stroke || this.getStrokeScaling())
-			opts.cacheItem = this;
-		var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
-		return arguments.length === 0
-				? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
-						bounds.height, this, 'setBounds')
-				: bounds;
-	},
-
-	setBounds: function() {
-		var rect = Rectangle.read(arguments),
-			bounds = this.getBounds(),
-			_matrix = this._matrix,
-			matrix = new Matrix(),
-			center = rect.getCenter();
-		matrix.translate(center);
-		if (rect.width != bounds.width || rect.height != bounds.height) {
-			if (!_matrix.isInvertible()) {
-				_matrix.initialize(_matrix._backup
-						|| new Matrix().translate(_matrix.getTranslation()));
-				bounds = this.getBounds();
-			}
-			matrix.scale(
-					bounds.width !== 0 ? rect.width / bounds.width : 0,
-					bounds.height !== 0 ? rect.height / bounds.height : 0);
-		}
-		center = bounds.getCenter();
-		matrix.translate(-center.x, -center.y);
-		this.transform(matrix);
-	},
-
-	_getBounds: function(matrix, options) {
-		var children = this._children;
-		if (!children || children.length === 0)
-			return new Rectangle();
-		Item._updateBoundsCache(this, options.cacheItem);
-		return Item._getBounds(children, matrix, options);
-	},
-
-	_getCachedBounds: function(matrix, options) {
-		matrix = matrix && matrix._orNullIfIdentity();
-		var internal = options.internal,
-			cacheItem = options.cacheItem,
-			_matrix = internal ? null : this._matrix._orNullIfIdentity(),
-			cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
-				options.stroke ? 1 : 0,
-				options.handle ? 1 : 0,
-				internal ? 1 : 0
-			].join('');
-		Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
-		if (cacheKey && this._bounds && cacheKey in this._bounds)
-			return this._bounds[cacheKey].rect.clone();
-		var bounds = this._getBounds(matrix || _matrix, options);
-		if (cacheKey) {
-			if (!this._bounds)
-				this._bounds = {};
-			var cached = this._bounds[cacheKey] = {
-				rect: bounds.clone(),
-				internal: options.internal
-			};
-		}
-		return bounds;
-	},
-
-	_getStrokeMatrix: function(matrix, options) {
-		var parent = this.getStrokeScaling() ? null
-				: options && options.internal ? this
-					: this._parent || this._symbol && this._symbol._item,
-			mx = parent ? parent.getViewMatrix().invert() : matrix;
-		return mx && mx._shiftless();
-	},
-
-	statics: {
-		_updateBoundsCache: function(parent, item) {
-			if (parent && item) {
-				var id = item._id,
-					ref = parent._boundsCache = parent._boundsCache || {
-						ids: {},
-						list: []
-					};
-				if (!ref.ids[id]) {
-					ref.list.push(item);
-					ref.ids[id] = item;
-				}
-			}
-		},
-
-		_clearBoundsCache: function(item) {
-			var cache = item._boundsCache;
-			if (cache) {
-				item._bounds = item._position = item._boundsCache = undefined;
-				for (var i = 0, list = cache.list, l = list.length; i < l; i++){
-					var other = list[i];
-					if (other !== item) {
-						other._bounds = other._position = undefined;
-						if (other._boundsCache)
-							Item._clearBoundsCache(other);
-					}
-				}
-			}
-		},
-
-		_getBounds: function(items, matrix, options) {
-			var x1 = Infinity,
-				x2 = -x1,
-				y1 = x1,
-				y2 = x2;
-			options = options || {};
-			for (var i = 0, l = items.length; i < l; i++) {
-				var item = items[i];
-				if (item._visible && !item.isEmpty()) {
-					var rect = item._getCachedBounds(
-						matrix && matrix.appended(item._matrix), options);
-					x1 = Math.min(rect.x, x1);
-					y1 = Math.min(rect.y, y1);
-					x2 = Math.max(rect.x + rect.width, x2);
-					y2 = Math.max(rect.y + rect.height, y2);
-				}
-			}
-			return isFinite(x1)
-					? new Rectangle(x1, y1, x2 - x1, y2 - y1)
-					: new Rectangle();
-		}
-	}
-
-}), {
-	beans: true,
-
-	_decompose: function() {
-		return this._decomposed || (this._decomposed = this._matrix.decompose());
-	},
-
-	getRotation: function() {
-		var decomposed = this._decompose();
-		return decomposed && decomposed.rotation;
-	},
-
-	setRotation: function(rotation) {
-		var current = this.getRotation();
-		if (current != null && rotation != null) {
-			this.rotate(rotation - current);
-		}
-	},
-
-	getScaling: function(_dontLink) {
-		var decomposed = this._decompose(),
-			scaling = decomposed && decomposed.scaling,
-			ctor = _dontLink ? Point : LinkedPoint;
-		return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling');
-	},
-
-	setScaling: function() {
-		var current = this.getScaling(),
-			scaling = Point.read(arguments, 0, { clone: true, readNull: true });
-		if (current && scaling) {
-			this.scale(scaling.x / current.x, scaling.y / current.y);
-		}
-	},
-
-	getMatrix: function() {
-		return this._matrix;
-	},
-
-	setMatrix: function() {
-		var matrix = this._matrix;
-		matrix.initialize.apply(matrix, arguments);
-	},
-
-	getGlobalMatrix: function(_dontClone) {
-		var matrix = this._globalMatrix,
-			updateVersion = this._project._updateVersion;
-		if (matrix && matrix._updateVersion !== updateVersion)
-			matrix = null;
-		if (!matrix) {
-			matrix = this._globalMatrix = this._matrix.clone();
-			var parent = this._parent;
-			if (parent)
-				matrix.prepend(parent.getGlobalMatrix(true));
-			matrix._updateVersion = updateVersion;
-		}
-		return _dontClone ? matrix : matrix.clone();
-	},
-
-	getViewMatrix: function() {
-		return this.getGlobalMatrix().prepend(this.getView()._matrix);
-	},
-
-	getApplyMatrix: function() {
-		return this._applyMatrix;
-	},
-
-	setApplyMatrix: function(apply) {
-		if (this._applyMatrix = this._canApplyMatrix && !!apply)
-			this.transform(null, true);
-	},
-
-	getTransformContent: '#getApplyMatrix',
-	setTransformContent: '#setApplyMatrix',
-}, {
-	getProject: function() {
-		return this._project;
-	},
-
-	_setProject: function(project, installEvents) {
-		if (this._project !== project) {
-			if (this._project)
-				this._installEvents(false);
-			this._project = project;
-			var children = this._children;
-			for (var i = 0, l = children && children.length; i < l; i++)
-				children[i]._setProject(project);
-			installEvents = true;
-		}
-		if (installEvents)
-			this._installEvents(true);
-	},
-
-	getView: function() {
-		return this._project._view;
-	},
-
-	_installEvents: function _installEvents(install) {
-		_installEvents.base.call(this, install);
-		var children = this._children;
-		for (var i = 0, l = children && children.length; i < l; i++)
-			children[i]._installEvents(install);
-	},
-
-	getLayer: function() {
-		var parent = this;
-		while (parent = parent._parent) {
-			if (parent instanceof Layer)
-				return parent;
-		}
-		return null;
-	},
-
-	getParent: function() {
-		return this._parent;
-	},
-
-	setParent: function(item) {
-		return item.addChild(this);
-	},
-
-	_getOwner: '#getParent',
-
-	getChildren: function() {
-		return this._children;
-	},
-
-	setChildren: function(items, _preserve) {
-		this.removeChildren();
-		this.addChildren(items, _preserve);
-	},
-
-	getFirstChild: function() {
-		return this._children && this._children[0] || null;
-	},
-
-	getLastChild: function() {
-		return this._children && this._children[this._children.length - 1]
-				|| null;
-	},
-
-	getNextSibling: function() {
-		var owner = this._getOwner();
-		return owner && owner._children[this._index + 1] || null;
-	},
-
-	getPreviousSibling: function() {
-		var owner = this._getOwner();
-		return owner && owner._children[this._index - 1] || null;
-	},
-
-	getIndex: function() {
-		return this._index;
-	},
-
-	equals: function(item) {
-		return item === this || item && this._class === item._class
-				&& this._style.equals(item._style)
-				&& this._matrix.equals(item._matrix)
-				&& this._locked === item._locked
-				&& this._visible === item._visible
-				&& this._blendMode === item._blendMode
-				&& this._opacity === item._opacity
-				&& this._clipMask === item._clipMask
-				&& this._guide === item._guide
-				&& this._equals(item)
-				|| false;
-	},
-
-	_equals: function(item) {
-		return Base.equals(this._children, item._children);
-	},
-
-	clone: function(options) {
-		var copy = new this.constructor(Item.NO_INSERT),
-			children = this._children,
-			insert = Base.pick(options ? options.insert : undefined,
-					options === undefined || options === true),
-			deep = Base.pick(options ? options.deep : undefined, true);
-		if (children)
-			copy.copyAttributes(this);
-		if (!children || deep)
-			copy.copyContent(this);
-		if (!children)
-			copy.copyAttributes(this);
-		if (insert)
-			copy.insertAbove(this);
-		var name = this._name,
-			parent = this._parent;
-		if (name && parent) {
-			var children = parent._children,
-				orig = name,
-				i = 1;
-			while (children[name])
-				name = orig + ' ' + (i++);
-			if (name !== orig)
-				copy.setName(name);
-		}
-		return copy;
-	},
-
-	copyContent: function(source) {
-		var children = source._children;
-		for (var i = 0, l = children && children.length; i < l; i++) {
-			this.addChild(children[i].clone(false), true);
-		}
-	},
-
-	copyAttributes: function(source, excludeMatrix) {
-		this.setStyle(source._style);
-		var keys = ['_locked', '_visible', '_blendMode', '_opacity',
-				'_clipMask', '_guide'];
-		for (var i = 0, l = keys.length; i < l; i++) {
-			var key = keys[i];
-			if (source.hasOwnProperty(key))
-				this[key] = source[key];
-		}
-		if (!excludeMatrix)
-			this._matrix.initialize(source._matrix);
-		this.setApplyMatrix(source._applyMatrix);
-		this.setPivot(source._pivot);
-		this.setSelection(source._selection);
-		var data = source._data,
-			name = source._name;
-		this._data = data ? Base.clone(data) : null;
-		if (name)
-			this.setName(name);
-	},
-
-	rasterize: function(resolution, insert) {
-		var bounds = this.getStrokeBounds(),
-			scale = (resolution || this.getView().getResolution()) / 72,
-			topLeft = bounds.getTopLeft().floor(),
-			bottomRight = bounds.getBottomRight().ceil(),
-			size = new Size(bottomRight.subtract(topLeft)),
-			raster = new Raster(Item.NO_INSERT);
-		if (!size.isZero()) {
-			var canvas = CanvasProvider.getCanvas(size.multiply(scale)),
-				ctx = canvas.getContext('2d'),
-				matrix = new Matrix().scale(scale).translate(topLeft.negate());
-			ctx.save();
-			matrix.applyToContext(ctx);
-			this.draw(ctx, new Base({ matrices: [matrix] }));
-			ctx.restore();
-			raster.setCanvas(canvas);
-		}
-		raster.transform(new Matrix().translate(topLeft.add(size.divide(2)))
-				.scale(1 / scale));
-		if (insert === undefined || insert)
-			raster.insertAbove(this);
-		return raster;
-	},
-
-	contains: function() {
-		return !!this._contains(
-				this._matrix._inverseTransform(Point.read(arguments)));
-	},
-
-	_contains: function(point) {
-		var children = this._children;
-		if (children) {
-			for (var i = children.length - 1; i >= 0; i--) {
-				if (children[i].contains(point))
-					return true;
-			}
-			return false;
-		}
-		return point.isInside(this.getInternalBounds());
-	},
-
-	isInside: function() {
-		return Rectangle.read(arguments).contains(this.getBounds());
-	},
-
-	_asPathItem: function() {
-		return new Path.Rectangle({
-			rectangle: this.getInternalBounds(),
-			matrix: this._matrix,
-			insert: false,
-		});
-	},
-
-	intersects: function(item, _matrix) {
-		if (!(item instanceof Item))
-			return false;
-		return this._asPathItem().getIntersections(item._asPathItem(), null,
-				_matrix, true).length > 0;
-	}
-},
-new function() {
-	function hitTest() {
-		return this._hitTest(
-				Point.read(arguments),
-				HitResult.getOptions(arguments));
-	}
-
-	function hitTestAll() {
-		var point = Point.read(arguments),
-			options = HitResult.getOptions(arguments),
-			callback = options.match,
-			results = [];
-		options = Base.set({}, options, {
-			match: function(hit) {
-				if (!callback || callback(hit))
-					results.push(hit);
-			}
-		});
-		this._hitTest(point, options);
-		return results;
-	}
-
-	function hitTestChildren(point, options, viewMatrix, _exclude) {
-		var children = this._children;
-		if (children) {
-			for (var i = children.length - 1; i >= 0; i--) {
-				var child = children[i];
-				var res = child !== _exclude && child._hitTest(point, options,
-						viewMatrix);
-				if (res)
-					return res;
-			}
-		}
-		return null;
-	}
-
-	Project.inject({
-		hitTest: hitTest,
-		hitTestAll: hitTestAll,
-		_hitTest: hitTestChildren
-	});
-
-	return {
-		hitTest: hitTest,
-		hitTestAll: hitTestAll,
-		_hitTestChildren: hitTestChildren,
-	};
-}, {
-
-	_hitTest: function(point, options, parentViewMatrix) {
-		if (this._locked || !this._visible || this._guide && !options.guides
-				|| this.isEmpty()) {
-			return null;
-		}
-
-		var matrix = this._matrix,
-			viewMatrix = parentViewMatrix
-					? parentViewMatrix.appended(matrix)
-					: this.getGlobalMatrix().prepend(this.getView()._matrix),
-			strokeMatrix = this.getStrokeScaling()
-					? null
-					: viewMatrix.inverted()._shiftless(),
-			tolerance = Math.max(options.tolerance, 1e-6),
-			tolerancePadding = options._tolerancePadding = new Size(
-					Path._getStrokePadding(tolerance, strokeMatrix));
-		point = matrix._inverseTransform(point);
-		if (!point || !this._children &&
-			!this.getBounds({ internal: true, stroke: true, handle: true })
-				.expand(tolerancePadding.multiply(2))._containsPoint(point)) {
-			return null;
-		}
-
-		var checkSelf = !(options.guides && !this._guide
-				|| options.selected && !this.isSelected()
-				|| options.type && options.type !== Base.hyphenate(this._class)
-				|| options.class && !(this instanceof options.class)),
-			callback = options.match,
-			that = this,
-			bounds,
-			res;
-
-		function match(hit) {
-			return !callback || hit && callback(hit) ? hit : null;
-		}
-
-		function checkBounds(type, part) {
-			var pt = bounds['get' + part]();
-			if (point.subtract(pt).divide(tolerancePadding).length <= 1) {
-				return new HitResult(type, that,
-						{ name: Base.hyphenate(part), point: pt });
-			}
-		}
-
-		if (checkSelf && (options.center || options.bounds) && this._parent) {
-			bounds = this.getInternalBounds();
-			if (options.center) {
-				res = checkBounds('center', 'Center');
-			}
-			if (!res && options.bounds) {
-				var points = [
-					'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
-					'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'
-				];
-				for (var i = 0; i < 8 && !res; i++) {
-					res = checkBounds('bounds', points[i]);
-				}
-			}
-			res = match(res);
-		}
-
-		if (!res) {
-			res = this._hitTestChildren(point, options, viewMatrix)
-				|| checkSelf
-					&& match(this._hitTestSelf(point, options, viewMatrix,
-						strokeMatrix))
-				|| null;
-		}
-		if (res && res.point) {
-			res.point = matrix.transform(res.point);
-		}
-		return res;
-	},
-
-	_hitTestSelf: function(point, options) {
-		if (options.fill && this.hasFill() && this._contains(point))
-			return new HitResult('fill', this);
-	},
-
-	matches: function(name, compare) {
-		function matchObject(obj1, obj2) {
-			for (var i in obj1) {
-				if (obj1.hasOwnProperty(i)) {
-					var val1 = obj1[i],
-						val2 = obj2[i];
-					if (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {
-						if (!matchObject(val1, val2))
-							return false;
-					} else if (!Base.equals(val1, val2)) {
-						return false;
-					}
-				}
-			}
-			return true;
-		}
-		var type = typeof name;
-		if (type === 'object') {
-			for (var key in name) {
-				if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
-					return false;
-			}
-			return true;
-		} else if (type === 'function') {
-			return name(this);
-		} else if (name === 'match') {
-			return compare(this);
-		} else {
-			var value = /^(empty|editable)$/.test(name)
-					? this['is' + Base.capitalize(name)]()
-					: name === 'type'
-						? Base.hyphenate(this._class)
-						: this[name];
-			if (name === 'class') {
-				if (typeof compare === 'function')
-					return this instanceof compare;
-				value = this._class;
-			}
-			if (typeof compare === 'function') {
-				return !!compare(value);
-			} else if (compare) {
-				if (compare.test) {
-					return compare.test(value);
-				} else if (Base.isPlainObject(compare)) {
-					return matchObject(compare, value);
-				}
-			}
-			return Base.equals(value, compare);
-		}
-	},
-
-	getItems: function(options) {
-		return Item._getItems(this, options, this._matrix);
-	},
-
-	getItem: function(options) {
-		return Item._getItems(this, options, this._matrix, null, true)[0]
-				|| null;
-	},
-
-	statics: {
-		_getItems: function _getItems(item, options, matrix, param, firstOnly) {
-			if (!param) {
-				var obj = typeof options === 'object' && options,
-					overlapping = obj && obj.overlapping,
-					inside = obj && obj.inside,
-					bounds = overlapping || inside,
-					rect = bounds && Rectangle.read([bounds]);
-				param = {
-					items: [],
-					recursive: obj && obj.recursive !== false,
-					inside: !!inside,
-					overlapping: !!overlapping,
-					rect: rect,
-					path: overlapping && new Path.Rectangle({
-						rectangle: rect,
-						insert: false
-					})
-				};
-				if (obj) {
-					options = Base.filter({}, options, {
-						recursive: true, inside: true, overlapping: true
-					});
-				}
-			}
-			var children = item._children,
-				items = param.items,
-				rect = param.rect;
-			matrix = rect && (matrix || new Matrix());
-			for (var i = 0, l = children && children.length; i < l; i++) {
-				var child = children[i],
-					childMatrix = matrix && matrix.appended(child._matrix),
-					add = true;
-				if (rect) {
-					var bounds = child.getBounds(childMatrix);
-					if (!rect.intersects(bounds))
-						continue;
-					if (!(rect.contains(bounds)
-							|| param.overlapping && (bounds.contains(rect)
-								|| param.path.intersects(child, childMatrix))))
-						add = false;
-				}
-				if (add && child.matches(options)) {
-					items.push(child);
-					if (firstOnly)
-						break;
-				}
-				if (param.recursive !== false) {
-					_getItems(child, options, childMatrix, param, firstOnly);
-				}
-				if (firstOnly && items.length > 0)
-					break;
-			}
-			return items;
-		}
-	}
-}, {
-
-	importJSON: function(json) {
-		var res = Base.importJSON(json, this);
-		return res !== this ? this.addChild(res) : res;
-	},
-
-	addChild: function(item, _preserve) {
-		return this.insertChild(undefined, item, _preserve);
-	},
-
-	insertChild: function(index, item, _preserve) {
-		var res = item ? this.insertChildren(index, [item], _preserve) : null;
-		return res && res[0];
-	},
-
-	addChildren: function(items, _preserve) {
-		return this.insertChildren(this._children.length, items, _preserve);
-	},
-
-	insertChildren: function(index, items, _preserve, _proto) {
-		var children = this._children;
-		if (children && items && items.length > 0) {
-			items = Array.prototype.slice.apply(items);
-			for (var i = items.length - 1; i >= 0; i--) {
-				var item = items[i];
-				if (!item || _proto && !(item instanceof _proto)) {
-					items.splice(i, 1);
-				} else {
-					item._remove(false, true);
-				}
-			}
-			Base.splice(children, items, index, 0);
-			var project = this._project,
-				notifySelf = project._changes;
-			for (var i = 0, l = items.length; i < l; i++) {
-				var item = items[i],
-					name = item._name;
-				item._parent = this;
-				item._setProject(project, true);
-				if (name)
-					item.setName(name);
-				if (notifySelf)
-					this._changed(5);
-			}
-			this._changed(11);
-		} else {
-			items = null;
-		}
-		return items;
-	},
-
-	_insertItem: '#insertChild',
-
-	_insertAt: function(item, offset, _preserve) {
-		var res = this;
-		if (res !== item) {
-			var owner = item && item._getOwner();
-			if (owner) {
-				res._remove(false, true);
-				owner._insertItem(item._index + offset, res, _preserve);
-			} else {
-				res = null;
-			}
-		}
-		return res;
-	},
-
-	insertAbove: function(item, _preserve) {
-		return this._insertAt(item, 1, _preserve);
-	},
-
-	insertBelow: function(item, _preserve) {
-		return this._insertAt(item, 0, _preserve);
-	},
-
-	sendToBack: function() {
-		var owner = this._getOwner();
-		return owner ? owner._insertItem(0, this) : null;
-	},
-
-	bringToFront: function() {
-		var owner = this._getOwner();
-		return owner ? owner._insertItem(undefined, this) : null;
-	},
-
-	appendTop: '#addChild',
-
-	appendBottom: function(item) {
-		return this.insertChild(0, item);
-	},
-
-	moveAbove: '#insertAbove',
-
-	moveBelow: '#insertBelow',
-
-	copyTo: function(owner) {
-		return owner._insertItem(undefined, this.clone(false));
-	},
-
-	reduce: function(options) {
-		var children = this._children;
-		if (children && children.length === 1) {
-			var child = children[0].reduce(options);
-			if (this._parent) {
-				child.insertAbove(this);
-				this.remove();
-			} else {
-				child.remove();
-			}
-			return child;
-		}
-		return this;
-	},
-
-	_removeNamed: function() {
-		var owner = this._getOwner();
-		if (owner) {
-			var children = owner._children,
-				namedChildren = owner._namedChildren,
-				name = this._name,
-				namedArray = namedChildren[name],
-				index = namedArray ? namedArray.indexOf(this) : -1;
-			if (index !== -1) {
-				if (children[name] == this)
-					delete children[name];
-				namedArray.splice(index, 1);
-				if (namedArray.length) {
-					children[name] = namedArray[0];
-				} else {
-					delete namedChildren[name];
-				}
-			}
-		}
-	},
-
-	_remove: function(notifySelf, notifyParent) {
-		var owner = this._getOwner(),
-			project = this._project,
-			index = this._index;
-		if (owner) {
-			if (index != null) {
-				if (project._activeLayer === this)
-					project._activeLayer = this.getNextSibling()
-							|| this.getPreviousSibling();
-				Base.splice(owner._children, null, index, 1);
-			}
-			if (this._name)
-				this._removeNamed();
-			this._installEvents(false);
-			if (notifySelf && project._changes)
-				this._changed(5);
-			if (notifyParent)
-				owner._changed(11, this);
-			this._parent = null;
-			return true;
-		}
-		return false;
-	},
-
-	remove: function() {
-		return this._remove(true, true);
-	},
-
-	replaceWith: function(item) {
-		var ok = item && item.insertBelow(this);
-		if (ok)
-			this.remove();
-		return ok;
-	},
-
-	removeChildren: function(start, end) {
-		if (!this._children)
-			return null;
-		start = start || 0;
-		end = Base.pick(end, this._children.length);
-		var removed = Base.splice(this._children, null, start, end - start);
-		for (var i = removed.length - 1; i >= 0; i--) {
-			removed[i]._remove(true, false);
-		}
-		if (removed.length > 0)
-			this._changed(11);
-		return removed;
-	},
-
-	clear: '#removeChildren',
-
-	reverseChildren: function() {
-		if (this._children) {
-			this._children.reverse();
-			for (var i = 0, l = this._children.length; i < l; i++)
-				this._children[i]._index = i;
-			this._changed(11);
-		}
-	},
-
-	isEmpty: function() {
-		return !this._children || this._children.length === 0;
-	},
-
-	isEditable: function() {
-		var item = this;
-		while (item) {
-			if (!item._visible || item._locked)
-				return false;
-			item = item._parent;
-		}
-		return true;
-	},
-
-	hasFill: function() {
-		return this.getStyle().hasFill();
-	},
-
-	hasStroke: function() {
-		return this.getStyle().hasStroke();
-	},
-
-	hasShadow: function() {
-		return this.getStyle().hasShadow();
-	},
-
-	_getOrder: function(item) {
-		function getList(item) {
-			var list = [];
-			do {
-				list.unshift(item);
-			} while (item = item._parent);
-			return list;
-		}
-		var list1 = getList(this),
-			list2 = getList(item);
-		for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {
-			if (list1[i] != list2[i]) {
-				return list1[i]._index < list2[i]._index ? 1 : -1;
-			}
-		}
-		return 0;
-	},
-
-	hasChildren: function() {
-		return this._children && this._children.length > 0;
-	},
-
-	isInserted: function() {
-		return this._parent ? this._parent.isInserted() : false;
-	},
-
-	isAbove: function(item) {
-		return this._getOrder(item) === -1;
-	},
-
-	isBelow: function(item) {
-		return this._getOrder(item) === 1;
-	},
-
-	isParent: function(item) {
-		return this._parent === item;
-	},
-
-	isChild: function(item) {
-		return item && item._parent === this;
-	},
-
-	isDescendant: function(item) {
-		var parent = this;
-		while (parent = parent._parent) {
-			if (parent === item)
-				return true;
-		}
-		return false;
-	},
-
-	isAncestor: function(item) {
-		return item ? item.isDescendant(this) : false;
-	},
-
-	isSibling: function(item) {
-		return this._parent === item._parent;
-	},
-
-	isGroupedWith: function(item) {
-		var parent = this._parent;
-		while (parent) {
-			if (parent._parent
-				&& /^(Group|Layer|CompoundPath)$/.test(parent._class)
-				&& item.isDescendant(parent))
-					return true;
-			parent = parent._parent;
-		}
-		return false;
-	},
-
-}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
-	var rotate = key === 'rotate';
-	this[key] = function() {
-		var value = (rotate ? Base : Point).read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		return this.transform(new Matrix()[key](value,
-				center || this.getPosition(true)));
-	};
-}, {
-	translate: function() {
-		var mx = new Matrix();
-		return this.transform(mx.translate.apply(mx, arguments));
-	},
-
-	transform: function(matrix, _applyMatrix, _applyRecursively,
-			_setApplyMatrix) {
-		if (matrix && matrix.isIdentity())
-			matrix = null;
-		var _matrix = this._matrix,
-			applyMatrix = (_applyMatrix || this._applyMatrix)
-					&& ((!_matrix.isIdentity() || matrix)
-						|| _applyMatrix && _applyRecursively && this._children);
-		if (!matrix && !applyMatrix)
-			return this;
-		if (matrix) {
-			if (!matrix.isInvertible() && _matrix.isInvertible())
-				_matrix._backup = _matrix.getValues();
-			_matrix.prepend(matrix);
-		}
-		if (applyMatrix = applyMatrix && this._transformContent(_matrix,
-					_applyRecursively, _setApplyMatrix)) {
-			var pivot = this._pivot,
-				style = this._style,
-				fillColor = style.getFillColor(true),
-				strokeColor = style.getStrokeColor(true);
-			if (pivot)
-				_matrix._transformPoint(pivot, pivot, true);
-			if (fillColor)
-				fillColor.transform(_matrix);
-			if (strokeColor)
-				strokeColor.transform(_matrix);
-			_matrix.reset(true);
-			if (_setApplyMatrix && this._canApplyMatrix)
-				this._applyMatrix = true;
-		}
-		var bounds = this._bounds,
-			position = this._position;
-		this._changed(9);
-		var decomp = bounds && matrix && matrix.decompose();
-		if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
-			for (var key in bounds) {
-				var cache = bounds[key];
-				if (applyMatrix || !cache.internal) {
-					var rect = cache.rect;
-					matrix._transformBounds(rect, rect);
-				}
-			}
-			var getter = this._boundsGetter,
-				rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
-			if (rect)
-				this._position = rect.getCenter(true);
-			this._bounds = bounds;
-		} else if (matrix && position) {
-			this._position = matrix._transformPoint(position, position);
-		}
-		return this;
-	},
-
-	_transformContent: function(matrix, applyRecursively, setApplyMatrix) {
-		var children = this._children;
-		if (children) {
-			for (var i = 0, l = children.length; i < l; i++)
-				children[i].transform(matrix, true, applyRecursively,
-						setApplyMatrix);
-			return true;
-		}
-	},
-
-	globalToLocal: function() {
-		return this.getGlobalMatrix(true)._inverseTransform(
-				Point.read(arguments));
-	},
-
-	localToGlobal: function() {
-		return this.getGlobalMatrix(true)._transformPoint(
-				Point.read(arguments));
-	},
-
-	parentToLocal: function() {
-		return this._matrix._inverseTransform(Point.read(arguments));
-	},
-
-	localToParent: function() {
-		return this._matrix._transformPoint(Point.read(arguments));
-	},
-
-	fitBounds: function(rectangle, fill) {
-		rectangle = Rectangle.read(arguments);
-		var bounds = this.getBounds(),
-			itemRatio = bounds.height / bounds.width,
-			rectRatio = rectangle.height / rectangle.width,
-			scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
-					? rectangle.width / bounds.width
-					: rectangle.height / bounds.height,
-			newBounds = new Rectangle(new Point(),
-					new Size(bounds.width * scale, bounds.height * scale));
-		newBounds.setCenter(rectangle.getCenter());
-		this.setBounds(newBounds);
-	}
-}), {
-
-	_setStyles: function(ctx, param, viewMatrix) {
-		var style = this._style;
-		if (style.hasFill()) {
-			ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx);
-		}
-		if (style.hasStroke()) {
-			ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx);
-			ctx.lineWidth = style.getStrokeWidth();
-			var strokeJoin = style.getStrokeJoin(),
-				strokeCap = style.getStrokeCap(),
-				miterLimit = style.getMiterLimit();
-			if (strokeJoin)
-				ctx.lineJoin = strokeJoin;
-			if (strokeCap)
-				ctx.lineCap = strokeCap;
-			if (miterLimit)
-				ctx.miterLimit = miterLimit;
-			if (paper.support.nativeDash) {
-				var dashArray = style.getDashArray(),
-					dashOffset = style.getDashOffset();
-				if (dashArray && dashArray.length) {
-					if ('setLineDash' in ctx) {
-						ctx.setLineDash(dashArray);
-						ctx.lineDashOffset = dashOffset;
-					} else {
-						ctx.mozDash = dashArray;
-						ctx.mozDashOffset = dashOffset;
-					}
-				}
-			}
-		}
-		if (style.hasShadow()) {
-			var pixelRatio = param.pixelRatio || 1,
-				mx = viewMatrix._shiftless().prepend(
-					new Matrix().scale(pixelRatio, pixelRatio)),
-				blur = mx.transform(new Point(style.getShadowBlur(), 0)),
-				offset = mx.transform(this.getShadowOffset());
-			ctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);
-			ctx.shadowBlur = blur.getLength();
-			ctx.shadowOffsetX = offset.x;
-			ctx.shadowOffsetY = offset.y;
-		}
-	},
-
-	draw: function(ctx, param, parentStrokeMatrix) {
-		var updateVersion = this._updateVersion = this._project._updateVersion;
-		if (!this._visible || this._opacity === 0)
-			return;
-		var matrices = param.matrices,
-			viewMatrix = param.viewMatrix,
-			matrix = this._matrix,
-			globalMatrix = matrices[matrices.length - 1].appended(matrix);
-		if (!globalMatrix.isInvertible())
-			return;
-
-		viewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)
-				: globalMatrix;
-
-		matrices.push(globalMatrix);
-		if (param.updateMatrix) {
-			globalMatrix._updateVersion = updateVersion;
-			this._globalMatrix = globalMatrix;
-		}
-
-		var blendMode = this._blendMode,
-			opacity = this._opacity,
-			normalBlend = blendMode === 'normal',
-			nativeBlend = BlendMode.nativeModes[blendMode],
-			direct = normalBlend && opacity === 1
-					|| param.dontStart
-					|| param.clip
-					|| (nativeBlend || normalBlend && opacity < 1)
-						&& this._canComposite(),
-			pixelRatio = param.pixelRatio || 1,
-			mainCtx, itemOffset, prevOffset;
-		if (!direct) {
-			var bounds = this.getStrokeBounds(viewMatrix);
-			if (!bounds.width || !bounds.height)
-				return;
-			prevOffset = param.offset;
-			itemOffset = param.offset = bounds.getTopLeft().floor();
-			mainCtx = ctx;
-			ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)
-					.multiply(pixelRatio));
-			if (pixelRatio !== 1)
-				ctx.scale(pixelRatio, pixelRatio);
-		}
-		ctx.save();
-		var strokeMatrix = parentStrokeMatrix
-				? parentStrokeMatrix.appended(matrix)
-				: this._canScaleStroke && !this.getStrokeScaling(true)
-					&& viewMatrix,
-			clip = !direct && param.clipItem,
-			transform = !strokeMatrix || clip;
-		if (direct) {
-			ctx.globalAlpha = opacity;
-			if (nativeBlend)
-				ctx.globalCompositeOperation = blendMode;
-		} else if (transform) {
-			ctx.translate(-itemOffset.x, -itemOffset.y);
-		}
-		if (transform) {
-			(direct ? matrix : viewMatrix).applyToContext(ctx);
-		}
-		if (clip) {
-			param.clipItem.draw(ctx, param.extend({ clip: true }));
-		}
-		if (strokeMatrix) {
-			ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
-			var offset = param.offset;
-			if (offset)
-				ctx.translate(-offset.x, -offset.y);
-		}
-		this._draw(ctx, param, viewMatrix, strokeMatrix);
-		ctx.restore();
-		matrices.pop();
-		if (param.clip && !param.dontFinish)
-			ctx.clip();
-		if (!direct) {
-			BlendMode.process(blendMode, ctx, mainCtx, opacity,
-					itemOffset.subtract(prevOffset).multiply(pixelRatio));
-			CanvasProvider.release(ctx);
-			param.offset = prevOffset;
-		}
-	},
-
-	_isUpdated: function(updateVersion) {
-		var parent = this._parent;
-		if (parent instanceof CompoundPath)
-			return parent._isUpdated(updateVersion);
-		var updated = this._updateVersion === updateVersion;
-		if (!updated && parent && parent._visible
-				&& parent._isUpdated(updateVersion)) {
-			this._updateVersion = updateVersion;
-			updated = true;
-		}
-		return updated;
-	},
-
-	_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {
-		var selection = this._selection,
-			itemSelected = selection & 1,
-			boundsSelected = selection & 2
-					|| itemSelected && this._selectBounds,
-			positionSelected = selection & 4;
-		if (!this._drawSelected)
-			itemSelected = false;
-		if ((itemSelected || boundsSelected || positionSelected)
-				&& this._isUpdated(updateVersion)) {
-			var layer,
-				color = this.getSelectedColor(true) || (layer = this.getLayer())
-					&& layer.getSelectedColor(true),
-				mx = matrix.appended(this.getGlobalMatrix(true)),
-				half = size / 2;
-			ctx.strokeStyle = ctx.fillStyle = color
-					? color.toCanvasStyle(ctx) : '#009dec';
-			if (itemSelected)
-				this._drawSelected(ctx, mx, selectionItems);
-			if (positionSelected) {
-				var point = this.getPosition(true),
-					x = point.x,
-					y = point.y;
-				ctx.beginPath();
-				ctx.arc(x, y, half, 0, Math.PI * 2, true);
-				ctx.stroke();
-				var deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],
-					start = half,
-					end = size + 1;
-				for (var i = 0; i < 4; i++) {
-					var delta = deltas[i],
-						dx = delta[0],
-						dy = delta[1];
-					ctx.moveTo(x + dx * start, y + dy * start);
-					ctx.lineTo(x + dx * end, y + dy * end);
-					ctx.stroke();
-				}
-			}
-			if (boundsSelected) {
-				var coords = mx._transformCorners(this.getInternalBounds());
-				ctx.beginPath();
-				for (var i = 0; i < 8; i++) {
-					ctx[i === 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);
-				}
-				ctx.closePath();
-				ctx.stroke();
-				for (var i = 0; i < 8; i++) {
-					ctx.fillRect(coords[i] - half, coords[++i] - half,
-							size, size);
-				}
-			}
-		}
-	},
-
-	_canComposite: function() {
-		return false;
-	}
-}, Base.each(['down', 'drag', 'up', 'move'], function(key) {
-	this['removeOn' + Base.capitalize(key)] = function() {
-		var hash = {};
-		hash[key] = true;
-		return this.removeOn(hash);
-	};
-}, {
-
-	removeOn: function(obj) {
-		for (var name in obj) {
-			if (obj[name]) {
-				var key = 'mouse' + name,
-					project = this._project,
-					sets = project._removeSets = project._removeSets || {};
-				sets[key] = sets[key] || {};
-				sets[key][this._id] = this;
-			}
-		}
-		return this;
-	}
-}));
-
-var Group = Item.extend({
-	_class: 'Group',
-	_selectBounds: false,
-	_selectChildren: true,
-	_serializeFields: {
-		children: []
-	},
-
-	initialize: function Group(arg) {
-		this._children = [];
-		this._namedChildren = {};
-		if (!this._initialize(arg))
-			this.addChildren(Array.isArray(arg) ? arg : arguments);
-	},
-
-	_changed: function _changed(flags) {
-		_changed.base.call(this, flags);
-		if (flags & 1026) {
-			this._clipItem = undefined;
-		}
-	},
-
-	_getClipItem: function() {
-		var clipItem = this._clipItem;
-		if (clipItem === undefined) {
-			clipItem = null;
-			var children = this._children;
-			for (var i = 0, l = children.length; i < l; i++) {
-				if (children[i]._clipMask) {
-					clipItem = children[i];
-					break;
-				}
-			}
-			this._clipItem = clipItem;
-		}
-		return clipItem;
-	},
-
-	isClipped: function() {
-		return !!this._getClipItem();
-	},
-
-	setClipped: function(clipped) {
-		var child = this.getFirstChild();
-		if (child)
-			child.setClipMask(clipped);
-	},
-
-	_getBounds: function _getBounds(matrix, options) {
-		var clipItem = this._getClipItem();
-		return clipItem
-			? clipItem._getCachedBounds(
-				matrix && matrix.appended(clipItem._matrix),
-				Base.set({}, options, { stroke: false }))
-			: _getBounds.base.call(this, matrix, options);
-	},
-
-	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
-		var clipItem = this._getClipItem();
-		return (!clipItem || clipItem.contains(point))
-				&& _hitTestChildren.base.call(this, point, options, viewMatrix,
-					clipItem);
-	},
-
-	_draw: function(ctx, param) {
-		var clip = param.clip,
-			clipItem = !clip && this._getClipItem();
-		param = param.extend({ clipItem: clipItem, clip: false });
-		if (clip) {
-			ctx.beginPath();
-			param.dontStart = param.dontFinish = true;
-		} else if (clipItem) {
-			clipItem.draw(ctx, param.extend({ clip: true }));
-		}
-		var children = this._children;
-		for (var i = 0, l = children.length; i < l; i++) {
-			var item = children[i];
-			if (item !== clipItem)
-				item.draw(ctx, param);
-		}
-	}
-});
-
-var Layer = Group.extend({
-	_class: 'Layer',
-
-	initialize: function Layer() {
-		Group.apply(this, arguments);
-	},
-
-	_getOwner: function() {
-		return this._parent || this._index != null && this._project;
-	},
-
-	isInserted: function isInserted() {
-		return this._parent ? isInserted.base.call(this) : this._index != null;
-	},
-
-	activate: function() {
-		this._project._activeLayer = this;
-	},
-
-	_hitTestSelf: function() {
-	}
-});
-
-var Shape = Item.extend({
-	_class: 'Shape',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_canScaleStroke: true,
-	_serializeFields: {
-		type: null,
-		size: null,
-		radius: null
-	},
-
-	initialize: function Shape(props) {
-		this._initialize(props);
-	},
-
-	_equals: function(item) {
-		return this._type === item._type
-			&& this._size.equals(item._size)
-			&& Base.equals(this._radius, item._radius);
-	},
-
-	copyContent: function(source) {
-		this.setType(source._type);
-		this.setSize(source._size);
-		this.setRadius(source._radius);
-	},
-
-	getType: function() {
-		return this._type;
-	},
-
-	setType: function(type) {
-		this._type = type;
-	},
-
-	getShape: '#getType',
-	setShape: '#setType',
-
-	getSize: function() {
-		var size = this._size;
-		return new LinkedSize(size.width, size.height, this, 'setSize');
-	},
-
-	setSize: function() {
-		var size = Size.read(arguments);
-		if (!this._size) {
-			this._size = size.clone();
-		} else if (!this._size.equals(size)) {
-			var type = this._type,
-				width = size.width,
-				height = size.height;
-			if (type === 'rectangle') {
-				var radius = Size.min(this._radius, size.divide(2));
-				this._radius.set(radius.width, radius.height);
-			} else if (type === 'circle') {
-				width = height = (width + height) / 2;
-				this._radius = width / 2;
-			} else if (type === 'ellipse') {
-				this._radius.set(width / 2, height / 2);
-			}
-			this._size.set(width, height);
-			this._changed(9);
-		}
-	},
-
-	getRadius: function() {
-		var rad = this._radius;
-		return this._type === 'circle'
-				? rad
-				: new LinkedSize(rad.width, rad.height, this, 'setRadius');
-	},
-
-	setRadius: function(radius) {
-		var type = this._type;
-		if (type === 'circle') {
-			if (radius === this._radius)
-				return;
-			var size = radius * 2;
-			this._radius = radius;
-			this._size.set(size, size);
-		} else {
-			radius = Size.read(arguments);
-			if (!this._radius) {
-				this._radius = radius.clone();
-			} else {
-				if (this._radius.equals(radius))
-					return;
-				this._radius.set(radius.width, radius.height);
-				if (type === 'rectangle') {
-					var size = Size.max(this._size, radius.multiply(2));
-					this._size.set(size.width, size.height);
-				} else if (type === 'ellipse') {
-					this._size.set(radius.width * 2, radius.height * 2);
-				}
-			}
-		}
-		this._changed(9);
-	},
-
-	isEmpty: function() {
-		return false;
-	},
-
-	toPath: function(insert) {
-		var path = new Path[Base.capitalize(this._type)]({
-			center: new Point(),
-			size: this._size,
-			radius: this._radius,
-			insert: false
-		});
-		path.copyAttributes(this);
-		if (paper.settings.applyMatrix)
-			path.setApplyMatrix(true);
-		if (insert === undefined || insert)
-			path.insertAbove(this);
-		return path;
-	},
-
-	toShape: '#clone',
-
-	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
-		var style = this._style,
-			hasFill = style.hasFill(),
-			hasStroke = style.hasStroke(),
-			dontPaint = param.dontFinish || param.clip,
-			untransformed = !strokeMatrix;
-		if (hasFill || hasStroke || dontPaint) {
-			var type = this._type,
-				radius = this._radius,
-				isCircle = type === 'circle';
-			if (!param.dontStart)
-				ctx.beginPath();
-			if (untransformed && isCircle) {
-				ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
-			} else {
-				var rx = isCircle ? radius : radius.width,
-					ry = isCircle ? radius : radius.height,
-					size = this._size,
-					width = size.width,
-					height = size.height;
-				if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
-					ctx.rect(-width / 2, -height / 2, width, height);
-				} else {
-					var x = width / 2,
-						y = height / 2,
-						kappa = 1 - 0.5522847498307936,
-						cx = rx * kappa,
-						cy = ry * kappa,
-						c = [
-							-x, -y + ry,
-							-x, -y + cy,
-							-x + cx, -y,
-							-x + rx, -y,
-							x - rx, -y,
-							x - cx, -y,
-							x, -y + cy,
-							x, -y + ry,
-							x, y - ry,
-							x, y - cy,
-							x - cx, y,
-							x - rx, y,
-							-x + rx, y,
-							-x + cx, y,
-							-x, y - cy,
-							-x, y - ry
-						];
-					if (strokeMatrix)
-						strokeMatrix.transform(c, c, 32);
-					ctx.moveTo(c[0], c[1]);
-					ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);
-					if (x !== rx)
-						ctx.lineTo(c[8], c[9]);
-					ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);
-					if (y !== ry)
-						ctx.lineTo(c[16], c[17]);
-					ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);
-					if (x !== rx)
-						ctx.lineTo(c[24], c[25]);
-					ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);
-				}
-			}
-			ctx.closePath();
-		}
-		if (!dontPaint && (hasFill || hasStroke)) {
-			this._setStyles(ctx, param, viewMatrix);
-			if (hasFill) {
-				ctx.fill(style.getFillRule());
-				ctx.shadowColor = 'rgba(0,0,0,0)';
-			}
-			if (hasStroke)
-				ctx.stroke();
-		}
-	},
-
-	_canComposite: function() {
-		return !(this.hasFill() && this.hasStroke());
-	},
-
-	_getBounds: function(matrix, options) {
-		var rect = new Rectangle(this._size).setCenter(0, 0),
-			style = this._style,
-			strokeWidth = options.stroke && style.hasStroke()
-					&& style.getStrokeWidth();
-		if (matrix)
-			rect = matrix._transformBounds(rect);
-		return strokeWidth
-				? rect.expand(Path._getStrokePadding(strokeWidth,
-					this._getStrokeMatrix(matrix, options)))
-				: rect;
-	}
-},
-new function() {
-	function getCornerCenter(that, point, expand) {
-		var radius = that._radius;
-		if (!radius.isZero()) {
-			var halfSize = that._size.divide(2);
-			for (var i = 0; i < 4; i++) {
-				var dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),
-					corner = dir.multiply(halfSize),
-					center = corner.subtract(dir.multiply(radius)),
-					rect = new Rectangle(corner, center);
-				if ((expand ? rect.expand(expand) : rect).contains(point))
-					return center;
-			}
-		}
-	}
-
-	function isOnEllipseStroke(point, radius, padding, quadrant) {
-		var vector = point.divide(radius);
-		return (!quadrant || vector.quadrant === quadrant) &&
-				vector.subtract(vector.normalize()).multiply(radius)
-					.divide(padding).length <= 1;
-	}
-
-	return {
-		_contains: function _contains(point) {
-			if (this._type === 'rectangle') {
-				var center = getCornerCenter(this, point);
-				return center
-						? point.subtract(center).divide(this._radius)
-							.getLength() <= 1
-						: _contains.base.call(this, point);
-			} else {
-				return point.divide(this.size).getLength() <= 0.5;
-			}
-		},
-
-		_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,
-				strokeMatrix) {
-			var hit = false,
-				style = this._style,
-				hitStroke = options.stroke && style.hasStroke(),
-				hitFill = options.fill && style.hasFill();
-			if (hitStroke || hitFill) {
-				var type = this._type,
-					radius = this._radius,
-					strokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,
-					strokePadding = options._tolerancePadding.add(
-						Path._getStrokePadding(strokeRadius,
-							!style.getStrokeScaling() && strokeMatrix));
-				if (type === 'rectangle') {
-					var padding = strokePadding.multiply(2),
-						center = getCornerCenter(this, point, padding);
-					if (center) {
-						hit = isOnEllipseStroke(point.subtract(center), radius,
-								strokePadding, center.getQuadrant());
-					} else {
-						var rect = new Rectangle(this._size).setCenter(0, 0),
-							outer = rect.expand(padding),
-							inner = rect.expand(padding.negate());
-						hit = outer._containsPoint(point)
-								&& !inner._containsPoint(point);
-					}
-				} else {
-					hit = isOnEllipseStroke(point, radius, strokePadding);
-				}
-			}
-			return hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)
-					: _hitTestSelf.base.apply(this, arguments);
-		}
-	};
-}, {
-
-statics: new function() {
-	function createShape(type, point, size, radius, args) {
-		var item = new Shape(Base.getNamed(args));
-		item._type = type;
-		item._size = size;
-		item._radius = radius;
-		return item.translate(point);
-	}
-
-	return {
-		Circle: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				radius = Base.readNamed(arguments, 'radius');
-			return createShape('circle', center, new Size(radius * 2), radius,
-					arguments);
-		},
-
-		Rectangle: function() {
-			var rect = Rectangle.readNamed(arguments, 'rectangle'),
-				radius = Size.min(Size.readNamed(arguments, 'radius'),
-						rect.getSize(true).divide(2));
-			return createShape('rectangle', rect.getCenter(true),
-					rect.getSize(true), radius, arguments);
-		},
-
-		Ellipse: function() {
-			var ellipse = Shape._readEllipse(arguments),
-				radius = ellipse.radius;
-			return createShape('ellipse', ellipse.center, radius.multiply(2),
-					radius, arguments);
-		},
-
-		_readEllipse: function(args) {
-			var center,
-				radius;
-			if (Base.hasNamed(args, 'radius')) {
-				center = Point.readNamed(args, 'center');
-				radius = Size.readNamed(args, 'radius');
-			} else {
-				var rect = Rectangle.readNamed(args, 'rectangle');
-				center = rect.getCenter(true);
-				radius = rect.getSize(true).divide(2);
-			}
-			return { center: center, radius: radius };
-		}
-	};
-}});
-
-var Raster = Item.extend({
-	_class: 'Raster',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_boundsOptions: { stroke: false, handle: false },
-	_serializeFields: {
-		crossOrigin: null,
-		source: null
-	},
-
-	initialize: function Raster(object, position) {
-		if (!this._initialize(object,
-				position !== undefined && Point.read(arguments, 1))) {
-			var image = typeof object === 'string'
-					? document.getElementById(object) : object;
-			if (image) {
-				this.setImage(image);
-			} else {
-				this.setSource(object);
-			}
-		}
-		if (!this._size) {
-			this._size = new Size();
-			this._loaded = false;
-		}
-	},
-
-	_equals: function(item) {
-		return this.getSource() === item.getSource();
-	},
-
-	copyContent: function(source) {
-		var image = source._image,
-			canvas = source._canvas;
-		if (image) {
-			this._setImage(image);
-		} else if (canvas) {
-			var copyCanvas = CanvasProvider.getCanvas(source._size);
-			copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
-			this._setImage(copyCanvas);
-		}
-		this._crossOrigin = source._crossOrigin;
-	},
-
-	getSize: function() {
-		var size = this._size;
-		return new LinkedSize(size ? size.width : 0, size ? size.height : 0,
-				this, 'setSize');
-	},
-
-	setSize: function() {
-		var size = Size.read(arguments);
-		if (!size.equals(this._size)) {
-			if (size.width > 0 && size.height > 0) {
-				var element = this.getElement();
-				this._setImage(CanvasProvider.getCanvas(size));
-				if (element)
-					this.getContext(true).drawImage(element, 0, 0,
-							size.width, size.height);
-			} else {
-				if (this._canvas)
-					CanvasProvider.release(this._canvas);
-				this._size = size.clone();
-			}
-		}
-	},
-
-	getWidth: function() {
-		return this._size ? this._size.width : 0;
-	},
-
-	setWidth: function(width) {
-		this.setSize(width, this.getHeight());
-	},
-
-	getHeight: function() {
-		return this._size ? this._size.height : 0;
-	},
-
-	setHeight: function(height) {
-		this.setSize(this.getWidth(), height);
-	},
-
-	getLoaded: function() {
-		return this._loaded;
-	},
-
-	isEmpty: function() {
-		var size = this._size;
-		return !size || size.width === 0 && size.height === 0;
-	},
-
-	getResolution: function() {
-		var matrix = this._matrix,
-			orig = new Point(0, 0).transform(matrix),
-			u = new Point(1, 0).transform(matrix).subtract(orig),
-			v = new Point(0, 1).transform(matrix).subtract(orig);
-		return new Size(
-			72 / u.getLength(),
-			72 / v.getLength()
-		);
-	},
-
-	getPpi: '#getResolution',
-
-	getImage: function() {
-		return this._image;
-	},
-
-	setImage: function(image) {
-		var that = this;
-
-		function emit(event) {
-			var view = that.getView(),
-				type = event && event.type || 'load';
-			if (view && that.responds(type)) {
-				paper = view._scope;
-				that.emit(type, new Event(event));
-			}
-		}
-
-		this._setImage(image);
-		if (this._loaded) {
-			setTimeout(emit, 0);
-		} else if (image) {
-			DomEvent.add(image, {
-				load: function(event) {
-					that._setImage(image);
-					emit(event);
-				},
-				error: emit
-			});
-		}
-	},
-
-	_setImage: function(image) {
-		if (this._canvas)
-			CanvasProvider.release(this._canvas);
-		if (image && image.getContext) {
-			this._image = null;
-			this._canvas = image;
-			this._loaded = true;
-		} else {
-			this._image = image;
-			this._canvas = null;
-			this._loaded = !!(image && image.src && image.complete);
-		}
-		this._size = new Size(
-				image ? image.naturalWidth || image.width : 0,
-				image ? image.naturalHeight || image.height : 0);
-		this._context = null;
-		this._changed(521);
-	},
-
-	getCanvas: function() {
-		if (!this._canvas) {
-			var ctx = CanvasProvider.getContext(this._size);
-			try {
-				if (this._image)
-					ctx.drawImage(this._image, 0, 0);
-				this._canvas = ctx.canvas;
-			} catch (e) {
-				CanvasProvider.release(ctx);
-			}
-		}
-		return this._canvas;
-	},
-
-	setCanvas: '#setImage',
-
-	getContext: function(modify) {
-		if (!this._context)
-			this._context = this.getCanvas().getContext('2d');
-		if (modify) {
-			this._image = null;
-			this._changed(513);
-		}
-		return this._context;
-	},
-
-	setContext: function(context) {
-		this._context = context;
-	},
-
-	getSource: function() {
-		var image = this._image;
-		return image && image.src || this.toDataURL();
-	},
-
-	setSource: function(src) {
-		var image = new window.Image(),
-			crossOrigin = this._crossOrigin;
-		if (crossOrigin)
-			image.crossOrigin = crossOrigin;
-		image.src = src;
-		this.setImage(image);
-	},
-
-	getCrossOrigin: function() {
-		var image = this._image;
-		return image && image.crossOrigin || this._crossOrigin || '';
-	},
-
-	setCrossOrigin: function(crossOrigin) {
-		this._crossOrigin = crossOrigin;
-		var image = this._image;
-		if (image)
-			image.crossOrigin = crossOrigin;
-	},
-
-	getElement: function() {
-		return this._canvas || this._loaded && this._image;
-	}
-}, {
-	beans: false,
-
-	getSubCanvas: function() {
-		var rect = Rectangle.read(arguments),
-			ctx = CanvasProvider.getContext(rect.getSize());
-		ctx.drawImage(this.getCanvas(), rect.x, rect.y,
-				rect.width, rect.height, 0, 0, rect.width, rect.height);
-		return ctx.canvas;
-	},
-
-	getSubRaster: function() {
-		var rect = Rectangle.read(arguments),
-			raster = new Raster(Item.NO_INSERT);
-		raster._setImage(this.getSubCanvas(rect));
-		raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
-		raster._matrix.prepend(this._matrix);
-		raster.insertAbove(this);
-		return raster;
-	},
-
-	toDataURL: function() {
-		var image = this._image,
-			src = image && image.src;
-		if (/^data:/.test(src))
-			return src;
-		var canvas = this.getCanvas();
-		return canvas ? canvas.toDataURL.apply(canvas, arguments) : null;
-	},
-
-	drawImage: function(image ) {
-		var point = Point.read(arguments, 1);
-		this.getContext(true).drawImage(image, point.x, point.y);
-	},
-
-	getAverageColor: function(object) {
-		var bounds, path;
-		if (!object) {
-			bounds = this.getBounds();
-		} else if (object instanceof PathItem) {
-			path = object;
-			bounds = object.getBounds();
-		} else if (typeof object === 'object') {
-			if ('width' in object) {
-				bounds = new Rectangle(object);
-			} else if ('x' in object) {
-				bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
-			}
-		}
-		if (!bounds)
-			return null;
-		var sampleSize = 32,
-			width = Math.min(bounds.width, sampleSize),
-			height = Math.min(bounds.height, sampleSize);
-		var ctx = Raster._sampleContext;
-		if (!ctx) {
-			ctx = Raster._sampleContext = CanvasProvider.getContext(
-					new Size(sampleSize));
-		} else {
-			ctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);
-		}
-		ctx.save();
-		var matrix = new Matrix()
-				.scale(width / bounds.width, height / bounds.height)
-				.translate(-bounds.x, -bounds.y);
-		matrix.applyToContext(ctx);
-		if (path)
-			path.draw(ctx, new Base({ clip: true, matrices: [matrix] }));
-		this._matrix.applyToContext(ctx);
-		var element = this.getElement(),
-			size = this._size;
-		if (element)
-			ctx.drawImage(element, -size.width / 2, -size.height / 2);
-		ctx.restore();
-		var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),
-				Math.ceil(height)).data,
-			channels = [0, 0, 0],
-			total = 0;
-		for (var i = 0, l = pixels.length; i < l; i += 4) {
-			var alpha = pixels[i + 3];
-			total += alpha;
-			alpha /= 255;
-			channels[0] += pixels[i] * alpha;
-			channels[1] += pixels[i + 1] * alpha;
-			channels[2] += pixels[i + 2] * alpha;
-		}
-		for (var i = 0; i < 3; i++)
-			channels[i] /= total;
-		return total ? Color.read(channels) : null;
-	},
-
-	getPixel: function() {
-		var point = Point.read(arguments);
-		var data = this.getContext().getImageData(point.x, point.y, 1, 1).data;
-		return new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],
-				data[3] / 255);
-	},
-
-	setPixel: function() {
-		var point = Point.read(arguments),
-			color = Color.read(arguments),
-			components = color._convert('rgb'),
-			alpha = color._alpha,
-			ctx = this.getContext(true),
-			imageData = ctx.createImageData(1, 1),
-			data = imageData.data;
-		data[0] = components[0] * 255;
-		data[1] = components[1] * 255;
-		data[2] = components[2] * 255;
-		data[3] = alpha != null ? alpha * 255 : 255;
-		ctx.putImageData(imageData, point.x, point.y);
-	},
-
-	createImageData: function() {
-		var size = Size.read(arguments);
-		return this.getContext().createImageData(size.width, size.height);
-	},
-
-	getImageData: function() {
-		var rect = Rectangle.read(arguments);
-		if (rect.isEmpty())
-			rect = new Rectangle(this._size);
-		return this.getContext().getImageData(rect.x, rect.y,
-				rect.width, rect.height);
-	},
-
-	setImageData: function(data ) {
-		var point = Point.read(arguments, 1);
-		this.getContext(true).putImageData(data, point.x, point.y);
-	},
-
-	_getBounds: function(matrix, options) {
-		var rect = new Rectangle(this._size).setCenter(0, 0);
-		return matrix ? matrix._transformBounds(rect) : rect;
-	},
-
-	_hitTestSelf: function(point) {
-		if (this._contains(point)) {
-			var that = this;
-			return new HitResult('pixel', that, {
-				offset: point.add(that._size.divide(2)).round(),
-				color: {
-					get: function() {
-						return that.getPixel(this.offset);
-					}
-				}
-			});
-		}
-	},
-
-	_draw: function(ctx) {
-		var element = this.getElement();
-		if (element) {
-			ctx.globalAlpha = this._opacity;
-			ctx.drawImage(element,
-					-this._size.width / 2, -this._size.height / 2);
-		}
-	},
-
-	_canComposite: function() {
-		return true;
-	}
-});
-
-var SymbolItem = Item.extend({
-	_class: 'SymbolItem',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_boundsOptions: { stroke: true },
-	_serializeFields: {
-		symbol: null
-	},
-
-	initialize: function SymbolItem(arg0, arg1) {
-		if (!this._initialize(arg0,
-				arg1 !== undefined && Point.read(arguments, 1)))
-			this.setDefinition(arg0 instanceof SymbolDefinition ?
-					arg0 : new SymbolDefinition(arg0));
-	},
-
-	_equals: function(item) {
-		return this._definition === item._definition;
-	},
-
-	copyContent: function(source) {
-		this.setDefinition(source._definition);
-	},
-
-	getDefinition: function() {
-		return this._definition;
-	},
-
-	setDefinition: function(definition) {
-		this._definition = definition;
-		this._changed(9);
-	},
-
-	getSymbol: '#getDefinition',
-	setSymbol: '#setDefinition',
-
-	isEmpty: function() {
-		return this._definition._item.isEmpty();
-	},
-
-	_getBounds: function(matrix, options) {
-		var item = this._definition._item;
-		return item._getCachedBounds(item._matrix.prepended(matrix), options);
-	},
-
-	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
-		var res = this._definition._item._hitTest(point, options, viewMatrix);
-		if (res)
-			res.item = this;
-		return res;
-	},
-
-	_draw: function(ctx, param) {
-		this._definition._item.draw(ctx, param);
-	}
-
-});
-
-var SymbolDefinition = Base.extend({
-	_class: 'SymbolDefinition',
-
-	initialize: function SymbolDefinition(item, dontCenter) {
-		this._id = UID.get();
-		this.project = paper.project;
-		if (item)
-			this.setItem(item, dontCenter);
-	},
-
-	_serialize: function(options, dictionary) {
-		return dictionary.add(this, function() {
-			return Base.serialize([this._class, this._item],
-					options, false, dictionary);
-		});
-	},
-
-	_changed: function(flags) {
-		if (flags & 8)
-			Item._clearBoundsCache(this);
-		if (flags & 1)
-			this.project._changed(flags);
-	},
-
-	getItem: function() {
-		return this._item;
-	},
-
-	setItem: function(item, _dontCenter) {
-		if (item._symbol)
-			item = item.clone();
-		if (this._item)
-			this._item._symbol = null;
-		this._item = item;
-		item.remove();
-		item.setSelected(false);
-		if (!_dontCenter)
-			item.setPosition(new Point());
-		item._symbol = this;
-		this._changed(9);
-	},
-
-	getDefinition: '#getItem',
-	setDefinition: '#setItem',
-
-	place: function(position) {
-		return new SymbolItem(this, position);
-	},
-
-	clone: function() {
-		return new SymbolDefinition(this._item.clone(false));
-	},
-
-	equals: function(symbol) {
-		return symbol === this
-				|| symbol && this._item.equals(symbol._item)
-				|| false;
-	}
-});
-
-var HitResult = Base.extend({
-	_class: 'HitResult',
-
-	initialize: function HitResult(type, item, values) {
-		this.type = type;
-		this.item = item;
-		if (values) {
-			values.enumerable = true;
-			this.inject(values);
-		}
-	},
-
-	statics: {
-		getOptions: function(args) {
-			var options = args && Base.read(args);
-			return Base.set({
-				type: null,
-				tolerance: paper.settings.hitTolerance,
-				fill: !options,
-				stroke: !options,
-				segments: !options,
-				handles: false,
-				ends: false,
-				center: false,
-				bounds: false,
-				guides: false,
-				selected: false
-			}, options);
-		}
-	}
-});
-
-var Segment = Base.extend({
-	_class: 'Segment',
-	beans: true,
-	_selection: 0,
-
-	initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
-		var count = arguments.length,
-			point, handleIn, handleOut,
-			selection;
-		if (count === 0) {
-		} else if (count === 1) {
-			if (arg0 && 'point' in arg0) {
-				point = arg0.point;
-				handleIn = arg0.handleIn;
-				handleOut = arg0.handleOut;
-				selection = arg0.selection;
-			} else {
-				point = arg0;
-			}
-		} else if (arg0 == null || typeof arg0 === 'object') {
-			point = arg0;
-			handleIn = arg1;
-			handleOut = arg2;
-			selection = arg3;
-		} else {
-			point = arg0 !== undefined ? [ arg0, arg1 ] : null;
-			handleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;
-			handleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;
-		}
-		new SegmentPoint(point, this, '_point');
-		new SegmentPoint(handleIn, this, '_handleIn');
-		new SegmentPoint(handleOut, this, '_handleOut');
-		if (selection)
-			this.setSelection(selection);
-	},
-
-	_serialize: function(options, dictionary) {
-		var point = this._point,
-			selection = this._selection,
-			obj = selection || this.hasHandles()
-					? [point, this._handleIn, this._handleOut]
-					: point;
-		if (selection)
-			obj.push(selection);
-		return Base.serialize(obj, options, true, dictionary);
-	},
-
-	_changed: function(point) {
-		var path = this._path;
-		if (!path)
-			return;
-		var curves = path._curves,
-			index = this._index,
-			curve;
-		if (curves) {
-			if ((!point || point === this._point || point === this._handleIn)
-					&& (curve = index > 0 ? curves[index - 1] : path._closed
-						? curves[curves.length - 1] : null))
-				curve._changed();
-			if ((!point || point === this._point || point === this._handleOut)
-					&& (curve = curves[index]))
-				curve._changed();
-		}
-		path._changed(25);
-	},
-
-	getPoint: function() {
-		return this._point;
-	},
-
-	setPoint: function() {
-		var point = Point.read(arguments);
-		this._point.set(point.x, point.y);
-	},
-
-	getHandleIn: function() {
-		return this._handleIn;
-	},
-
-	setHandleIn: function() {
-		var point = Point.read(arguments);
-		this._handleIn.set(point.x, point.y);
-	},
-
-	getHandleOut: function() {
-		return this._handleOut;
-	},
-
-	setHandleOut: function() {
-		var point = Point.read(arguments);
-		this._handleOut.set(point.x, point.y);
-	},
-
-	hasHandles: function() {
-		return !this._handleIn.isZero() || !this._handleOut.isZero();
-	},
-
-	clearHandles: function() {
-		this._handleIn.set(0, 0);
-		this._handleOut.set(0, 0);
-	},
-
-	getSelection: function() {
-		return this._selection;
-	},
-
-	setSelection: function(selection) {
-		var oldSelection = this._selection,
-			path = this._path;
-		this._selection = selection = selection || 0;
-		if (path && selection !== oldSelection) {
-			path._updateSelection(this, oldSelection, selection);
-			path._changed(129);
-		}
-	},
-
-	changeSelection: function(flag, selected) {
-		var selection = this._selection;
-		this.setSelection(selected ? selection | flag : selection & ~flag);
-	},
-
-	isSelected: function() {
-		return !!(this._selection & 7);
-	},
-
-	setSelected: function(selected) {
-		this.changeSelection(7, selected);
-	},
-
-	getIndex: function() {
-		return this._index !== undefined ? this._index : null;
-	},
-
-	getPath: function() {
-		return this._path || null;
-	},
-
-	getCurve: function() {
-		var path = this._path,
-			index = this._index;
-		if (path) {
-			if (index > 0 && !path._closed
-					&& index === path._segments.length - 1)
-				index--;
-			return path.getCurves()[index] || null;
-		}
-		return null;
-	},
-
-	getLocation: function() {
-		var curve = this.getCurve();
-		return curve
-				? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)
-				: null;
-	},
-
-	getNext: function() {
-		var segments = this._path && this._path._segments;
-		return segments && (segments[this._index + 1]
-				|| this._path._closed && segments[0]) || null;
-	},
-
-	smooth: function(options, _first, _last) {
-		var opts = options || {},
-			type = opts.type,
-			factor = opts.factor,
-			prev = this.getPrevious(),
-			next = this.getNext(),
-			p0 = (prev || this)._point,
-			p1 = this._point,
-			p2 = (next || this)._point,
-			d1 = p0.getDistance(p1),
-			d2 = p1.getDistance(p2);
-		if (!type || type === 'catmull-rom') {
-			var a = factor === undefined ? 0.5 : factor,
-				d1_a = Math.pow(d1, a),
-				d1_2a = d1_a * d1_a,
-				d2_a = Math.pow(d2, a),
-				d2_2a = d2_a * d2_a;
-			if (!_first && prev) {
-				var A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,
-					N = 3 * d2_a * (d2_a + d1_a);
-				this.setHandleIn(N !== 0
-					? new Point(
-						(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,
-						(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)
-					: new Point());
-			}
-			if (!_last && next) {
-				var A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,
-					N = 3 * d1_a * (d1_a + d2_a);
-				this.setHandleOut(N !== 0
-					? new Point(
-						(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,
-						(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)
-					: new Point());
-			}
-		} else if (type === 'geometric') {
-			if (prev && next) {
-				var vector = p0.subtract(p2),
-					t = factor === undefined ? 0.4 : factor,
-					k = t * d1 / (d1 + d2);
-				if (!_first)
-					this.setHandleIn(vector.multiply(k));
-				if (!_last)
-					this.setHandleOut(vector.multiply(k - t));
-			}
-		} else {
-			throw new Error('Smoothing method \'' + type + '\' not supported.');
-		}
-	},
-
-	getPrevious: function() {
-		var segments = this._path && this._path._segments;
-		return segments && (segments[this._index - 1]
-				|| this._path._closed && segments[segments.length - 1]) || null;
-	},
-
-	isFirst: function() {
-		return this._index === 0;
-	},
-
-	isLast: function() {
-		var path = this._path;
-		return path && this._index === path._segments.length - 1 || false;
-	},
-
-	reverse: function() {
-		var handleIn = this._handleIn,
-			handleOut = this._handleOut,
-			inX = handleIn._x,
-			inY = handleIn._y;
-		handleIn.set(handleOut._x, handleOut._y);
-		handleOut.set(inX, inY);
-	},
-
-	reversed: function() {
-		return new Segment(this._point, this._handleOut, this._handleIn);
-	},
-
-	remove: function() {
-		return this._path ? !!this._path.removeSegment(this._index) : false;
-	},
-
-	clone: function() {
-		return new Segment(this._point, this._handleIn, this._handleOut);
-	},
-
-	equals: function(segment) {
-		return segment === this || segment && this._class === segment._class
-				&& this._point.equals(segment._point)
-				&& this._handleIn.equals(segment._handleIn)
-				&& this._handleOut.equals(segment._handleOut)
-				|| false;
-	},
-
-	toString: function() {
-		var parts = [ 'point: ' + this._point ];
-		if (!this._handleIn.isZero())
-			parts.push('handleIn: ' + this._handleIn);
-		if (!this._handleOut.isZero())
-			parts.push('handleOut: ' + this._handleOut);
-		return '{ ' + parts.join(', ') + ' }';
-	},
-
-	transform: function(matrix) {
-		this._transformCoordinates(matrix, new Array(6), true);
-		this._changed();
-	},
-
-	interpolate: function(from, to, factor) {
-		var u = 1 - factor,
-			v = factor,
-			point1 = from._point,
-			point2 = to._point,
-			handleIn1 = from._handleIn,
-			handleIn2 = to._handleIn,
-			handleOut2 = to._handleOut,
-			handleOut1 = from._handleOut;
-		this._point.set(
-				u * point1._x + v * point2._x,
-				u * point1._y + v * point2._y, true);
-		this._handleIn.set(
-				u * handleIn1._x + v * handleIn2._x,
-				u * handleIn1._y + v * handleIn2._y, true);
-		this._handleOut.set(
-				u * handleOut1._x + v * handleOut2._x,
-				u * handleOut1._y + v * handleOut2._y, true);
-		this._changed();
-	},
-
-	_transformCoordinates: function(matrix, coords, change) {
-		var point = this._point,
-			handleIn = !change || !this._handleIn.isZero()
-					? this._handleIn : null,
-			handleOut = !change || !this._handleOut.isZero()
-					? this._handleOut : null,
-			x = point._x,
-			y = point._y,
-			i = 2;
-		coords[0] = x;
-		coords[1] = y;
-		if (handleIn) {
-			coords[i++] = handleIn._x + x;
-			coords[i++] = handleIn._y + y;
-		}
-		if (handleOut) {
-			coords[i++] = handleOut._x + x;
-			coords[i++] = handleOut._y + y;
-		}
-		if (matrix) {
-			matrix._transformCoordinates(coords, coords, i / 2);
-			x = coords[0];
-			y = coords[1];
-			if (change) {
-				point._x = x;
-				point._y = y;
-				i = 2;
-				if (handleIn) {
-					handleIn._x = coords[i++] - x;
-					handleIn._y = coords[i++] - y;
-				}
-				if (handleOut) {
-					handleOut._x = coords[i++] - x;
-					handleOut._y = coords[i++] - y;
-				}
-			} else {
-				if (!handleIn) {
-					coords[i++] = x;
-					coords[i++] = y;
-				}
-				if (!handleOut) {
-					coords[i++] = x;
-					coords[i++] = y;
-				}
-			}
-		}
-		return coords;
-	}
-});
-
-var SegmentPoint = Point.extend({
-	initialize: function SegmentPoint(point, owner, key) {
-		var x, y,
-			selected;
-		if (!point) {
-			x = y = 0;
-		} else if ((x = point[0]) !== undefined) {
-			y = point[1];
-		} else {
-			var pt = point;
-			if ((x = pt.x) === undefined) {
-				pt = Point.read(arguments);
-				x = pt.x;
-			}
-			y = pt.y;
-			selected = pt.selected;
-		}
-		this._x = x;
-		this._y = y;
-		this._owner = owner;
-		owner[key] = this;
-		if (selected)
-			this.setSelected(true);
-	},
-
-	set: function(x, y) {
-		this._x = x;
-		this._y = y;
-		this._owner._changed(this);
-		return this;
-	},
-
-	getX: function() {
-		return this._x;
-	},
-
-	setX: function(x) {
-		this._x = x;
-		this._owner._changed(this);
-	},
-
-	getY: function() {
-		return this._y;
-	},
-
-	setY: function(y) {
-		this._y = y;
-		this._owner._changed(this);
-	},
-
-	isZero: function() {
-		return Numerical.isZero(this._x) && Numerical.isZero(this._y);
-	},
-
-	isSelected: function() {
-		return !!(this._owner._selection & this._getSelection());
-	},
-
-	setSelected: function(selected) {
-		this._owner.changeSelection(this._getSelection(), selected);
-	},
-
-	_getSelection: function() {
-		var owner = this._owner;
-		return this === owner._point ? 1
-			: this === owner._handleIn ? 2
-			: this === owner._handleOut ? 4
-			: 0;
-	}
-});
-
-var Curve = Base.extend({
-	_class: 'Curve',
-
-	initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
-		var count = arguments.length,
-			seg1, seg2,
-			point1, point2,
-			handle1, handle2;
-		if (count === 3) {
-			this._path = arg0;
-			seg1 = arg1;
-			seg2 = arg2;
-		} else if (count === 0) {
-			seg1 = new Segment();
-			seg2 = new Segment();
-		} else if (count === 1) {
-			if ('segment1' in arg0) {
-				seg1 = new Segment(arg0.segment1);
-				seg2 = new Segment(arg0.segment2);
-			} else if ('point1' in arg0) {
-				point1 = arg0.point1;
-				handle1 = arg0.handle1;
-				handle2 = arg0.handle2;
-				point2 = arg0.point2;
-			} else if (Array.isArray(arg0)) {
-				point1 = [arg0[0], arg0[1]];
-				point2 = [arg0[6], arg0[7]];
-				handle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];
-				handle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];
-			}
-		} else if (count === 2) {
-			seg1 = new Segment(arg0);
-			seg2 = new Segment(arg1);
-		} else if (count === 4) {
-			point1 = arg0;
-			handle1 = arg1;
-			handle2 = arg2;
-			point2 = arg3;
-		} else if (count === 8) {
-			point1 = [arg0, arg1];
-			point2 = [arg6, arg7];
-			handle1 = [arg2 - arg0, arg3 - arg1];
-			handle2 = [arg4 - arg6, arg5 - arg7];
-		}
-		this._segment1 = seg1 || new Segment(point1, null, handle1);
-		this._segment2 = seg2 || new Segment(point2, handle2, null);
-	},
-
-	_serialize: function(options, dictionary) {
-		return Base.serialize(this.hasHandles()
-				? [this.getPoint1(), this.getHandle1(), this.getHandle2(),
-					this.getPoint2()]
-				: [this.getPoint1(), this.getPoint2()],
-				options, true, dictionary);
-	},
-
-	_changed: function() {
-		this._length = this._bounds = undefined;
-	},
-
-	clone: function() {
-		return new Curve(this._segment1, this._segment2);
-	},
-
-	toString: function() {
-		var parts = [ 'point1: ' + this._segment1._point ];
-		if (!this._segment1._handleOut.isZero())
-			parts.push('handle1: ' + this._segment1._handleOut);
-		if (!this._segment2._handleIn.isZero())
-			parts.push('handle2: ' + this._segment2._handleIn);
-		parts.push('point2: ' + this._segment2._point);
-		return '{ ' + parts.join(', ') + ' }';
-	},
-
-	remove: function() {
-		var removed = false;
-		if (this._path) {
-			var segment2 = this._segment2,
-				handleOut = segment2._handleOut;
-			removed = segment2.remove();
-			if (removed)
-				this._segment1._handleOut.set(handleOut.x, handleOut.y);
-		}
-		return removed;
-	},
-
-	getPoint1: function() {
-		return this._segment1._point;
-	},
-
-	setPoint1: function() {
-		var point = Point.read(arguments);
-		this._segment1._point.set(point.x, point.y);
-	},
-
-	getPoint2: function() {
-		return this._segment2._point;
-	},
-
-	setPoint2: function() {
-		var point = Point.read(arguments);
-		this._segment2._point.set(point.x, point.y);
-	},
-
-	getHandle1: function() {
-		return this._segment1._handleOut;
-	},
-
-	setHandle1: function() {
-		var point = Point.read(arguments);
-		this._segment1._handleOut.set(point.x, point.y);
-	},
-
-	getHandle2: function() {
-		return this._segment2._handleIn;
-	},
-
-	setHandle2: function() {
-		var point = Point.read(arguments);
-		this._segment2._handleIn.set(point.x, point.y);
-	},
-
-	getSegment1: function() {
-		return this._segment1;
-	},
-
-	getSegment2: function() {
-		return this._segment2;
-	},
-
-	getPath: function() {
-		return this._path;
-	},
-
-	getIndex: function() {
-		return this._segment1._index;
-	},
-
-	getNext: function() {
-		var curves = this._path && this._path._curves;
-		return curves && (curves[this._segment1._index + 1]
-				|| this._path._closed && curves[0]) || null;
-	},
-
-	getPrevious: function() {
-		var curves = this._path && this._path._curves;
-		return curves && (curves[this._segment1._index - 1]
-				|| this._path._closed && curves[curves.length - 1]) || null;
-	},
-
-	isFirst: function() {
-		return this._segment1._index === 0;
-	},
-
-	isLast: function() {
-		var path = this._path;
-		return path && this._segment1._index === path._curves.length - 1
-				|| false;
-	},
-
-	isSelected: function() {
-		return this.getPoint1().isSelected()
-				&& this.getHandle2().isSelected()
-				&& this.getHandle2().isSelected()
-				&& this.getPoint2().isSelected();
-	},
-
-	setSelected: function(selected) {
-		this.getPoint1().setSelected(selected);
-		this.getHandle1().setSelected(selected);
-		this.getHandle2().setSelected(selected);
-		this.getPoint2().setSelected(selected);
-	},
-
-	getValues: function(matrix) {
-		return Curve.getValues(this._segment1, this._segment2, matrix);
-	},
-
-	getPoints: function() {
-		var coords = this.getValues(),
-			points = [];
-		for (var i = 0; i < 8; i += 2)
-			points.push(new Point(coords[i], coords[i + 1]));
-		return points;
-	},
-
-	getLength: function() {
-		if (this._length == null)
-			this._length = Curve.getLength(this.getValues(), 0, 1);
-		return this._length;
-	},
-
-	getArea: function() {
-		return Curve.getArea(this.getValues());
-	},
-
-	getLine: function() {
-		return new Line(this._segment1._point, this._segment2._point);
-	},
-
-	getPart: function(from, to) {
-		return new Curve(Curve.getPart(this.getValues(), from, to));
-	},
-
-	getPartLength: function(from, to) {
-		return Curve.getLength(this.getValues(), from, to);
-	},
-
-	getIntersections: function(curve) {
-		return Curve._getIntersections(this.getValues(),
-				curve && curve !== this ? curve.getValues() : null,
-				this, curve, [], {});
-	},
-
-	divideAt: function(location) {
-		return this.divideAtTime(location && location.curve === this
-				? location.time : location);
-	},
-
-	divideAtTime: function(time, _setHandles) {
-		var tMin = 4e-7,
-			tMax = 1 - tMin,
-			res = null;
-		if (time >= tMin && time <= tMax) {
-			var parts = Curve.subdivide(this.getValues(), time),
-				left = parts[0],
-				right = parts[1],
-				setHandles = _setHandles || this.hasHandles(),
-				segment1 = this._segment1,
-				segment2 = this._segment2,
-				path = this._path;
-			if (setHandles) {
-				segment1._handleOut.set(left[2] - left[0], left[3] - left[1]);
-				segment2._handleIn.set(right[4] - right[6],right[5] - right[7]);
-			}
-			var x = left[6], y = left[7],
-				segment = new Segment(new Point(x, y),
-						setHandles && new Point(left[4] - x, left[5] - y),
-						setHandles && new Point(right[2] - x, right[3] - y));
-			if (path) {
-				path.insert(segment1._index + 1, segment);
-				res = this.getNext();
-			} else {
-				this._segment2 = segment;
-				this._changed();
-				res = new Curve(segment, segment2);
-			}
-		}
-		return res;
-	},
-
-	splitAt: function(location) {
-		return this._path ? this._path.splitAt(location) : null;
-	},
-
-	splitAtTime: function(t) {
-		return this.splitAt(this.getLocationAtTime(t));
-	},
-
-	divide: function(offset, isTime) {
-		return this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset
-				: this.getTimeAt(offset));
-	},
-
-	split: function(offset, isTime) {
-		return this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset
-				: this.getTimeAt(offset));
-	},
-
-	reversed: function() {
-		return new Curve(this._segment2.reversed(), this._segment1.reversed());
-	},
-
-	clearHandles: function() {
-		this._segment1._handleOut.set(0, 0);
-		this._segment2._handleIn.set(0, 0);
-	},
-
-statics: {
-	getValues: function(segment1, segment2, matrix) {
-		var p1 = segment1._point,
-			h1 = segment1._handleOut,
-			h2 = segment2._handleIn,
-			p2 = segment2._point,
-			values = [
-				p1._x, p1._y,
-				p1._x + h1._x, p1._y + h1._y,
-				p2._x + h2._x, p2._y + h2._y,
-				p2._x, p2._y
-			];
-		if (matrix)
-			matrix._transformCoordinates(values, values, 4);
-		return values;
-	},
-
-	subdivide: function(v, t) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7];
-		if (t === undefined)
-			t = 0.5;
-		var u = 1 - t,
-			p3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,
-			p4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,
-			p5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,
-			p6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,
-			p7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,
-			p8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;
-		return [
-			[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],
-			[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]
-		];
-	},
-
-	solveCubic: function (v, coord, val, roots, min, max) {
-		var p1 = v[coord],
-			c1 = v[coord + 2],
-			c2 = v[coord + 4],
-			p2 = v[coord + 6],
-			res = 0;
-		if (  !(p1 < val && p2 < val && c1 < val && c2 < val ||
-				p1 > val && p2 > val && c1 > val && c2 > val)) {
-			var c = 3 * (c1 - p1),
-				b = 3 * (c2 - c1) - c,
-				a = p2 - p1 - c - b;
-			res = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
-		}
-		return res;
-	},
-
-	getTimeOf: function(v, point) {
-		var p1 = new Point(v[0], v[1]),
-			p2 = new Point(v[6], v[7]),
-			epsilon = 1e-12,
-			t = point.isClose(p1, epsilon) ? 0
-			  : point.isClose(p2, epsilon) ? 1
-			  : null;
-		if (t !== null)
-			return t;
-		var coords = [point.x, point.y],
-			roots = [],
-			geomEpsilon = 2e-7;
-		for (var c = 0; c < 2; c++) {
-			var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);
-			for (var i = 0; i < count; i++) {
-				t = roots[i];
-				if (point.isClose(Curve.getPoint(v, t), geomEpsilon))
-					return t;
-			}
-		}
-		return point.isClose(p1, geomEpsilon) ? 0
-			 : point.isClose(p2, geomEpsilon) ? 1
-			 : null;
-	},
-
-	getNearestTime: function(v, point) {
-		if (Curve.isStraight(v)) {
-			var p1x = v[0], p1y = v[1],
-				p2x = v[6], p2y = v[7],
-				vx = p2x - p1x, vy = p2y - p1y,
-				det = vx * vx + vy * vy;
-			if (det === 0)
-				return 0;
-			var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
-			return u < 1e-12 ? 0
-				 : u > 0.999999999999 ? 1
-				 : Curve.getTimeOf(v,
-					new Point(p1x + u * vx, p1y + u * vy));
-		}
-
-		var count = 100,
-			minDist = Infinity,
-			minT = 0;
-
-		function refine(t) {
-			if (t >= 0 && t <= 1) {
-				var dist = point.getDistance(Curve.getPoint(v, t), true);
-				if (dist < minDist) {
-					minDist = dist;
-					minT = t;
-					return true;
-				}
-			}
-		}
-
-		for (var i = 0; i <= count; i++)
-			refine(i / count);
-
-		var step = 1 / (count * 2);
-		while (step > 4e-7) {
-			if (!refine(minT - step) && !refine(minT + step))
-				step /= 2;
-		}
-		return minT;
-	},
-
-	getPart: function(v, from, to) {
-		var flip = from > to;
-		if (flip) {
-			var tmp = from;
-			from = to;
-			to = tmp;
-		}
-		if (from > 0)
-			v = Curve.subdivide(v, from)[1];
-		if (to < 1)
-			v = Curve.subdivide(v, (to - from) / (1 - from))[0];
-		return flip
-				? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]
-				: v;
-	},
-
-	isFlatEnough: function(v, flatness) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7],
-			ux = 3 * c1x - 2 * p1x - p2x,
-			uy = 3 * c1y - 2 * p1y - p2y,
-			vx = 3 * c2x - 2 * p2x - p1x,
-			vy = 3 * c2y - 2 * p2y - p1y;
-		return Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)
-				<= 16 * flatness * flatness;
-	},
-
-	getArea: function(v) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7];
-		return 3 * ((p2y - p1y) * (c1x + c2x) - (p2x - p1x) * (c1y + c2y)
-				+ c1y * (p1x - c2x) - c1x * (p1y - c2y)
-				+ p2y * (c2x + p1x / 3) - p2x * (c2y + p1y / 3)) / 20;
-	},
-
-	getBounds: function(v) {
-		var min = v.slice(0, 2),
-			max = min.slice(),
-			roots = [0, 0];
-		for (var i = 0; i < 2; i++)
-			Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
-					i, 0, min, max, roots);
-		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
-	},
-
-	_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
-		function add(value, padding) {
-			var left = value - padding,
-				right = value + padding;
-			if (left < min[coord])
-				min[coord] = left;
-			if (right > max[coord])
-				max[coord] = right;
-		}
-
-		padding /= 2;
-		var minPad = min[coord] - padding,
-			maxPad = max[coord] + padding;
-		if (    v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||
-				v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
-			if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {
-				add(v0, padding);
-				add(v3, padding);
-			} else {
-				var a = 3 * (v1 - v2) - v0 + v3,
-					b = 2 * (v0 + v2) - 4 * v1,
-					c = v1 - v0,
-					count = Numerical.solveQuadratic(a, b, c, roots),
-					tMin = 4e-7,
-					tMax = 1 - tMin;
-				add(v3, 0);
-				for (var i = 0; i < count; i++) {
-					var t = roots[i],
-						u = 1 - t;
-					if (tMin < t && t < tMax)
-						add(u * u * u * v0
-							+ 3 * u * u * t * v1
-							+ 3 * u * t * t * v2
-							+ t * t * t * v3,
-							padding);
-				}
-			}
-		}
-	}
-}}, Base.each(
-	['getBounds', 'getStrokeBounds', 'getHandleBounds'],
-	function(name) {
-		this[name] = function() {
-			if (!this._bounds)
-				this._bounds = {};
-			var bounds = this._bounds[name];
-			if (!bounds) {
-				bounds = this._bounds[name] = Path[name](
-						[this._segment1, this._segment2], false, this._path);
-			}
-			return bounds.clone();
-		};
-	},
-{
-
-}), Base.each({
-	isStraight: function(l, h1, h2) {
-		if (h1.isZero() && h2.isZero()) {
-			return true;
-		} else {
-			var v = l.getVector(),
-				epsilon = 2e-7;
-			if (v.isZero()) {
-				return false;
-			} else if (l.getDistance(h1) < epsilon
-					&& l.getDistance(h2) < epsilon) {
-				var div = v.dot(v),
-					p1 = v.dot(h1) / div,
-					p2 = v.dot(h2) / div;
-				return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
-			}
-		}
-		return false;
-	},
-
-	isLinear: function(l, h1, h2) {
-		var third = l.getVector().divide(3);
-		return h1.equals(third) && h2.negate().equals(third);
-	}
-}, function(test, name) {
-	this[name] = function() {
-		var seg1 = this._segment1,
-			seg2 = this._segment2;
-		return test(new Line(seg1._point, seg2._point),
-				seg1._handleOut, seg2._handleIn);
-	};
-
-	this.statics[name] = function(v) {
-		var p1x = v[0], p1y = v[1],
-			p2x = v[6], p2y = v[7];
-		return test(new Line(p1x, p1y, p2x, p2y),
-				new Point(v[2] - p1x, v[3] - p1y),
-				new Point(v[4] - p2x, v[5] - p2y));
-	};
-}, {
-	statics: {},
-
-	hasHandles: function() {
-		return !this._segment1._handleOut.isZero()
-				|| !this._segment2._handleIn.isZero();
-	},
-
-	isCollinear: function(curve) {
-		return curve && this.isStraight() && curve.isStraight()
-				&& this.getLine().isCollinear(curve.getLine());
-	},
-
-	isHorizontal: function() {
-		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)
-				< 1e-7;
-	},
-
-	isVertical: function() {
-		return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)
-				< 1e-7;
-	}
-}), {
-	beans: false,
-
-	getLocationAt: function(offset, _isTime) {
-		return this.getLocationAtTime(
-				_isTime ? offset : this.getTimeAt(offset));
-	},
-
-	getLocationAtTime: function(t) {
-		return t != null && t >= 0 && t <= 1
-				? new CurveLocation(this, t)
-				: null;
-	},
-
-	getTimeAt: function(offset, start) {
-		return Curve.getTimeAt(this.getValues(), offset, start);
-	},
-
-	getParameterAt: '#getTimeAt',
-
-	getOffsetAtTime: function(t) {
-		return this.getPartLength(0, t);
-	},
-
-	getLocationOf: function() {
-		return this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));
-	},
-
-	getOffsetOf: function() {
-		var loc = this.getLocationOf.apply(this, arguments);
-		return loc ? loc.getOffset() : null;
-	},
-
-	getTimeOf: function() {
-		return Curve.getTimeOf(this.getValues(), Point.read(arguments));
-	},
-
-	getParameterOf: '#getTimeOf',
-
-	getNearestLocation: function() {
-		var point = Point.read(arguments),
-			values = this.getValues(),
-			t = Curve.getNearestTime(values, point),
-			pt = Curve.getPoint(values, t);
-		return new CurveLocation(this, t, pt, null, point.getDistance(pt));
-	},
-
-	getNearestPoint: function() {
-		var loc = this.getNearestLocation.apply(this, arguments);
-		return loc ? loc.getPoint() : loc;
-	}
-
-},
-new function() {
-	var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
-		'getWeightedNormal', 'getCurvature'];
-	return Base.each(methods,
-		function(name) {
-			this[name + 'At'] = function(location, _isTime) {
-				var values = this.getValues();
-				return Curve[name](values, _isTime ? location
-						: Curve.getTimeAt(values, location));
-			};
-
-			this[name + 'AtTime'] = function(time) {
-				return Curve[name](this.getValues(), time);
-			};
-		}, {
-			statics: {
-				_evaluateMethods: methods
-			}
-		}
-	);
-},
-new function() {
-
-	function getLengthIntegrand(v) {
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7],
-
-			ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
-			bx = 6 * (p1x + c2x) - 12 * c1x,
-			cx = 3 * (c1x - p1x),
-
-			ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
-			by = 6 * (p1y + c2y) - 12 * c1y,
-			cy = 3 * (c1y - p1y);
-
-		return function(t) {
-			var dx = (ax * t + bx) * t + cx,
-				dy = (ay * t + by) * t + cy;
-			return Math.sqrt(dx * dx + dy * dy);
-		};
-	}
-
-	function getIterations(a, b) {
-		return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
-	}
-
-	function evaluate(v, t, type, normalized) {
-		if (t == null || t < 0 || t > 1)
-			return null;
-		var p1x = v[0], p1y = v[1],
-			c1x = v[2], c1y = v[3],
-			c2x = v[4], c2y = v[5],
-			p2x = v[6], p2y = v[7],
-			isZero = Numerical.isZero;
-		if (isZero(c1x - p1x) && isZero(c1y - p1y)) {
-			c1x = p1x;
-			c1y = p1y;
-		}
-		if (isZero(c2x - p2x) && isZero(c2y - p2y)) {
-			c2x = p2x;
-			c2y = p2y;
-		}
-		var cx = 3 * (c1x - p1x),
-			bx = 3 * (c2x - c1x) - cx,
-			ax = p2x - p1x - cx - bx,
-			cy = 3 * (c1y - p1y),
-			by = 3 * (c2y - c1y) - cy,
-			ay = p2y - p1y - cy - by,
-			x, y;
-		if (type === 0) {
-			x = t === 0 ? p1x : t === 1 ? p2x
-					: ((ax * t + bx) * t + cx) * t + p1x;
-			y = t === 0 ? p1y : t === 1 ? p2y
-					: ((ay * t + by) * t + cy) * t + p1y;
-		} else {
-			var tMin = 4e-7,
-				tMax = 1 - tMin;
-			if (t < tMin) {
-				x = cx;
-				y = cy;
-			} else if (t > tMax) {
-				x = 3 * (p2x - c2x);
-				y = 3 * (p2y - c2y);
-			} else {
-				x = (3 * ax * t + 2 * bx) * t + cx;
-				y = (3 * ay * t + 2 * by) * t + cy;
-			}
-			if (normalized) {
-				if (x === 0 && y === 0 && (t < tMin || t > tMax)) {
-					x = c2x - c1x;
-					y = c2y - c1y;
-				}
-				var len = Math.sqrt(x * x + y * y);
-				if (len) {
-					x /= len;
-					y /= len;
-				}
-			}
-			if (type === 3) {
-				var x2 = 6 * ax * t + 2 * bx,
-					y2 = 6 * ay * t + 2 * by,
-					d = Math.pow(x * x + y * y, 3 / 2);
-				x = d !== 0 ? (x * y2 - y * x2) / d : 0;
-				y = 0;
-			}
-		}
-		return type === 2 ? new Point(y, -x) : new Point(x, y);
-	}
-
-	return { statics: {
-
-		getLength: function(v, a, b, ds) {
-			if (a === undefined)
-				a = 0;
-			if (b === undefined)
-				b = 1;
-			if (Curve.isStraight(v)) {
-				var c = v;
-				if (b < 1) {
-					c = Curve.subdivide(c, b)[0];
-					a /= b;
-				}
-				if (a > 0) {
-					c = Curve.subdivide(c, a)[1];
-				}
-				var dx = c[6] - c[0],
-					dy = c[7] - c[1];
-				return Math.sqrt(dx * dx + dy * dy);
-			}
-			return Numerical.integrate(ds || getLengthIntegrand(v), a, b,
-					getIterations(a, b));
-		},
-
-		getTimeAt: function(v, offset, start) {
-			if (start === undefined)
-				start = offset < 0 ? 1 : 0;
-			if (offset === 0)
-				return start;
-			var abs = Math.abs,
-				epsilon = 1e-12,
-				forward = offset > 0,
-				a = forward ? start : 0,
-				b = forward ? 1 : start,
-				ds = getLengthIntegrand(v),
-				rangeLength = Curve.getLength(v, a, b, ds),
-				diff = abs(offset) - rangeLength;
-			if (abs(diff) < epsilon) {
-				return forward ? b : a;
-			} else if (diff > epsilon) {
-				return null;
-			}
-			var guess = offset / rangeLength,
-				length = 0;
-			function f(t) {
-				length += Numerical.integrate(ds, start, t,
-						getIterations(start, t));
-				start = t;
-				return length - offset;
-			}
-			return Numerical.findRoot(f, ds, start + guess, a, b, 32,
-					1e-12);
-		},
-
-		getPoint: function(v, t) {
-			return evaluate(v, t, 0, false);
-		},
-
-		getTangent: function(v, t) {
-			return evaluate(v, t, 1, true);
-		},
-
-		getWeightedTangent: function(v, t) {
-			return evaluate(v, t, 1, false);
-		},
-
-		getNormal: function(v, t) {
-			return evaluate(v, t, 2, true);
-		},
-
-		getWeightedNormal: function(v, t) {
-			return evaluate(v, t, 2, false);
-		},
-
-		getCurvature: function(v, t) {
-			return evaluate(v, t, 3, false).x;
-		}
-	}};
-},
-new function() {
-
-	function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
-			overlap) {
-		var excludeStart = !overlap && param.excludeStart,
-			excludeEnd = !overlap && param.excludeEnd,
-			tMin = 4e-7,
-			tMax = 1 - tMin;
-		if (t1 == null)
-			t1 = Curve.getTimeOf(v1, p1);
-		if (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&
-			t1 <= (excludeEnd ? tMax : 1)) {
-			if (t2 == null)
-				t2 = Curve.getTimeOf(v2, p2);
-			if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
-				t2 <= (excludeStart ? tMax : 1)) {
-				var renormalize = param.renormalize;
-				if (renormalize) {
-					var res = renormalize(t1, t2);
-					t1 = res[0];
-					t2 = res[1];
-				}
-				var loc1 = new CurveLocation(c1, t1,
-						p1 || Curve.getPoint(v1, t1), overlap),
-					loc2 = new CurveLocation(c2, t2,
-						p2 || Curve.getPoint(v2, t2), overlap),
-					flip = loc1.getPath() === loc2.getPath()
-						&& loc1.getIndex() > loc2.getIndex(),
-					loc = flip ? loc2 : loc1,
-					include = param.include;
-				loc1._intersection = loc2;
-				loc2._intersection = loc1;
-				if (!include || include(loc)) {
-					CurveLocation.insert(locations, loc, true);
-				}
-			}
-		}
-	}
-
-	function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,
-			uMin, uMax, flip, recursion, calls) {
-		if (++recursion >= 48 || ++calls > 4096)
-			return calls;
-		var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
-			getSignedDistance = Line.getSignedDistance,
-			d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),
-			d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),
-			factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
-			dMin = factor * Math.min(0, d1, d2),
-			dMax = factor * Math.max(0, d1, d2),
-			dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
-			dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
-			dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
-			dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
-			hull = getConvexHull(dp0, dp1, dp2, dp3),
-			top = hull[0],
-			bottom = hull[1],
-			tMinClip,
-			tMaxClip;
-		if (d1 === 0 && d2 === 0
-				&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0
-			|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null
-			|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),
-				dMin, dMax)) == null)
-			return calls;
-		var tMinNew = tMin + (tMax - tMin) * tMinClip,
-			tMaxNew = tMin + (tMax - tMin) * tMaxClip;
-		if (Math.max(uMax - uMin, tMaxNew - tMinNew)
-				< 1e-9) {
-			var t = (tMinNew + tMaxNew) / 2,
-				u = (uMin + uMax) / 2;
-			v1 = c1.getValues();
-			v2 = c2.getValues();
-			addLocation(locations, param,
-					flip ? v2 : v1, flip ? c2 : c1, flip ? u : t, null,
-					flip ? v1 : v2, flip ? c1 : c2, flip ? t : u, null);
-		} else {
-			v1 = Curve.getPart(v1, tMinClip, tMaxClip);
-			if (tMaxClip - tMinClip > 0.8) {
-				if (tMaxNew - tMinNew > uMax - uMin) {
-					var parts = Curve.subdivide(v1, 0.5),
-						t = (tMinNew + tMaxNew) / 2;
-					calls = addCurveIntersections(
-							v2, parts[0], c2, c1, locations, param,
-							uMin, uMax, tMinNew, t, !flip, recursion, calls);
-					calls = addCurveIntersections(
-							v2, parts[1], c2, c1, locations, param,
-							uMin, uMax, t, tMaxNew, !flip, recursion, calls);
-				} else {
-					var parts = Curve.subdivide(v2, 0.5),
-						u = (uMin + uMax) / 2;
-					calls = addCurveIntersections(
-							parts[0], v1, c2, c1, locations, param,
-							uMin, u, tMinNew, tMaxNew, !flip, recursion, calls);
-					calls = addCurveIntersections(
-							parts[1], v1, c2, c1, locations, param,
-							u, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
-				}
-			} else {
-				calls = addCurveIntersections(
-						v2, v1, c2, c1, locations, param,
-						uMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
-			}
-		}
-		return calls;
-	}
-
-	function getConvexHull(dq0, dq1, dq2, dq3) {
-		var p0 = [ 0, dq0 ],
-			p1 = [ 1 / 3, dq1 ],
-			p2 = [ 2 / 3, dq2 ],
-			p3 = [ 1, dq3 ],
-			dist1 = dq1 - (2 * dq0 + dq3) / 3,
-			dist2 = dq2 - (dq0 + 2 * dq3) / 3,
-			hull;
-		if (dist1 * dist2 < 0) {
-			hull = [[p0, p1, p3], [p0, p2, p3]];
-		} else {
-			var distRatio = dist1 / dist2;
-			hull = [
-				distRatio >= 2 ? [p0, p1, p3]
-				: distRatio <= 0.5 ? [p0, p2, p3]
-				: [p0, p1, p2, p3],
-				[p0, p3]
-			];
-		}
-		return (dist1 || dist2) < 0 ? hull.reverse() : hull;
-	}
-
-	function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
-		if (hullTop[0][1] < dMin) {
-			return clipConvexHullPart(hullTop, true, dMin);
-		} else if (hullBottom[0][1] > dMax) {
-			return clipConvexHullPart(hullBottom, false, dMax);
-		} else {
-			return hullTop[0][0];
-		}
-	}
-
-	function clipConvexHullPart(part, top, threshold) {
-		var px = part[0][0],
-			py = part[0][1];
-		for (var i = 1, l = part.length; i < l; i++) {
-			var qx = part[i][0],
-				qy = part[i][1];
-			if (top ? qy >= threshold : qy <= threshold) {
-				return qy === threshold ? qx
-						: px + (threshold - py) * (qx - px) / (qy - py);
-			}
-			px = qx;
-			py = qy;
-		}
-		return null;
-	}
-
-	function addCurveLineIntersections(v1, v2, c1, c2, locations, param) {
-		var flip = Curve.isStraight(v1),
-			vc = flip ? v2 : v1,
-			vl = flip ? v1 : v2,
-			lx1 = vl[0], ly1 = vl[1],
-			lx2 = vl[6], ly2 = vl[7],
-			ldx = lx2 - lx1,
-			ldy = ly2 - ly1,
-			angle = Math.atan2(-ldy, ldx),
-			sin = Math.sin(angle),
-			cos = Math.cos(angle),
-			rvc = [];
-		for(var i = 0; i < 8; i += 2) {
-			var x = vc[i] - lx1,
-				y = vc[i + 1] - ly1;
-			rvc.push(
-				x * cos - y * sin,
-				x * sin + y * cos);
-		}
-		var roots = [],
-			count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
-		for (var i = 0; i < count; i++) {
-			var tc = roots[i],
-				pc = Curve.getPoint(vc, tc),
-				tl = Curve.getTimeOf(vl, pc);
-			if (tl !== null) {
-				var pl = Curve.getPoint(vl, tl),
-					t1 = flip ? tl : tc,
-					t2 = flip ? tc : tl;
-				if (!param.excludeEnd || t2 > Numerical.CURVETIME_EPSILON) {
-					addLocation(locations, param,
-							v1, c1, t1, flip ? pl : pc,
-							v2, c2, t2, flip ? pc : pl);
-				}
-			}
-		}
-	}
-
-	function addLineIntersection(v1, v2, c1, c2, locations, param) {
-		var pt = Line.intersect(
-				v1[0], v1[1], v1[6], v1[7],
-				v2[0], v2[1], v2[6], v2[7]);
-		if (pt) {
-			addLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);
-		}
-	}
-
-	return { statics: {
-		_getIntersections: function(v1, v2, c1, c2, locations, param) {
-			if (!v2) {
-				return Curve._getSelfIntersection(v1, c1, locations, param);
-			}
-			var epsilon = 2e-7,
-				c1p1x = v1[0], c1p1y = v1[1],
-				c1p2x = v1[6], c1p2y = v1[7],
-				c2p1x = v2[0], c2p1y = v2[1],
-				c2p2x = v2[6], c2p2y = v2[7],
-				c1s1x = (3 * v1[2] + c1p1x) / 4,
-				c1s1y = (3 * v1[3] + c1p1y) / 4,
-				c1s2x = (3 * v1[4] + c1p2x) / 4,
-				c1s2y = (3 * v1[5] + c1p2y) / 4,
-				c2s1x = (3 * v2[2] + c2p1x) / 4,
-				c2s1y = (3 * v2[3] + c2p1y) / 4,
-				c2s2x = (3 * v2[4] + c2p2x) / 4,
-				c2s2y = (3 * v2[5] + c2p2y) / 4,
-				min = Math.min,
-				max = Math.max;
-			if (!(  max(c1p1x, c1s1x, c1s2x, c1p2x) + epsilon >
-					min(c2p1x, c2s1x, c2s2x, c2p2x) &&
-					min(c1p1x, c1s1x, c1s2x, c1p2x) - epsilon <
-					max(c2p1x, c2s1x, c2s2x, c2p2x) &&
-					max(c1p1y, c1s1y, c1s2y, c1p2y) + epsilon >
-					min(c2p1y, c2s1y, c2s2y, c2p2y) &&
-					min(c1p1y, c1s1y, c1s2y, c1p2y) - epsilon <
-					max(c2p1y, c2s1y, c2s2y, c2p2y)))
-				return locations;
-			var overlaps = Curve.getOverlaps(v1, v2);
-			if (overlaps) {
-				for (var i = 0; i < 2; i++) {
-					var overlap = overlaps[i];
-					addLocation(locations, param,
-						v1, c1, overlap[0], null,
-						v2, c2, overlap[1], null, true);
-				}
-				return locations;
-			}
-
-			var straight1 = Curve.isStraight(v1),
-				straight2 = Curve.isStraight(v2),
-				straight = straight1 && straight2,
-				before = locations.length;
-			(straight
-				? addLineIntersection
-				: straight1 || straight2
-					? addCurveLineIntersections
-					: addCurveIntersections)(
-						v1, v2, c1, c2, locations, param,
-						0, 1, 0, 1, 0, 0, 0);
-			if (straight && locations.length > before)
-				return locations;
-			var c1p1 = new Point(c1p1x, c1p1y),
-				c1p2 = new Point(c1p2x, c1p2y),
-				c2p1 = new Point(c2p1x, c2p1y),
-				c2p2 = new Point(c2p2x, c2p2y);
-			if (c1p1.isClose(c2p1, epsilon))
-				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);
-			if (!param.excludeStart && c1p1.isClose(c2p2, epsilon))
-				addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);
-			if (!param.excludeEnd && c1p2.isClose(c2p1, epsilon))
-				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);
-			if (c1p2.isClose(c2p2, epsilon))
-				addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);
-			return locations;
-		},
-
-		_getSelfIntersection: function(v1, c1, locations, param) {
-			var p1x = v1[0], p1y = v1[1],
-				h1x = v1[2], h1y = v1[3],
-				h2x = v1[4], h2y = v1[5],
-				p2x = v1[6], p2y = v1[7];
-			var line = new Line(p1x, p1y, p2x, p2y, false),
-				side1 = line.getSide(new Point(h1x, h1y), true),
-				side2 = line.getSide(new Point(h2x, h2y), true);
-			if (side1 === side2) {
-				var edgeSum = (p1x - h2x) * (h1y - p2y)
-							+ (h1x - p2x) * (h2y - p1y);
-				if (edgeSum * side1 > 0)
-					return locations;
-			}
-			var ax = p2x - 3 * h2x + 3 * h1x - p1x,
-				bx = h2x - 2 * h1x + p1x,
-				cx = h1x - p1x,
-				ay = p2y - 3 * h2y + 3 * h1y - p1y,
-				by = h2y - 2 * h1y + p1y,
-				cy = h1y - p1y,
-				ac = ay * cx - ax * cy,
-				ab = ay * bx - ax * by,
-				bc = by * cx - bx * cy;
-			if (ac * ac - 4 * ab * bc < 0) {
-				var roots = [],
-					tSplit,
-					count = Numerical.solveCubic(
-							ax * ax  + ay * ay,
-							3 * (ax * bx + ay * by),
-							2 * (bx * bx + by * by) + ax * cx + ay * cy,
-							bx * cx + by * cy,
-							roots, 0, 1);
-				if (count > 0) {
-					for (var i = 0, maxCurvature = 0; i < count; i++) {
-						var curvature = Math.abs(
-								c1.getCurvatureAtTime(roots[i]));
-						if (curvature > maxCurvature) {
-							maxCurvature = curvature;
-							tSplit = roots[i];
-						}
-					}
-					var parts = Curve.subdivide(v1, tSplit);
-					param.excludeEnd = true;
-					param.renormalize = function(t1, t2) {
-						return [t1 * tSplit, t2 * (1 - tSplit) + tSplit];
-					};
-					Curve._getIntersections(parts[0], parts[1], c1, c1,
-							locations, param);
-				}
-			}
-			return locations;
-		},
-
-		getOverlaps: function(v1, v2) {
-			var abs = Math.abs,
-				timeEpsilon = 4e-7,
-				geomEpsilon = 2e-7,
-				straight1 = Curve.isStraight(v1),
-				straight2 = Curve.isStraight(v2),
-				straightBoth = straight1 && straight2;
-
-			function getSquaredLineLength(v) {
-				var x = v[6] - v[0],
-					y = v[7] - v[1];
-				return x * x + y * y;
-			}
-
-			var flip = getSquaredLineLength(v1) < getSquaredLineLength(v2),
-				l1 = flip ? v2 : v1,
-				l2 = flip ? v1 : v2,
-				line = new Line(l1[0], l1[1], l1[6], l1[7]);
-			if (line.getDistance(new Point(l2[0], l2[1])) < geomEpsilon &&
-				line.getDistance(new Point(l2[6], l2[7])) < geomEpsilon) {
-				if (!straightBoth &&
-					line.getDistance(new Point(l1[2], l1[3])) < geomEpsilon &&
-					line.getDistance(new Point(l1[4], l1[5])) < geomEpsilon &&
-					line.getDistance(new Point(l2[2], l2[3])) < geomEpsilon &&
-					line.getDistance(new Point(l2[4], l2[5])) < geomEpsilon) {
-					straight1 = straight2 = straightBoth = true;
-				}
-			} else if (straightBoth) {
-				return null;
-			}
-			if (straight1 ^ straight2) {
-				return null;
-			}
-
-			var v = [v1, v2],
-				pairs = [];
-			for (var i = 0, t1 = 0;
-					i < 2 && pairs.length < 2;
-					i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
-				var t2 = Curve.getTimeOf(v[i ^ 1], new Point(
-						v[i][t1 === 0 ? 0 : 6],
-						v[i][t1 === 0 ? 1 : 7]));
-				if (t2 != null) {
-					var pair = i === 0 ? [t1, t2] : [t2, t1];
-					if (pairs.length === 0 ||
-						abs(pair[0] - pairs[0][0]) > timeEpsilon &&
-						abs(pair[1] - pairs[0][1]) > timeEpsilon)
-						pairs.push(pair);
-				}
-				if (i === 1 && pairs.length === 0)
-					break;
-			}
-			if (pairs.length !== 2) {
-				pairs = null;
-			} else if (!straightBoth) {
-				var o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),
-					o2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);
-				if (abs(o2[2] - o1[2]) > geomEpsilon ||
-					abs(o2[3] - o1[3]) > geomEpsilon ||
-					abs(o2[4] - o1[4]) > geomEpsilon ||
-					abs(o2[5] - o1[5]) > geomEpsilon)
-					pairs = null;
-			}
-			return pairs;
-		}
-	}};
-});
-
-var CurveLocation = Base.extend({
-	_class: 'CurveLocation',
-	beans: true,
-
-	initialize: function CurveLocation(curve, time, point, _overlap, _distance) {
-		if (time > 0.9999996) {
-			var next = curve.getNext();
-			if (next) {
-				time = 0;
-				curve = next;
-			}
-		}
-		this._setCurve(curve);
-		this._time = time;
-		this._point = point || curve.getPointAtTime(time);
-		this._overlap = _overlap;
-		this._distance = _distance;
-		this._intersection = this._next = this._previous = null;
-	},
-
-	_setCurve: function(curve) {
-		var path = curve._path;
-		this._path = path;
-		this._version = path ? path._version : 0;
-		this._curve = curve;
-		this._segment = null;
-		this._segment1 = curve._segment1;
-		this._segment2 = curve._segment2;
-	},
-
-	_setSegment: function(segment) {
-		this._setCurve(segment.getCurve());
-		this._segment = segment;
-		this._time = segment === this._segment1 ? 0 : 1;
-		this._point = segment._point.clone();
-	},
-
-	getSegment: function() {
-		var curve = this.getCurve(),
-			segment = this._segment;
-		if (!segment) {
-			var time = this.getTime();
-			if (time === 0) {
-				segment = curve._segment1;
-			} else if (time === 1) {
-				segment = curve._segment2;
-			} else if (time != null) {
-				segment = curve.getPartLength(0, time)
-					< curve.getPartLength(time, 1)
-						? curve._segment1
-						: curve._segment2;
-			}
-			this._segment = segment;
-		}
-		return segment;
-	},
-
-	getCurve: function() {
-		var path = this._path,
-			that = this;
-		if (path && path._version !== this._version) {
-			this._time = this._curve = this._offset = null;
-		}
-
-		function trySegment(segment) {
-			var curve = segment && segment.getCurve();
-			if (curve && (that._time = curve.getTimeOf(that._point))
-					!= null) {
-				that._setCurve(curve);
-				that._segment = segment;
-				return curve;
-			}
-		}
-
-		return this._curve
-			|| trySegment(this._segment)
-			|| trySegment(this._segment1)
-			|| trySegment(this._segment2.getPrevious());
-	},
-
-	getPath: function() {
-		var curve = this.getCurve();
-		return curve && curve._path;
-	},
-
-	getIndex: function() {
-		var curve = this.getCurve();
-		return curve && curve.getIndex();
-	},
-
-	getTime: function() {
-		var curve = this.getCurve(),
-			time = this._time;
-		return curve && time == null
-			? this._time = curve.getTimeOf(this._point)
-			: time;
-	},
-
-	getParameter: '#getTime',
-
-	getPoint: function() {
-		return this._point;
-	},
-
-	getOffset: function() {
-		var offset = this._offset;
-		if (offset == null) {
-			offset = 0;
-			var path = this.getPath(),
-				index = this.getIndex();
-			if (path && index != null) {
-				var curves = path.getCurves();
-				for (var i = 0; i < index; i++)
-					offset += curves[i].getLength();
-			}
-			this._offset = offset += this.getCurveOffset();
-		}
-		return offset;
-	},
-
-	getCurveOffset: function() {
-		var curve = this.getCurve(),
-			time = this.getTime();
-		return time != null && curve && curve.getPartLength(0, time);
-	},
-
-	getIntersection: function() {
-		return this._intersection;
-	},
-
-	getDistance: function() {
-		return this._distance;
-	},
-
-	divide: function() {
-		var curve = this.getCurve(),
-			res = null;
-		if (curve) {
-			res = curve.divideAtTime(this.getTime());
-			if (res)
-				this._setSegment(res._segment1);
-		}
-		return res;
-	},
-
-	split: function() {
-		var curve = this.getCurve();
-		return curve ? curve.splitAtTime(this.getTime()) : null;
-	},
-
-	equals: function(loc, _ignoreOther) {
-		var res = this === loc,
-			epsilon = 2e-7;
-		if (!res && loc instanceof CurveLocation
-				&& this.getPath() === loc.getPath()
-				&& this.getPoint().isClose(loc.getPoint(), epsilon)) {
-			var c1 = this.getCurve(),
-				c2 = loc.getCurve(),
-				abs = Math.abs,
-				diff = abs(
-					((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
-							+ this.getTime()) -
-					((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
-							+ loc.getTime()));
-			res = (diff < 4e-7
-				|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon
-					|| abs(this.getPath().getLength() - diff) < epsilon))
-				&& (_ignoreOther
-					|| (!this._intersection && !loc._intersection
-						|| this._intersection && this._intersection.equals(
-								loc._intersection, true)));
-		}
-		return res;
-	},
-
-	toString: function() {
-		var parts = [],
-			point = this.getPoint(),
-			f = Formatter.instance;
-		if (point)
-			parts.push('point: ' + point);
-		var index = this.getIndex();
-		if (index != null)
-			parts.push('index: ' + index);
-		var time = this.getTime();
-		if (time != null)
-			parts.push('time: ' + f.number(time));
-		if (this._distance != null)
-			parts.push('distance: ' + f.number(this._distance));
-		return '{ ' + parts.join(', ') + ' }';
-	},
-
-	isTouching: function() {
-		var inter = this._intersection;
-		if (inter && this.getTangent().isCollinear(inter.getTangent())) {
-			var curve1 = this.getCurve(),
-				curve2 = inter.getCurve();
-			return !(curve1.isStraight() && curve2.isStraight()
-					&& curve1.getLine().intersect(curve2.getLine()));
-		}
-		return false;
-	},
-
-	isCrossing: function() {
-		var inter = this._intersection;
-		if (!inter)
-			return false;
-		var t1 = this.getTime(),
-			t2 = inter.getTime(),
-			tMin = 4e-7,
-			tMax = 1 - tMin,
-			t1Inside = t1 > tMin && t1 < tMax,
-			t2Inside = t2 > tMin && t2 < tMax;
-		if (t1Inside && t2Inside)
-			return !this.isTouching();
-		var c2 = this.getCurve(),
-			c1 = t1 <= tMin ? c2.getPrevious() : c2,
-			c4 = inter.getCurve(),
-			c3 = t2 <= tMin ? c4.getPrevious() : c4;
-		if (t1 >= tMax)
-			c2 = c2.getNext();
-		if (t2 >= tMax)
-			c4 = c4.getNext();
-		if (!c1 || !c2 || !c3 || !c4)
-			return false;
-
-		function isInRange(angle, min, max) {
-			return min < max
-					? angle > min && angle < max
-					: angle > min || angle < max;
-		}
-
-		var lenghts = [];
-		if (!t1Inside)
-			lenghts.push(c1.getLength(), c2.getLength());
-		if (!t2Inside)
-			lenghts.push(c3.getLength(), c4.getLength());
-		var pt = this.getPoint(),
-			offset = Math.min.apply(Math, lenghts) / 64,
-			v2 = t1Inside ? c2.getTangentAtTime(t1)
-					: c2.getPointAt(offset).subtract(pt),
-			v1 = t1Inside ? v2.negate()
-					: c1.getPointAt(-offset).subtract(pt),
-			v4 = t2Inside ? c4.getTangentAtTime(t2)
-					: c4.getPointAt(offset).subtract(pt),
-			v3 = t2Inside ? v4.negate()
-					: c3.getPointAt(-offset).subtract(pt),
-			a1 = v1.getAngle(),
-			a2 = v2.getAngle(),
-			a3 = v3.getAngle(),
-			a4 = v4.getAngle();
-		return !!(t1Inside
-				? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&
-				  (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))
-				: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&
-				  (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));
-	},
-
-	hasOverlap: function() {
-		return !!this._overlap;
-	}
-}, Base.each(Curve._evaluateMethods, function(name) {
-	var get = name + 'At';
-	this[name] = function() {
-		var curve = this.getCurve(),
-			time = this.getTime();
-		return time != null && curve && curve[get](time, true);
-	};
-}, {
-	preserve: true
-}),
-new function() {
-
-	function insert(locations, loc, merge) {
-		var length = locations.length,
-			l = 0,
-			r = length - 1;
-
-		function search(index, dir) {
-			for (var i = index + dir; i >= -1 && i <= length; i += dir) {
-				var loc2 = locations[((i % length) + length) % length];
-				if (!loc.getPoint().isClose(loc2.getPoint(),
-						2e-7))
-					break;
-				if (loc.equals(loc2))
-					return loc2;
-			}
-			return null;
-		}
-
-		while (l <= r) {
-			var m = (l + r) >>> 1,
-				loc2 = locations[m],
-				found;
-			if (merge && (found = loc.equals(loc2) ? loc2
-					: (search(m, -1) || search(m, 1)))) {
-				if (loc._overlap) {
-					found._overlap = found._intersection._overlap = true;
-				}
-				return found;
-			}
-		var path1 = loc.getPath(),
-			path2 = loc2.getPath(),
-			diff = path1 === path2
-				? (loc.getIndex() + loc.getTime())
-				- (loc2.getIndex() + loc2.getTime())
-				: path1._id - path2._id;
-			if (diff < 0) {
-				r = m - 1;
-			} else {
-				l = m + 1;
-			}
-		}
-		locations.splice(l, 0, loc);
-		return loc;
-	}
-
-	return { statics: {
-		insert: insert,
-
-		expand: function(locations) {
-			var expanded = locations.slice();
-			for (var i = locations.length - 1; i >= 0; i--) {
-				insert(expanded, locations[i]._intersection, false);
-			}
-			return expanded;
-		}
-	}};
-});
-
-var PathItem = Item.extend({
-	_class: 'PathItem',
-	_selectBounds: false,
-	_canScaleStroke: true,
-
-	initialize: function PathItem() {
-	},
-
-	statics: {
-		create: function(pathData) {
-			var ctor = (pathData && pathData.match(/m/gi) || []).length > 1
-					|| /z\s*\S+/i.test(pathData) ? CompoundPath : Path;
-			return new ctor(pathData);
-		}
-	},
-
-	_asPathItem: function() {
-		return this;
-	},
-
-	setPathData: function(data) {
-
-		var parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),
-			coords,
-			relative = false,
-			previous,
-			control,
-			current = new Point(),
-			start = new Point();
-
-		function getCoord(index, coord) {
-			var val = +coords[index];
-			if (relative)
-				val += current[coord];
-			return val;
-		}
-
-		function getPoint(index) {
-			return new Point(
-				getCoord(index, 'x'),
-				getCoord(index + 1, 'y')
-			);
-		}
-
-		this.clear();
-
-		for (var i = 0, l = parts && parts.length; i < l; i++) {
-			var part = parts[i],
-				command = part[0],
-				lower = command.toLowerCase();
-			coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
-			var length = coords && coords.length;
-			relative = command === lower;
-			if (previous === 'z' && !/[mz]/.test(lower))
-				this.moveTo(current = start);
-			switch (lower) {
-			case 'm':
-			case 'l':
-				var move = lower === 'm';
-				for (var j = 0; j < length; j += 2)
-					this[j === 0 && move ? 'moveTo' : 'lineTo'](
-							current = getPoint(j));
-				control = current;
-				if (move)
-					start = current;
-				break;
-			case 'h':
-			case 'v':
-				var coord = lower === 'h' ? 'x' : 'y';
-				for (var j = 0; j < length; j++) {
-					current[coord] = getCoord(j, coord);
-					this.lineTo(current);
-				}
-				control = current;
-				break;
-			case 'c':
-				for (var j = 0; j < length; j += 6) {
-					this.cubicCurveTo(
-							getPoint(j),
-							control = getPoint(j + 2),
-							current = getPoint(j + 4));
-				}
-				break;
-			case 's':
-				for (var j = 0; j < length; j += 4) {
-					this.cubicCurveTo(
-							/[cs]/.test(previous)
-									? current.multiply(2).subtract(control)
-									: current,
-							control = getPoint(j),
-							current = getPoint(j + 2));
-					previous = lower;
-				}
-				break;
-			case 'q':
-				for (var j = 0; j < length; j += 4) {
-					this.quadraticCurveTo(
-							control = getPoint(j),
-							current = getPoint(j + 2));
-				}
-				break;
-			case 't':
-				for (var j = 0; j < length; j += 2) {
-					this.quadraticCurveTo(
-							control = (/[qt]/.test(previous)
-									? current.multiply(2).subtract(control)
-									: current),
-							current = getPoint(j));
-					previous = lower;
-				}
-				break;
-			case 'a':
-				for (var j = 0; j < length; j += 7) {
-					this.arcTo(current = getPoint(j + 5),
-							new Size(+coords[j], +coords[j + 1]),
-							+coords[j + 2], +coords[j + 4], +coords[j + 3]);
-				}
-				break;
-			case 'z':
-				this.closePath(1e-12);
-				break;
-			}
-			previous = lower;
-		}
-	},
-
-	_canComposite: function() {
-		return !(this.hasFill() && this.hasStroke());
-	},
-
-	_contains: function(point) {
-		var winding = point.isInside(
-				this.getBounds({ internal: true, handle: true }))
-					&& this._getWinding(point);
-		return !!(this.getFillRule() === 'evenodd' ? winding & 1 : winding);
-	},
-
-	getIntersections: function(path, include, _matrix, _returnFirst) {
-		var self = this === path || !path,
-			matrix1 = this._matrix._orNullIfIdentity(),
-			matrix2 = self ? matrix1
-				: (_matrix || path._matrix)._orNullIfIdentity();
-		if (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
-			return [];
-		var curves1 = this.getCurves(),
-			curves2 = self ? curves1 : path.getCurves(),
-			length1 = curves1.length,
-			length2 = self ? length1 : curves2.length,
-			values2 = [],
-			arrays = [],
-			locations,
-			path;
-		for (var i = 0; i < length2; i++)
-			values2[i] = curves2[i].getValues(matrix2);
-		for (var i = 0; i < length1; i++) {
-			var curve1 = curves1[i],
-				values1 = self ? values2[i] : curve1.getValues(matrix1),
-				path1 = curve1.getPath();
-			if (path1 !== path) {
-				path = path1;
-				locations = [];
-				arrays.push(locations);
-			}
-			if (self) {
-				Curve._getSelfIntersection(values1, curve1, locations, {
-					include: include,
-					excludeStart: length1 === 1 &&
-							curve1.getPoint1().equals(curve1.getPoint2())
-				});
-			}
-			for (var j = self ? i + 1 : 0; j < length2; j++) {
-				if (_returnFirst && locations.length)
-					return locations;
-				var curve2 = curves2[j];
-				Curve._getIntersections(
-					values1, values2[j], curve1, curve2, locations,
-					{
-						include: include,
-						excludeStart: self && curve1.getPrevious() === curve2,
-						excludeEnd: self && curve1.getNext() === curve2
-					}
-				);
-			}
-		}
-		locations = [];
-		for (var i = 0, l = arrays.length; i < l; i++) {
-			locations.push.apply(locations, arrays[i]);
-		}
-		return locations;
-	},
-
-	getCrossings: function(path) {
-		return this.getIntersections(path, function(inter) {
-			return inter._overlap || inter.isCrossing();
-		});
-	},
-
-	getNearestLocation: function() {
-		var point = Point.read(arguments),
-			curves = this.getCurves(),
-			minDist = Infinity,
-			minLoc = null;
-		for (var i = 0, l = curves.length; i < l; i++) {
-			var loc = curves[i].getNearestLocation(point);
-			if (loc._distance < minDist) {
-				minDist = loc._distance;
-				minLoc = loc;
-			}
-		}
-		return minLoc;
-	},
-
-	getNearestPoint: function() {
-		var loc = this.getNearestLocation.apply(this, arguments);
-		return loc ? loc.getPoint() : loc;
-	},
-
-	interpolate: function(from, to, factor) {
-		var isPath = !this._children,
-			name = isPath ? '_segments' : '_children',
-			itemsFrom = from[name],
-			itemsTo = to[name],
-			items = this[name];
-		if (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {
-			throw new Error('Invalid operands in interpolate() call: ' +
-					from + ', ' + to);
-		}
-		var current = items.length,
-			length = itemsTo.length;
-		if (current < length) {
-			var ctor = isPath ? Segment : Path;
-			for (var i = current; i < length; i++) {
-				this.add(new ctor());
-			}
-		} else if (current > length) {
-			this[isPath ? 'removeSegments' : 'removeChildren'](length, current);
-		}
-		for (var i = 0; i < length; i++) {
-			items[i].interpolate(itemsFrom[i], itemsTo[i], factor);
-		}
-		if (isPath) {
-			this.setClosed(from._closed);
-			this._changed(9);
-		}
-	},
-
-});
-
-var Path = PathItem.extend({
-	_class: 'Path',
-	_serializeFields: {
-		segments: [],
-		closed: false
-	},
-
-	initialize: function Path(arg) {
-		this._closed = false;
-		this._segments = [];
-		this._version = 0;
-		var segments = Array.isArray(arg)
-			? typeof arg[0] === 'object'
-				? arg
-				: arguments
-			: arg && (arg.size === undefined && (arg.x !== undefined
-					|| arg.point !== undefined))
-				? arguments
-				: null;
-		if (segments && segments.length > 0) {
-			this.setSegments(segments);
-		} else {
-			this._curves = undefined;
-			this._segmentSelection = 0;
-			if (!segments && typeof arg === 'string') {
-				this.setPathData(arg);
-				arg = null;
-			}
-		}
-		this._initialize(!segments && arg);
-	},
-
-	_equals: function(item) {
-		return this._closed === item._closed
-				&& Base.equals(this._segments, item._segments);
-	},
-
-	copyContent: function(source) {
-		this.setSegments(source._segments);
-		this._closed = source._closed;
-		var clockwise = source._clockwise;
-		if (clockwise !== undefined)
-			this._clockwise = clockwise;
-	},
-
-	_changed: function _changed(flags) {
-		_changed.base.call(this, flags);
-		if (flags & 8) {
-			this._length = this._area = this._clockwise = this._monoCurves =
-					undefined;
-			if (flags & 16) {
-				this._version++;
-			} else if (this._curves) {
-			   for (var i = 0, l = this._curves.length; i < l; i++)
-					this._curves[i]._changed();
-			}
-		} else if (flags & 32) {
-			this._bounds = undefined;
-		}
-	},
-
-	getStyle: function() {
-		var parent = this._parent;
-		return (parent instanceof CompoundPath ? parent : this)._style;
-	},
-
-	getSegments: function() {
-		return this._segments;
-	},
-
-	setSegments: function(segments) {
-		var fullySelected = this.isFullySelected();
-		this._segments.length = 0;
-		this._segmentSelection = 0;
-		this._curves = undefined;
-		if (segments && segments.length > 0)
-			this._add(Segment.readAll(segments));
-		if (fullySelected)
-			this.setFullySelected(true);
-	},
-
-	getFirstSegment: function() {
-		return this._segments[0];
-	},
-
-	getLastSegment: function() {
-		return this._segments[this._segments.length - 1];
-	},
-
-	getCurves: function() {
-		var curves = this._curves,
-			segments = this._segments;
-		if (!curves) {
-			var length = this._countCurves();
-			curves = this._curves = new Array(length);
-			for (var i = 0; i < length; i++)
-				curves[i] = new Curve(this, segments[i],
-					segments[i + 1] || segments[0]);
-		}
-		return curves;
-	},
-
-	getFirstCurve: function() {
-		return this.getCurves()[0];
-	},
-
-	getLastCurve: function() {
-		var curves = this.getCurves();
-		return curves[curves.length - 1];
-	},
-
-	isClosed: function() {
-		return this._closed;
-	},
-
-	setClosed: function(closed) {
-		if (this._closed != (closed = !!closed)) {
-			this._closed = closed;
-			if (this._curves) {
-				var length = this._curves.length = this._countCurves();
-				if (closed)
-					this._curves[length - 1] = new Curve(this,
-						this._segments[length - 1], this._segments[0]);
-			}
-			this._changed(25);
-		}
-	}
-}, {
-	beans: true,
-
-	getPathData: function(_matrix, _precision) {
-		var segments = this._segments,
-			length = segments.length,
-			f = new Formatter(_precision),
-			coords = new Array(6),
-			first = true,
-			curX, curY,
-			prevX, prevY,
-			inX, inY,
-			outX, outY,
-			parts = [];
-
-		function addSegment(segment, skipLine) {
-			segment._transformCoordinates(_matrix, coords);
-			curX = coords[0];
-			curY = coords[1];
-			if (first) {
-				parts.push('M' + f.pair(curX, curY));
-				first = false;
-			} else {
-				inX = coords[2];
-				inY = coords[3];
-				if (inX === curX && inY === curY
-						&& outX === prevX && outY === prevY) {
-					if (!skipLine)
-						parts.push('l' + f.pair(curX - prevX, curY - prevY));
-				} else {
-					parts.push('c' + f.pair(outX - prevX, outY - prevY)
-							+ ' ' + f.pair(inX - prevX, inY - prevY)
-							+ ' ' + f.pair(curX - prevX, curY - prevY));
-				}
-			}
-			prevX = curX;
-			prevY = curY;
-			outX = coords[4];
-			outY = coords[5];
-		}
-
-		if (length === 0)
-			return '';
-
-		for (var i = 0; i < length; i++)
-			addSegment(segments[i]);
-		if (this._closed && length > 0) {
-			addSegment(segments[0], true);
-			parts.push('z');
-		}
-		return parts.join('');
-	},
-
-	isEmpty: function() {
-		return this._segments.length === 0;
-	},
-
-	_transformContent: function(matrix) {
-		var segments = this._segments,
-			coords = new Array(6);
-		for (var i = 0, l = segments.length; i < l; i++)
-			segments[i]._transformCoordinates(matrix, coords, true);
-		return true;
-	},
-
-	_add: function(segs, index) {
-		var segments = this._segments,
-			curves = this._curves,
-			amount = segs.length,
-			append = index == null,
-			index = append ? segments.length : index;
-		for (var i = 0; i < amount; i++) {
-			var segment = segs[i];
-			if (segment._path)
-				segment = segs[i] = segment.clone();
-			segment._path = this;
-			segment._index = index + i;
-			if (segment._selection)
-				this._updateSelection(segment, 0, segment._selection);
-		}
-		if (append) {
-			segments.push.apply(segments, segs);
-		} else {
-			segments.splice.apply(segments, [index, 0].concat(segs));
-			for (var i = index + amount, l = segments.length; i < l; i++)
-				segments[i]._index = i;
-		}
-		if (curves) {
-			var total = this._countCurves(),
-				start = index > 0 && index + amount - 1 === total ? index - 1
-					: index,
-				insert = start,
-				end = Math.min(start + amount, total);
-			if (segs._curves) {
-				curves.splice.apply(curves, [start, 0].concat(segs._curves));
-				insert += segs._curves.length;
-			}
-			for (var i = insert; i < end; i++)
-				curves.splice(i, 0, new Curve(this, null, null));
-			this._adjustCurves(start, end);
-		}
-		this._changed(25);
-		return segs;
-	},
-
-	_adjustCurves: function(start, end) {
-		var segments = this._segments,
-			curves = this._curves,
-			curve;
-		for (var i = start; i < end; i++) {
-			curve = curves[i];
-			curve._path = this;
-			curve._segment1 = segments[i];
-			curve._segment2 = segments[i + 1] || segments[0];
-			curve._changed();
-		}
-		if (curve = curves[this._closed && start === 0 ? segments.length - 1
-				: start - 1]) {
-			curve._segment2 = segments[start] || segments[0];
-			curve._changed();
-		}
-		if (curve = curves[end]) {
-			curve._segment1 = segments[end];
-			curve._changed();
-		}
-	},
-
-	_countCurves: function() {
-		var length = this._segments.length;
-		return !this._closed && length > 0 ? length - 1 : length;
-	},
-
-	add: function(segment1 ) {
-		return arguments.length > 1 && typeof segment1 !== 'number'
-			? this._add(Segment.readAll(arguments))
-			: this._add([ Segment.read(arguments) ])[0];
-	},
-
-	insert: function(index, segment1 ) {
-		return arguments.length > 2 && typeof segment1 !== 'number'
-			? this._add(Segment.readAll(arguments, 1), index)
-			: this._add([ Segment.read(arguments, 1) ], index)[0];
-	},
-
-	addSegment: function() {
-		return this._add([ Segment.read(arguments) ])[0];
-	},
-
-	insertSegment: function(index ) {
-		return this._add([ Segment.read(arguments, 1) ], index)[0];
-	},
-
-	addSegments: function(segments) {
-		return this._add(Segment.readAll(segments));
-	},
-
-	insertSegments: function(index, segments) {
-		return this._add(Segment.readAll(segments), index);
-	},
-
-	removeSegment: function(index) {
-		return this.removeSegments(index, index + 1)[0] || null;
-	},
-
-	removeSegments: function(start, end, _includeCurves) {
-		start = start || 0;
-		end = Base.pick(end, this._segments.length);
-		var segments = this._segments,
-			curves = this._curves,
-			count = segments.length,
-			removed = segments.splice(start, end - start),
-			amount = removed.length;
-		if (!amount)
-			return removed;
-		for (var i = 0; i < amount; i++) {
-			var segment = removed[i];
-			if (segment._selection)
-				this._updateSelection(segment, segment._selection, 0);
-			segment._index = segment._path = null;
-		}
-		for (var i = start, l = segments.length; i < l; i++)
-			segments[i]._index = i;
-		if (curves) {
-			var index = start > 0 && end === count + (this._closed ? 1 : 0)
-					? start - 1
-					: start,
-				curves = curves.splice(index, amount);
-			for (var i = curves.length - 1; i >= 0; i--)
-				curves[i]._path = null;
-			if (_includeCurves)
-				removed._curves = curves.slice(1);
-			this._adjustCurves(index, index);
-		}
-		this._changed(25);
-		return removed;
-	},
-
-	clear: '#removeSegments',
-
-	hasHandles: function() {
-		var segments = this._segments;
-		for (var i = 0, l = segments.length; i < l; i++) {
-			if (segments[i].hasHandles())
-				return true;
-		}
-		return false;
-	},
-
-	clearHandles: function() {
-		var segments = this._segments;
-		for (var i = 0, l = segments.length; i < l; i++)
-			segments[i].clearHandles();
-	},
-
-	getLength: function() {
-		if (this._length == null) {
-			var curves = this.getCurves(),
-				length = 0;
-			for (var i = 0, l = curves.length; i < l; i++)
-				length += curves[i].getLength();
-			this._length = length;
-		}
-		return this._length;
-	},
-
-	getArea: function(_closed) {
-		var cached = _closed === undefined,
-			area = this._area;
-		if (!cached || area == null) {
-			var segments = this._segments,
-				count = segments.length,
-				closed = cached ? this._closed : _closed,
-				last = count - 1;
-			area = 0;
-			for (var i = 0, l = closed ? count : last; i < l; i++) {
-				area += Curve.getArea(Curve.getValues(
-						segments[i], segments[i < last ? i + 1 : 0]));
-			}
-			if (cached)
-				this._area = area;
-		}
-		return area;
-	},
-
-	isClockwise: function() {
-		if (this._clockwise !== undefined)
-			return this._clockwise;
-		return this.getArea() >= 0;
-	},
-
-	setClockwise: function(clockwise) {
-		if (this.isClockwise() != (clockwise = !!clockwise))
-			this.reverse();
-		this._clockwise = clockwise;
-	},
-
-	isFullySelected: function() {
-		var length = this._segments.length;
-		return this.isSelected() && length > 0 && this._segmentSelection
-				=== length * 7;
-	},
-
-	setFullySelected: function(selected) {
-		if (selected)
-			this._selectSegments(true);
-		this.setSelected(selected);
-	},
-
-	setSelection: function setSelection(selection) {
-		if (!(selection & 1))
-			this._selectSegments(false);
-		setSelection.base.call(this, selection);
-	},
-
-	_selectSegments: function(selected) {
-		var segments = this._segments,
-			length = segments.length,
-			selection = selected ? 7 : 0;
-		this._segmentSelection = selection * length;
-		for (var i = 0; i < length; i++)
-			segments[i]._selection = selection;
-	},
-
-	_updateSelection: function(segment, oldSelection, newSelection) {
-		segment._selection = newSelection;
-		var selection = this._segmentSelection += newSelection - oldSelection;
-		if (selection > 0)
-			this.setSelected(true);
-	},
-
-	splitAt: function(location) {
-		var loc = typeof location === 'number'
-				? this.getLocationAt(location) : location,
-			index = loc && loc.index,
-			time = loc && loc.time,
-			tMin = 4e-7,
-			tMax = 1 - tMin;
-		if (time >= tMax) {
-			index++;
-			time = 0;
-		}
-		var curves = this.getCurves();
-		if (index >= 0 && index < curves.length) {
-			if (time >= tMin) {
-				curves[index++].divideAtTime(time);
-			}
-			var segs = this.removeSegments(index, this._segments.length, true),
-				path;
-			if (this._closed) {
-				this.setClosed(false);
-				path = this;
-			} else {
-				path = new Path(Item.NO_INSERT);
-				path.insertAbove(this, true);
-				path.copyAttributes(this);
-			}
-			path._add(segs, 0);
-			this.addSegment(segs[0]);
-			return path;
-		}
-		return null;
-	},
-
-	split: function(index, time) {
-		var curve,
-			location = time === undefined ? index
-				: (curve = this.getCurves()[index])
-					&& curve.getLocationAtTime(time);
-		return location != null ? this.splitAt(location) : null;
-	},
-
-	join: function(path, tolerance) {
-		var epsilon = tolerance || 0;
-		if (path && path !== this) {
-			var segments = path._segments,
-				last1 = this.getLastSegment(),
-				last2 = path.getLastSegment();
-			if (!last2)
-				return this;
-			if (last1 && last1._point.isClose(last2._point, epsilon))
-				path.reverse();
-			var first2 = path.getFirstSegment();
-			if (last1 && last1._point.isClose(first2._point, epsilon)) {
-				last1.setHandleOut(first2._handleOut);
-				this._add(segments.slice(1));
-			} else {
-				var first1 = this.getFirstSegment();
-				if (first1 && first1._point.isClose(first2._point, epsilon))
-					path.reverse();
-				last2 = path.getLastSegment();
-				if (first1 && first1._point.isClose(last2._point, epsilon)) {
-					first1.setHandleIn(last2._handleIn);
-					this._add(segments.slice(0, segments.length - 1), 0);
-				} else {
-					this._add(segments.slice());
-				}
-			}
-			if (path._closed)
-				this._add([segments[0]]);
-			path.remove();
-		}
-		var first = this.getFirstSegment(),
-			last = this.getLastSegment();
-		if (first !== last && first._point.isClose(last._point, epsilon)) {
-			first.setHandleIn(last._handleIn);
-			last.remove();
-			this.setClosed(true);
-		}
-		return this;
-	},
-
-	reduce: function(options) {
-		var curves = this.getCurves(),
-			simplify = options && options.simplify,
-			tolerance = simplify ? 2e-7 : 0;
-		for (var i = curves.length - 1; i >= 0; i--) {
-			var curve = curves[i];
-			if (!curve.hasHandles() && (curve.getLength() < tolerance
-					|| simplify && curve.isCollinear(curve.getNext())))
-				curve.remove();
-		}
-		return this;
-	},
-
-	reverse: function() {
-		this._segments.reverse();
-		for (var i = 0, l = this._segments.length; i < l; i++) {
-			var segment = this._segments[i];
-			var handleIn = segment._handleIn;
-			segment._handleIn = segment._handleOut;
-			segment._handleOut = handleIn;
-			segment._index = i;
-		}
-		this._curves = null;
-		if (this._clockwise !== undefined)
-			this._clockwise = !this._clockwise;
-		this._changed(9);
-	},
-
-	flatten: function(flatness) {
-		var iterator = new PathIterator(this, flatness || 0.25, 256, true),
-			parts = iterator.parts,
-			length = parts.length,
-			segments = [];
-		for (var i = 0; i < length; i++) {
-			segments.push(new Segment(parts[i].curve.slice(0, 2)));
-		}
-		if (!this._closed && length > 0) {
-			segments.push(new Segment(parts[length - 1].curve.slice(6)));
-		}
-		this.setSegments(segments);
-	},
-
-	simplify: function(tolerance) {
-		var segments = new PathFitter(this).fit(tolerance || 2.5);
-		if (segments)
-			this.setSegments(segments);
-		return !!segments;
-	},
-
-	smooth: function(options) {
-		var that = this,
-			opts = options || {},
-			type = opts.type || 'asymmetric',
-			segments = this._segments,
-			length = segments.length,
-			closed = this._closed;
-
-		function getIndex(value, _default) {
-			var index = value && value.index;
-			if (index != null) {
-				var path = value.path;
-				if (path && path !== that)
-					throw new Error(value._class + ' ' + index + ' of ' + path
-							+ ' is not part of ' + that);
-				if (_default && value instanceof Curve)
-					index++;
-			} else {
-				index = typeof value === 'number' ? value : _default;
-			}
-			return Math.min(index < 0 && closed
-					? index % length
-					: index < 0 ? index + length : index, length - 1);
-		}
-
-		var loop = closed && opts.from === undefined && opts.to === undefined,
-			from = getIndex(opts.from, 0),
-			to = getIndex(opts.to, length - 1);
-
-		if (from > to) {
-			if (closed) {
-				from -= length;
-			} else {
-				var tmp = from;
-				from = to;
-				to = tmp;
-			}
-		}
-		if (/^(?:asymmetric|continuous)$/.test(type)) {
-			var asymmetric = type === 'asymmetric',
-				min = Math.min,
-				amount = to - from + 1,
-				n = amount - 1,
-				padding = loop ? min(amount, 4) : 1,
-				paddingLeft = padding,
-				paddingRight = padding,
-				knots = [];
-			if (!closed) {
-				paddingLeft = min(1, from);
-				paddingRight = min(1, length - to - 1);
-			}
-			n += paddingLeft + paddingRight;
-			if (n <= 1)
-				return;
-			for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
-				knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
-			}
-
-			var x = knots[0]._x + 2 * knots[1]._x,
-				y = knots[0]._y + 2 * knots[1]._y,
-				f = 2,
-				n_1 = n - 1,
-				rx = [x],
-				ry = [y],
-				rf = [f],
-				px = [],
-				py = [];
-			for (var i = 1; i < n; i++) {
-				var internal = i < n_1,
-					a = internal ? 1 : asymmetric ? 1 : 2,
-					b = internal ? 4 : asymmetric ? 2 : 7,
-					u = internal ? 4 : asymmetric ? 3 : 8,
-					v = internal ? 2 : asymmetric ? 0 : 1,
-					m = a / f;
-				f = rf[i] = b - m;
-				x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
-				y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
-			}
-
-			px[n_1] = rx[n_1] / rf[n_1];
-			py[n_1] = ry[n_1] / rf[n_1];
-			for (var i = n - 2; i >= 0; i--) {
-				px[i] = (rx[i] - px[i + 1]) / rf[i];
-				py[i] = (ry[i] - py[i + 1]) / rf[i];
-			}
-			px[n] = (3 * knots[n]._x - px[n_1]) / 2;
-			py[n] = (3 * knots[n]._y - py[n_1]) / 2;
-
-			for (var i = paddingLeft, max = n - paddingRight, j = from;
-					i <= max; i++, j++) {
-				var segment = segments[j < 0 ? j + length : j],
-					pt = segment._point,
-					hx = px[i] - pt._x,
-					hy = py[i] - pt._y;
-				if (loop || i < max)
-					segment.setHandleOut(hx, hy);
-				if (loop || i > paddingLeft)
-					segment.setHandleIn(-hx, -hy);
-			}
-		} else {
-			for (var i = from; i <= to; i++) {
-				segments[i < 0 ? i + length : i].smooth(opts,
-						!loop && i === from, !loop && i === to);
-			}
-		}
-	},
-
-	toShape: function(insert) {
-		if (!this._closed)
-			return null;
-
-		var segments = this._segments,
-			type,
-			size,
-			radius,
-			topCenter;
-
-		function isCollinear(i, j) {
-			var seg1 = segments[i],
-				seg2 = seg1.getNext(),
-				seg3 = segments[j],
-				seg4 = seg3.getNext();
-			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
-					&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
-					&& seg2._point.subtract(seg1._point).isCollinear(
-						seg4._point.subtract(seg3._point));
-		}
-
-		function isOrthogonal(i) {
-			var seg2 = segments[i],
-				seg1 = seg2.getPrevious(),
-				seg3 = seg2.getNext();
-			return seg1._handleOut.isZero() && seg2._handleIn.isZero()
-					&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
-					&& seg2._point.subtract(seg1._point).isOrthogonal(
-						seg3._point.subtract(seg2._point));
-		}
-
-		function isArc(i) {
-			var seg1 = segments[i],
-				seg2 = seg1.getNext(),
-				handle1 = seg1._handleOut,
-				handle2 = seg2._handleIn,
-				kappa = 0.5522847498307936;
-			if (handle1.isOrthogonal(handle2)) {
-				var pt1 = seg1._point,
-					pt2 = seg2._point,
-					corner = new Line(pt1, handle1, true).intersect(
-							new Line(pt2, handle2, true), true);
-				return corner && Numerical.isZero(handle1.getLength() /
-						corner.subtract(pt1).getLength() - kappa)
-					&& Numerical.isZero(handle2.getLength() /
-						corner.subtract(pt2).getLength() - kappa);
-			}
-			return false;
-		}
-
-		function getDistance(i, j) {
-			return segments[i]._point.getDistance(segments[j]._point);
-		}
-
-		if (!this.hasHandles() && segments.length === 4
-				&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {
-			type = Shape.Rectangle;
-			size = new Size(getDistance(0, 3), getDistance(0, 1));
-			topCenter = segments[1]._point.add(segments[2]._point).divide(2);
-		} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
-				&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {
-			type = Shape.Rectangle;
-			size = new Size(getDistance(1, 6), getDistance(0, 3));
-			radius = size.subtract(new Size(getDistance(0, 7),
-					getDistance(1, 2))).divide(2);
-			topCenter = segments[3]._point.add(segments[4]._point).divide(2);
-		} else if (segments.length === 4
-				&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
-			if (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {
-				type = Shape.Circle;
-				radius = getDistance(0, 2) / 2;
-			} else {
-				type = Shape.Ellipse;
-				radius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);
-			}
-			topCenter = segments[1]._point;
-		}
-
-		if (type) {
-			var center = this.getPosition(true),
-				shape = new type({
-					center: center,
-					size: size,
-					radius: radius,
-					insert: false
-				});
-			shape.copyAttributes(this, true);
-			shape._matrix.prepend(this._matrix);
-			shape.rotate(topCenter.subtract(center).getAngle() + 90);
-			if (insert === undefined || insert)
-				shape.insertAbove(this);
-			return shape;
-		}
-		return null;
-	},
-
-	toPath: '#clone',
-
-	_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
-		var that = this,
-			style = this.getStyle(),
-			segments = this._segments,
-			numSegments = segments.length,
-			closed = this._closed,
-			tolerancePadding = options._tolerancePadding,
-			strokePadding = tolerancePadding,
-			join, cap, miterLimit,
-			area, loc, res,
-			hitStroke = options.stroke && style.hasStroke(),
-			hitFill = options.fill && style.hasFill(),
-			hitCurves = options.curves,
-			strokeRadius = hitStroke
-					? style.getStrokeWidth() / 2
-					: hitFill && options.tolerance > 0 || hitCurves
-						? 0 : null;
-		if (strokeRadius !== null) {
-			if (strokeRadius > 0) {
-				join = style.getStrokeJoin();
-				cap = style.getStrokeCap();
-				miterLimit = strokeRadius * style.getMiterLimit();
-				strokePadding = strokePadding.add(
-					Path._getStrokePadding(strokeRadius, strokeMatrix));
-			} else {
-				join = cap = 'round';
-			}
-		}
-
-		function isCloseEnough(pt, padding) {
-			return point.subtract(pt).divide(padding).length <= 1;
-		}
-
-		function checkSegmentPoint(seg, pt, name) {
-			if (!options.selected || pt.isSelected()) {
-				var anchor = seg._point;
-				if (pt !== anchor)
-					pt = pt.add(anchor);
-				if (isCloseEnough(pt, strokePadding)) {
-					return new HitResult(name, that, {
-						segment: seg,
-						point: pt
-					});
-				}
-			}
-		}
-
-		function checkSegmentPoints(seg, ends) {
-			return (ends || options.segments)
-				&& checkSegmentPoint(seg, seg._point, 'segment')
-				|| (!ends && options.handles) && (
-					checkSegmentPoint(seg, seg._handleIn, 'handle-in') ||
-					checkSegmentPoint(seg, seg._handleOut, 'handle-out'));
-		}
-
-		function addToArea(point) {
-			area.add(point);
-		}
-
-		function checkSegmentStroke(segment) {
-			if (join !== 'round' || cap !== 'round') {
-				area = new Path({ internal: true, closed: true });
-				if (closed || segment._index > 0
-						&& segment._index < numSegments - 1) {
-					if (join !== 'round' && (segment._handleIn.isZero()
-							|| segment._handleOut.isZero()))
-						Path._addBevelJoin(segment, join, strokeRadius,
-							   miterLimit, null, strokeMatrix, addToArea, true);
-				} else if (cap !== 'round') {
-					Path._addSquareCap(segment, cap, strokeRadius, null,
-							strokeMatrix, addToArea, true);
-				}
-				if (!area.isEmpty()) {
-					var loc;
-					return area.contains(point)
-						|| (loc = area.getNearestLocation(point))
-							&& isCloseEnough(loc.getPoint(), tolerancePadding);
-				}
-			}
-			return isCloseEnough(segment._point, strokePadding);
-		}
-
-		if (options.ends && !options.segments && !closed) {
-			if (res = checkSegmentPoints(segments[0], true)
-					|| checkSegmentPoints(segments[numSegments - 1], true))
-				return res;
-		} else if (options.segments || options.handles) {
-			for (var i = 0; i < numSegments; i++)
-				if (res = checkSegmentPoints(segments[i]))
-					return res;
-		}
-		if (strokeRadius !== null) {
-			loc = this.getNearestLocation(point);
-			if (loc) {
-				var time = loc.getTime();
-				if (time === 0 || time === 1 && numSegments > 1) {
-					if (!checkSegmentStroke(loc.getSegment()))
-						loc = null;
-				} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
-					loc = null;
-				}
-			}
-			if (!loc && join === 'miter' && numSegments > 1) {
-				for (var i = 0; i < numSegments; i++) {
-					var segment = segments[i];
-					if (point.getDistance(segment._point) <= miterLimit
-							&& checkSegmentStroke(segment)) {
-						loc = segment.getLocation();
-						break;
-					}
-				}
-			}
-		}
-		return !loc && hitFill && this._contains(point)
-				|| loc && !hitStroke && !hitCurves
-					? new HitResult('fill', this)
-					: loc
-						? new HitResult(hitStroke ? 'stroke' : 'curve', this, {
-							location: loc,
-							point: loc.getPoint()
-						})
-						: null;
-	}
-
-}, Base.each(Curve._evaluateMethods,
-	function(name) {
-		this[name + 'At'] = function(offset) {
-			var loc = this.getLocationAt(offset);
-			return loc && loc[name]();
-		};
-	},
-{
-	beans: false,
-
-	getLocationOf: function() {
-		var point = Point.read(arguments),
-			curves = this.getCurves();
-		for (var i = 0, l = curves.length; i < l; i++) {
-			var loc = curves[i].getLocationOf(point);
-			if (loc)
-				return loc;
-		}
-		return null;
-	},
-
-	getOffsetOf: function() {
-		var loc = this.getLocationOf.apply(this, arguments);
-		return loc ? loc.getOffset() : null;
-	},
-
-	getLocationAt: function(offset) {
-		var curves = this.getCurves(),
-			length = 0;
-		for (var i = 0, l = curves.length; i < l; i++) {
-			var start = length,
-				curve = curves[i];
-			length += curve.getLength();
-			if (length > offset) {
-				return curve.getLocationAt(offset - start);
-			}
-		}
-		if (curves.length > 0 && offset <= this.getLength())
-			return new CurveLocation(curves[curves.length - 1], 1);
-		return null;
-	}
-
-}),
-new function() {
-
-	function drawHandles(ctx, segments, matrix, size) {
-		var half = size / 2,
-			coords = new Array(6),
-			pX, pY;
-
-		function drawHandle(index) {
-			var hX = coords[index],
-				hY = coords[index + 1];
-			if (pX != hX || pY != hY) {
-				ctx.beginPath();
-				ctx.moveTo(pX, pY);
-				ctx.lineTo(hX, hY);
-				ctx.stroke();
-				ctx.beginPath();
-				ctx.arc(hX, hY, half, 0, Math.PI * 2, true);
-				ctx.fill();
-			}
-		}
-
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var segment = segments[i],
-				selection = segment._selection;
-			segment._transformCoordinates(matrix, coords);
-			pX = coords[0];
-			pY = coords[1];
-			if (selection & 2)
-				drawHandle(2);
-			if (selection & 4)
-				drawHandle(4);
-			ctx.fillRect(pX - half, pY - half, size, size);
-			if (!(selection & 1)) {
-				var fillStyle = ctx.fillStyle;
-				ctx.fillStyle = '#ffffff';
-				ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);
-				ctx.fillStyle = fillStyle;
-			}
-		}
-	}
-
-	function drawSegments(ctx, path, matrix) {
-		var segments = path._segments,
-			length = segments.length,
-			coords = new Array(6),
-			first = true,
-			curX, curY,
-			prevX, prevY,
-			inX, inY,
-			outX, outY;
-
-		function drawSegment(segment) {
-			if (matrix) {
-				segment._transformCoordinates(matrix, coords);
-				curX = coords[0];
-				curY = coords[1];
-			} else {
-				var point = segment._point;
-				curX = point._x;
-				curY = point._y;
-			}
-			if (first) {
-				ctx.moveTo(curX, curY);
-				first = false;
-			} else {
-				if (matrix) {
-					inX = coords[2];
-					inY = coords[3];
-				} else {
-					var handle = segment._handleIn;
-					inX = curX + handle._x;
-					inY = curY + handle._y;
-				}
-				if (inX === curX && inY === curY
-						&& outX === prevX && outY === prevY) {
-					ctx.lineTo(curX, curY);
-				} else {
-					ctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);
-				}
-			}
-			prevX = curX;
-			prevY = curY;
-			if (matrix) {
-				outX = coords[4];
-				outY = coords[5];
-			} else {
-				var handle = segment._handleOut;
-				outX = prevX + handle._x;
-				outY = prevY + handle._y;
-			}
-		}
-
-		for (var i = 0; i < length; i++)
-			drawSegment(segments[i]);
-		if (path._closed && length > 0)
-			drawSegment(segments[0]);
-	}
-
-	return {
-		_draw: function(ctx, param, viewMatrix, strokeMatrix) {
-			var dontStart = param.dontStart,
-				dontPaint = param.dontFinish || param.clip,
-				style = this.getStyle(),
-				hasFill = style.hasFill(),
-				hasStroke = style.hasStroke(),
-				dashArray = style.getDashArray(),
-				dashLength = !paper.support.nativeDash && hasStroke
-						&& dashArray && dashArray.length;
-
-			if (!dontStart)
-				ctx.beginPath();
-
-			if (hasFill || hasStroke && !dashLength || dontPaint) {
-				drawSegments(ctx, this, strokeMatrix);
-				if (this._closed)
-					ctx.closePath();
-			}
-
-			function getOffset(i) {
-				return dashArray[((i % dashLength) + dashLength) % dashLength];
-			}
-
-			if (!dontPaint && (hasFill || hasStroke)) {
-				this._setStyles(ctx, param, viewMatrix);
-				if (hasFill) {
-					ctx.fill(style.getFillRule());
-					ctx.shadowColor = 'rgba(0,0,0,0)';
-				}
-				if (hasStroke) {
-					if (dashLength) {
-						if (!dontStart)
-							ctx.beginPath();
-						var iterator = new PathIterator(this, 0.25, 32, false,
-								strokeMatrix),
-							length = iterator.length,
-							from = -style.getDashOffset(), to,
-							i = 0;
-						from = from % length;
-						while (from > 0) {
-							from -= getOffset(i--) + getOffset(i--);
-						}
-						while (from < length) {
-							to = from + getOffset(i++);
-							if (from > 0 || to > 0)
-								iterator.drawPart(ctx,
-										Math.max(from, 0), Math.max(to, 0));
-							from = to + getOffset(i++);
-						}
-					}
-					ctx.stroke();
-				}
-			}
-		},
-
-		_drawSelected: function(ctx, matrix) {
-			ctx.beginPath();
-			drawSegments(ctx, this, matrix);
-			ctx.stroke();
-			drawHandles(ctx, this._segments, matrix, paper.settings.handleSize);
-		}
-	};
-},
-new function() {
-	function getCurrentSegment(that) {
-		var segments = that._segments;
-		if (segments.length === 0)
-			throw new Error('Use a moveTo() command first');
-		return segments[segments.length - 1];
-	}
-
-	return {
-		moveTo: function() {
-			var segments = this._segments;
-			if (segments.length === 1)
-				this.removeSegment(0);
-			if (!segments.length)
-				this._add([ new Segment(Point.read(arguments)) ]);
-		},
-
-		moveBy: function() {
-			throw new Error('moveBy() is unsupported on Path items.');
-		},
-
-		lineTo: function() {
-			this._add([ new Segment(Point.read(arguments)) ]);
-		},
-
-		cubicCurveTo: function() {
-			var handle1 = Point.read(arguments),
-				handle2 = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this);
-			current.setHandleOut(handle1.subtract(current._point));
-			this._add([ new Segment(to, handle2.subtract(to)) ]);
-		},
-
-		quadraticCurveTo: function() {
-			var handle = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.cubicCurveTo(
-				handle.add(current.subtract(handle).multiply(1 / 3)),
-				handle.add(to.subtract(handle).multiply(1 / 3)),
-				to
-			);
-		},
-
-		curveTo: function() {
-			var through = Point.read(arguments),
-				to = Point.read(arguments),
-				t = Base.pick(Base.read(arguments), 0.5),
-				t1 = 1 - t,
-				current = getCurrentSegment(this)._point,
-				handle = through.subtract(current.multiply(t1 * t1))
-					.subtract(to.multiply(t * t)).divide(2 * t * t1);
-			if (handle.isNaN())
-				throw new Error(
-					'Cannot put a curve through points with parameter = ' + t);
-			this.quadraticCurveTo(handle, to);
-		},
-
-		arcTo: function() {
-			var current = getCurrentSegment(this),
-				from = current._point,
-				to = Point.read(arguments),
-				through,
-				peek = Base.peek(arguments),
-				clockwise = Base.pick(peek, true),
-				center, extent, vector, matrix;
-			if (typeof clockwise === 'boolean') {
-				var middle = from.add(to).divide(2),
-				through = middle.add(middle.subtract(from).rotate(
-						clockwise ? -90 : 90));
-			} else if (Base.remain(arguments) <= 2) {
-				through = to;
-				to = Point.read(arguments);
-			} else {
-				var radius = Size.read(arguments),
-					isZero = Numerical.isZero;
-				if (isZero(radius.width) || isZero(radius.height))
-					return this.lineTo(to);
-				var rotation = Base.read(arguments),
-					clockwise = !!Base.read(arguments),
-					large = !!Base.read(arguments),
-					middle = from.add(to).divide(2),
-					pt = from.subtract(middle).rotate(-rotation),
-					x = pt.x,
-					y = pt.y,
-					abs = Math.abs,
-					rx = abs(radius.width),
-					ry = abs(radius.height),
-					rxSq = rx * rx,
-					rySq = ry * ry,
-					xSq = x * x,
-					ySq = y * y;
-				var factor = Math.sqrt(xSq / rxSq + ySq / rySq);
-				if (factor > 1) {
-					rx *= factor;
-					ry *= factor;
-					rxSq = rx * rx;
-					rySq = ry * ry;
-				}
-				factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
-						(rxSq * ySq + rySq * xSq);
-				if (abs(factor) < 1e-12)
-					factor = 0;
-				if (factor < 0)
-					throw new Error(
-							'Cannot create an arc with the given arguments');
-				center = new Point(rx * y / ry, -ry * x / rx)
-						.multiply((large === clockwise ? -1 : 1)
-							* Math.sqrt(factor))
-						.rotate(rotation).add(middle);
-				matrix = new Matrix().translate(center).rotate(rotation)
-						.scale(rx, ry);
-				vector = matrix._inverseTransform(from);
-				extent = vector.getDirectedAngle(matrix._inverseTransform(to));
-				if (!clockwise && extent > 0)
-					extent -= 360;
-				else if (clockwise && extent < 0)
-					extent += 360;
-			}
-			if (through) {
-				var l1 = new Line(from.add(through).divide(2),
-							through.subtract(from).rotate(90), true),
-					l2 = new Line(through.add(to).divide(2),
-							to.subtract(through).rotate(90), true),
-					line = new Line(from, to),
-					throughSide = line.getSide(through);
-				center = l1.intersect(l2, true);
-				if (!center) {
-					if (!throughSide)
-						return this.lineTo(to);
-					throw new Error(
-							'Cannot create an arc with the given arguments');
-				}
-				vector = from.subtract(center);
-				extent = vector.getDirectedAngle(to.subtract(center));
-				var centerSide = line.getSide(center);
-				if (centerSide === 0) {
-					extent = throughSide * Math.abs(extent);
-				} else if (throughSide === centerSide) {
-					extent += extent < 0 ? 360 : -360;
-				}
-			}
-			var ext = Math.abs(extent),
-				count = ext >= 360 ? 4 : Math.ceil(ext / 90),
-				inc = extent / count,
-				half = inc * Math.PI / 360,
-				z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),
-				segments = [];
-			for (var i = 0; i <= count; i++) {
-				var pt = to,
-					out = null;
-				if (i < count) {
-					out = vector.rotate(90).multiply(z);
-					if (matrix) {
-						pt = matrix._transformPoint(vector);
-						out = matrix._transformPoint(vector.add(out))
-								.subtract(pt);
-					} else {
-						pt = center.add(vector);
-					}
-				}
-				if (i === 0) {
-					current.setHandleOut(out);
-				} else {
-					var _in = vector.rotate(-90).multiply(z);
-					if (matrix) {
-						_in = matrix._transformPoint(vector.add(_in))
-								.subtract(pt);
-					}
-					segments.push(new Segment(pt, _in, out));
-				}
-				vector = vector.rotate(inc);
-			}
-			this._add(segments);
-		},
-
-		lineBy: function() {
-			var to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.lineTo(current.add(to));
-		},
-
-		curveBy: function() {
-			var through = Point.read(arguments),
-				to = Point.read(arguments),
-				parameter = Base.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.curveTo(current.add(through), current.add(to), parameter);
-		},
-
-		cubicCurveBy: function() {
-			var handle1 = Point.read(arguments),
-				handle2 = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.cubicCurveTo(current.add(handle1), current.add(handle2),
-					current.add(to));
-		},
-
-		quadraticCurveBy: function() {
-			var handle = Point.read(arguments),
-				to = Point.read(arguments),
-				current = getCurrentSegment(this)._point;
-			this.quadraticCurveTo(current.add(handle), current.add(to));
-		},
-
-		arcBy: function() {
-			var current = getCurrentSegment(this)._point,
-				point = current.add(Point.read(arguments)),
-				clockwise = Base.pick(Base.peek(arguments), true);
-			if (typeof clockwise === 'boolean') {
-				this.arcTo(point, clockwise);
-			} else {
-				this.arcTo(point, current.add(Point.read(arguments)));
-			}
-		},
-
-		closePath: function(tolerance) {
-			this.setClosed(true);
-			this.join(this, tolerance);
-		}
-	};
-}, {
-
-	_getBounds: function(matrix, options) {
-		var method = options.handle
-				? 'getHandleBounds'
-				: options.stroke
-				? 'getStrokeBounds'
-				: 'getBounds';
-		return Path[method](this._segments, this._closed, this, matrix, options);
-	},
-
-statics: {
-	getBounds: function(segments, closed, path, matrix, options, strokePadding) {
-		var first = segments[0];
-		if (!first)
-			return new Rectangle();
-		var coords = new Array(6),
-			prevCoords = first._transformCoordinates(matrix, new Array(6)),
-			min = prevCoords.slice(0, 2),
-			max = min.slice(),
-			roots = new Array(2);
-
-		function processSegment(segment) {
-			segment._transformCoordinates(matrix, coords);
-			for (var i = 0; i < 2; i++) {
-				Curve._addBounds(
-					prevCoords[i],
-					prevCoords[i + 4],
-					coords[i + 2],
-					coords[i],
-					i, strokePadding ? strokePadding[i] : 0, min, max, roots);
-			}
-			var tmp = prevCoords;
-			prevCoords = coords;
-			coords = tmp;
-		}
-
-		for (var i = 1, l = segments.length; i < l; i++)
-			processSegment(segments[i]);
-		if (closed)
-			processSegment(first);
-		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
-	},
-
-	getStrokeBounds: function(segments, closed, path, matrix, options) {
-		var style = path.getStyle(),
-			stroke = style.hasStroke(),
-			strokeWidth = style.getStrokeWidth(),
-			strokeMatrix = stroke && path._getStrokeMatrix(matrix, options),
-			strokePadding = stroke && Path._getStrokePadding(strokeWidth,
-				strokeMatrix),
-			bounds = Path.getBounds(segments, closed, path, matrix, options,
-				strokePadding);
-		if (!stroke)
-			return bounds;
-		var strokeRadius = strokeWidth / 2,
-			join = style.getStrokeJoin(),
-			cap = style.getStrokeCap(),
-			miterLimit = strokeRadius * style.getMiterLimit(),
-			joinBounds = new Rectangle(new Size(strokePadding));
-
-		function addPoint(point) {
-			bounds = bounds.include(point);
-		}
-
-		function addRound(segment) {
-			bounds = bounds.unite(
-					joinBounds.setCenter(segment._point.transform(matrix)));
-		}
-
-		function addJoin(segment, join) {
-			var handleIn = segment._handleIn,
-				handleOut = segment._handleOut;
-			if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
-					&& handleIn.isCollinear(handleOut)) {
-				addRound(segment);
-			} else {
-				Path._addBevelJoin(segment, join, strokeRadius, miterLimit,
-						matrix, strokeMatrix, addPoint);
-			}
-		}
-
-		function addCap(segment, cap) {
-			if (cap === 'round') {
-				addRound(segment);
-			} else {
-				Path._addSquareCap(segment, cap, strokeRadius, matrix,
-						strokeMatrix, addPoint);
-			}
-		}
-
-		var length = segments.length - (closed ? 0 : 1);
-		for (var i = 1; i < length; i++)
-			addJoin(segments[i], join);
-		if (closed) {
-			addJoin(segments[0], join);
-		} else if (length > 0) {
-			addCap(segments[0], cap);
-			addCap(segments[segments.length - 1], cap);
-		}
-		return bounds;
-	},
-
-	_getStrokePadding: function(radius, matrix) {
-		if (!matrix)
-			return [radius, radius];
-		var hor = new Point(radius, 0).transform(matrix),
-			ver = new Point(0, radius).transform(matrix),
-			phi = hor.getAngleInRadians(),
-			a = hor.getLength(),
-			b = ver.getLength();
-		var sin = Math.sin(phi),
-			cos = Math.cos(phi),
-			tan = Math.tan(phi),
-			tx = Math.atan2(b * tan, a),
-			ty = Math.atan2(b, tan * a);
-		return [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),
-				Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];
-	},
-
-	_addBevelJoin: function(segment, join, radius, miterLimit, matrix,
-			strokeMatrix, addPoint, isArea) {
-		var curve2 = segment.getCurve(),
-			curve1 = curve2.getPrevious(),
-			point = curve2.getPointAtTime(0),
-			normal1 = curve1.getNormalAtTime(1),
-			normal2 = curve2.getNormalAtTime(0),
-			step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
-		normal1.setLength(step);
-		normal2.setLength(step);
-		if (matrix)
-			matrix._transformPoint(point, point);
-		if (strokeMatrix) {
-			strokeMatrix._transformPoint(normal1, normal1);
-			strokeMatrix._transformPoint(normal2, normal2);
-		}
-		if (isArea) {
-			addPoint(point);
-			addPoint(point.add(normal1));
-		}
-		if (join === 'miter') {
-			var corner = new Line(point.add(normal1),
-					new Point(-normal1.y, normal1.x), true
-				).intersect(new Line(point.add(normal2),
-					new Point(-normal2.y, normal2.x), true
-				), true);
-			if (corner && point.getDistance(corner) <= miterLimit) {
-				addPoint(corner);
-				if (!isArea)
-					return;
-			}
-		}
-		if (!isArea)
-			addPoint(point.add(normal1));
-		addPoint(point.add(normal2));
-	},
-
-	_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,
-			addPoint, isArea) {
-		var point = segment._point,
-			loc = segment.getLocation(),
-			normal = loc.getNormal().multiply(radius);
-		if (matrix)
-			matrix._transformPoint(point, point);
-		if (strokeMatrix)
-			strokeMatrix._transformPoint(normal, normal);
-		if (isArea) {
-			addPoint(point.subtract(normal));
-			addPoint(point.add(normal));
-		}
-		if (cap === 'square') {
-			point = point.add(normal.rotate(
-					loc.getTime() === 0 ? -90 : 90));
-		}
-		addPoint(point.add(normal));
-		addPoint(point.subtract(normal));
-	},
-
-	getHandleBounds: function(segments, closed, path, matrix, options) {
-		var style = path.getStyle(),
-			stroke = options.stroke && style.hasStroke(),
-			strokePadding,
-			joinPadding;
-		if (stroke) {
-			var strokeMatrix = path._getStrokeMatrix(matrix, options),
-				strokeRadius = style.getStrokeWidth() / 2,
-				joinRadius = strokeRadius;
-			if (style.getStrokeJoin() === 'miter')
-				joinRadius = strokeRadius * style.getMiterLimit();
-			if (style.getStrokeCap() === 'square')
-				joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
-			strokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);
-			joinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);
-		}
-		var coords = new Array(6),
-			x1 = Infinity,
-			x2 = -x1,
-			y1 = x1,
-			y2 = x2;
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var segment = segments[i];
-			segment._transformCoordinates(matrix, coords);
-			for (var j = 0; j < 6; j += 2) {
-				var padding = j === 0 ? joinPadding : strokePadding,
-					paddingX = padding ? padding[0] : 0,
-					paddingY = padding ? padding[1] : 0,
-					x = coords[j],
-					y = coords[j + 1],
-					xn = x - paddingX,
-					xx = x + paddingX,
-					yn = y - paddingY,
-					yx = y + paddingY;
-				if (xn < x1) x1 = xn;
-				if (xx > x2) x2 = xx;
-				if (yn < y1) y1 = yn;
-				if (yx > y2) y2 = yx;
-			}
-		}
-		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
-	}
-}});
-
-Path.inject({ statics: new function() {
-
-	var kappa = 0.5522847498307936,
-		ellipseSegments = [
-			new Segment([-1, 0], [0, kappa ], [0, -kappa]),
-			new Segment([0, -1], [-kappa, 0], [kappa, 0 ]),
-			new Segment([1, 0], [0, -kappa], [0, kappa ]),
-			new Segment([0, 1], [kappa, 0 ], [-kappa, 0])
-		];
-
-	function createPath(segments, closed, args) {
-		var props = Base.getNamed(args),
-			path = new Path(props && props.insert === false && Item.NO_INSERT);
-		path._add(segments);
-		path._closed = closed;
-		return path.set(props);
-	}
-
-	function createEllipse(center, radius, args) {
-		var segments = new Array(4);
-		for (var i = 0; i < 4; i++) {
-			var segment = ellipseSegments[i];
-			segments[i] = new Segment(
-				segment._point.multiply(radius).add(center),
-				segment._handleIn.multiply(radius),
-				segment._handleOut.multiply(radius)
-			);
-		}
-		return createPath(segments, true, args);
-	}
-
-	return {
-		Line: function() {
-			return createPath([
-				new Segment(Point.readNamed(arguments, 'from')),
-				new Segment(Point.readNamed(arguments, 'to'))
-			], false, arguments);
-		},
-
-		Circle: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				radius = Base.readNamed(arguments, 'radius');
-			return createEllipse(center, new Size(radius), arguments);
-		},
-
-		Rectangle: function() {
-			var rect = Rectangle.readNamed(arguments, 'rectangle'),
-				radius = Size.readNamed(arguments, 'radius', 0,
-						{ readNull: true }),
-				bl = rect.getBottomLeft(true),
-				tl = rect.getTopLeft(true),
-				tr = rect.getTopRight(true),
-				br = rect.getBottomRight(true),
-				segments;
-			if (!radius || radius.isZero()) {
-				segments = [
-					new Segment(bl),
-					new Segment(tl),
-					new Segment(tr),
-					new Segment(br)
-				];
-			} else {
-				radius = Size.min(radius, rect.getSize(true).divide(2));
-				var rx = radius.width,
-					ry = radius.height,
-					hx = rx * kappa,
-					hy = ry * kappa;
-				segments = [
-					new Segment(bl.add(rx, 0), null, [-hx, 0]),
-					new Segment(bl.subtract(0, ry), [0, hy]),
-					new Segment(tl.add(0, ry), null, [0, -hy]),
-					new Segment(tl.add(rx, 0), [-hx, 0], null),
-					new Segment(tr.subtract(rx, 0), null, [hx, 0]),
-					new Segment(tr.add(0, ry), [0, -hy], null),
-					new Segment(br.subtract(0, ry), null, [0, hy]),
-					new Segment(br.subtract(rx, 0), [hx, 0])
-				];
-			}
-			return createPath(segments, true, arguments);
-		},
-
-		RoundRectangle: '#Rectangle',
-
-		Ellipse: function() {
-			var ellipse = Shape._readEllipse(arguments);
-			return createEllipse(ellipse.center, ellipse.radius, arguments);
-		},
-
-		Oval: '#Ellipse',
-
-		Arc: function() {
-			var from = Point.readNamed(arguments, 'from'),
-				through = Point.readNamed(arguments, 'through'),
-				to = Point.readNamed(arguments, 'to'),
-				props = Base.getNamed(arguments),
-				path = new Path(props && props.insert === false
-						&& Item.NO_INSERT);
-			path.moveTo(from);
-			path.arcTo(through, to);
-			return path.set(props);
-		},
-
-		RegularPolygon: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				sides = Base.readNamed(arguments, 'sides'),
-				radius = Base.readNamed(arguments, 'radius'),
-				step = 360 / sides,
-				three = sides % 3 === 0,
-				vector = new Point(0, three ? -radius : radius),
-				offset = three ? -1 : 0.5,
-				segments = new Array(sides);
-			for (var i = 0; i < sides; i++)
-				segments[i] = new Segment(center.add(
-					vector.rotate((i + offset) * step)));
-			return createPath(segments, true, arguments);
-		},
-
-		Star: function() {
-			var center = Point.readNamed(arguments, 'center'),
-				points = Base.readNamed(arguments, 'points') * 2,
-				radius1 = Base.readNamed(arguments, 'radius1'),
-				radius2 = Base.readNamed(arguments, 'radius2'),
-				step = 360 / points,
-				vector = new Point(0, -1),
-				segments = new Array(points);
-			for (var i = 0; i < points; i++)
-				segments[i] = new Segment(center.add(vector.rotate(step * i)
-						.multiply(i % 2 ? radius2 : radius1)));
-			return createPath(segments, true, arguments);
-		}
-	};
-}});
-
-var CompoundPath = PathItem.extend({
-	_class: 'CompoundPath',
-	_serializeFields: {
-		children: []
-	},
-
-	initialize: function CompoundPath(arg) {
-		this._children = [];
-		this._namedChildren = {};
-		if (!this._initialize(arg)) {
-			if (typeof arg === 'string') {
-				this.setPathData(arg);
-			} else {
-				this.addChildren(Array.isArray(arg) ? arg : arguments);
-			}
-		}
-	},
-
-	insertChildren: function insertChildren(index, items, _preserve) {
-		for (var i = items.length - 1; i >= 0; i--) {
-			var item = items[i];
-			if (item instanceof CompoundPath) {
-				items = items.slice();
-				items.splice.apply(items, [i, 1].concat(item.removeChildren()));
-				item.remove();
-			}
-		}
-		items = insertChildren.base.call(this, index, items, _preserve, Path);
-		for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
-			var item = items[i];
-			if (item._clockwise === undefined)
-				item.setClockwise(item._index === 0);
-		}
-		return items;
-	},
-
-	reduce: function reduce(options) {
-		var children = this._children;
-		for (var i = children.length - 1; i >= 0; i--) {
-			var path = children[i].reduce(options);
-			if (path.isEmpty())
-				path.remove();
-		}
-		if (children.length === 0) {
-			var path = new Path(Item.NO_INSERT);
-			path.copyAttributes(this);
-			path.insertAbove(this);
-			this.remove();
-			return path;
-		}
-		return reduce.base.call(this);
-	},
-
-	isClockwise: function() {
-		var child = this.getFirstChild();
-		return child && child.isClockwise();
-	},
-
-	setClockwise: function(clockwise) {
-		if (this.isClockwise() ^ !!clockwise)
-			this.reverse();
-	},
-
-	getFirstSegment: function() {
-		var first = this.getFirstChild();
-		return first && first.getFirstSegment();
-	},
-
-	getLastSegment: function() {
-		var last = this.getLastChild();
-		return last && last.getLastSegment();
-	},
-
-	getCurves: function() {
-		var children = this._children,
-			curves = [];
-		for (var i = 0, l = children.length; i < l; i++)
-			curves.push.apply(curves, children[i].getCurves());
-		return curves;
-	},
-
-	getFirstCurve: function() {
-		var first = this.getFirstChild();
-		return first && first.getFirstCurve();
-	},
-
-	getLastCurve: function() {
-		var last = this.getLastChild();
-		return last && last.getFirstCurve();
-	},
-
-	getArea: function() {
-		var children = this._children,
-			area = 0;
-		for (var i = 0, l = children.length; i < l; i++)
-			area += children[i].getArea();
-		return area;
-	}
-}, {
-	beans: true,
-
-	getPathData: function(_matrix, _precision) {
-		var children = this._children,
-			paths = [];
-		for (var i = 0, l = children.length; i < l; i++) {
-			var child = children[i],
-				mx = child._matrix;
-			paths.push(child.getPathData(_matrix && !mx.isIdentity()
-					? _matrix.appended(mx) : _matrix, _precision));
-		}
-		return paths.join(' ');
-	}
-}, {
-	_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
-		return _hitTestChildren.base.call(this, point,
-				options.class === Path || options.type === 'path' ? options
-					: Base.set({}, options, { fill: false }),
-				viewMatrix);
-	},
-
-	_draw: function(ctx, param, viewMatrix, strokeMatrix) {
-		var children = this._children;
-		if (children.length === 0)
-			return;
-
-		param = param.extend({ dontStart: true, dontFinish: true });
-		ctx.beginPath();
-		for (var i = 0, l = children.length; i < l; i++)
-			children[i].draw(ctx, param, strokeMatrix);
-
-		if (!param.clip) {
-			this._setStyles(ctx, param, viewMatrix);
-			var style = this._style;
-			if (style.hasFill()) {
-				ctx.fill(style.getFillRule());
-				ctx.shadowColor = 'rgba(0,0,0,0)';
-			}
-			if (style.hasStroke())
-				ctx.stroke();
-		}
-	},
-
-	_drawSelected: function(ctx, matrix, selectionItems) {
-		var children = this._children;
-		for (var i = 0, l = children.length; i < l; i++) {
-			var child = children[i],
-				mx = child._matrix;
-			if (!selectionItems[child._id]) {
-				child._drawSelected(ctx, mx.isIdentity() ? matrix
-						: matrix.appended(mx));
-			}
-		}
-	}
-},
-new function() {
-	function getCurrentPath(that, check) {
-		var children = that._children;
-		if (check && children.length === 0)
-			throw new Error('Use a moveTo() command first');
-		return children[children.length - 1];
-	}
-
-	return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
-			'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
-			'arcBy'],
-		function(key) {
-			this[key] = function() {
-				var path = getCurrentPath(this, true);
-				path[key].apply(path, arguments);
-			};
-		}, {
-			moveTo: function() {
-				var current = getCurrentPath(this),
-					path = current && current.isEmpty() ? current
-							: new Path(Item.NO_INSERT);
-				if (path !== current)
-					this.addChild(path);
-				path.moveTo.apply(path, arguments);
-			},
-
-			moveBy: function() {
-				var current = getCurrentPath(this, true),
-					last = current && current.getLastSegment(),
-					point = Point.read(arguments);
-				this.moveTo(last ? point.add(last._point) : point);
-			},
-
-			closePath: function(tolerance) {
-				getCurrentPath(this, true).closePath(tolerance);
-			}
-		}
-	);
-}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
-	this[key] = function(param) {
-		var children = this._children,
-			res;
-		for (var i = 0, l = children.length; i < l; i++) {
-			res = children[i][key](param) || res;
-		}
-		return res;
-	};
-}, {}));
-
-PathItem.inject(new function() {
-	var operators = {
-		unite:     { 1: true },
-		intersect: { 2: true },
-		subtract:  { 1: true },
-		exclude:   { 1: true }
-	};
-
-	function preparePath(path, resolve) {
-		var res = path.clone(false).reduce({ simplify: true })
-				.transform(null, true, true);
-		return resolve ? res.resolveCrossings() : res;
-	}
-
-	function createResult(ctor, paths, reduce, path1, path2) {
-		var result = new ctor(Item.NO_INSERT);
-		result.addChildren(paths, true);
-		if (reduce)
-			result = result.reduce({ simplify: true });
-		result.insertAbove(path2 && path1.isSibling(path2)
-				&& path1.getIndex() < path2.getIndex() ? path2 : path1);
-		result.copyAttributes(path1, true);
-		return result;
-	}
-
-	function computeBoolean(path1, path2, operation) {
-		var operator = operators[operation];
-		operator[operation] = true;
-		if (!path1._children && !path1._closed)
-			return computeOpenBoolean(path1, path2, operator);
-		var _path1 = preparePath(path1, true),
-			_path2 = path2 && path1 !== path2 && preparePath(path2, true);
-		if (_path2 && (operator.subtract || operator.exclude)
-				^ (_path2.isClockwise() ^ _path1.isClockwise()))
-			_path2.reverse();
-		var crossings = divideLocations(
-				CurveLocation.expand(_path1.getCrossings(_path2))),
-			segments = [],
-			monoCurves = [];
-
-		function collect(paths) {
-			for (var i = 0, l = paths.length; i < l; i++) {
-				var path = paths[i];
-				segments.push.apply(segments, path._segments);
-				monoCurves.push.apply(monoCurves, path._getMonoCurves());
-				path._overlapsOnly = path._validOverlapsOnly = true;
-			}
-		}
-
-		collect(_path1._children || [_path1]);
-		if (_path2)
-			collect(_path2._children || [_path2]);
-		for (var i = 0, l = crossings.length; i < l; i++) {
-			propagateWinding(crossings[i]._segment, _path1, _path2, monoCurves,
-					operator);
-		}
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var segment = segments[i],
-				inter = segment._intersection;
-			if (segment._winding == null) {
-				propagateWinding(segment, _path1, _path2, monoCurves, operator);
-			}
-			if (!(inter && inter._overlap)) {
-				var path = segment._path;
-				path._overlapsOnly = false;
-				if (operator[segment._winding])
-					path._validOverlapsOnly = false;
-			}
-		}
-		return createResult(CompoundPath, tracePaths(segments, operator), true,
-					path1, path2);
-	}
-
-	function computeOpenBoolean(path1, path2, operator) {
-		if (!path2 || !path2._children && !path2._closed
-				|| !operator.subtract && !operator.intersect)
-			return null;
-		var _path1 = preparePath(path1, false),
-			_path2 = preparePath(path2, false),
-			crossings = _path1.getCrossings(_path2),
-			sub = operator.subtract,
-			paths = [];
-
-		function addPath(path) {
-			if (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {
-				paths.unshift(path);
-				return true;
-			}
-		}
-
-		for (var i = crossings.length - 1; i >= 0; i--) {
-			var path = crossings[i].split();
-			if (path) {
-				if (addPath(path))
-					path.getFirstSegment().setHandleIn(0, 0);
-				_path1.getLastSegment().setHandleOut(0, 0);
-			}
-		}
-		addPath(_path1);
-		return createResult(Group, paths, false, path1, path2);
-	}
-
-	function linkIntersections(from, to) {
-		var prev = from;
-		while (prev) {
-			if (prev === to)
-				return;
-			prev = prev._previous;
-		}
-		while (from._next && from._next !== to)
-			from = from._next;
-		if (!from._next) {
-			while (to._previous)
-				to = to._previous;
-			from._next = to;
-			to._previous = from;
-		}
-	}
-
-	function divideLocations(locations, include) {
-		var results = include && [],
-			tMin = 4e-7,
-			tMax = 1 - tMin,
-			noHandles = false,
-			clearCurves = [],
-			prevCurve,
-			prevTime;
-
-		for (var i = locations.length - 1; i >= 0; i--) {
-			var loc = locations[i];
-			if (include) {
-				if (!include(loc))
-					continue;
-				results.unshift(loc);
-			}
-			var curve = loc._curve,
-				time = loc._time,
-				origTime = time,
-				segment;
-			if (curve !== prevCurve) {
-				noHandles = !curve.hasHandles();
-			} else if (prevTime >= tMin && prevTime <= tMax ) {
-				time /= prevTime;
-			}
-			if (time < tMin) {
-				segment = curve._segment1;
-			} else if (time > tMax) {
-				segment = curve._segment2;
-			} else {
-				var newCurve = curve.divideAtTime(time, true);
-				if (noHandles)
-					clearCurves.push(curve, newCurve);
-				segment = newCurve._segment1;
-			}
-			loc._setSegment(segment);
-			var inter = segment._intersection,
-				dest = loc._intersection;
-			if (inter) {
-				linkIntersections(inter, dest);
-				var other = inter;
-				while (other) {
-					linkIntersections(other._intersection, inter);
-					other = other._next;
-				}
-			} else {
-				segment._intersection = dest;
-			}
-			prevCurve = curve;
-			prevTime = origTime;
-		}
-		for (var i = 0, l = clearCurves.length; i < l; i++) {
-			clearCurves[i].clearHandles();
-		}
-		return results || locations;
-	}
-
-	function getWinding(point, curves, horizontal) {
-		var epsilon = 2e-7,
-			px = point.x,
-			py = point.y,
-			windLeft = 0,
-			windRight = 0,
-			length = curves.length,
-			roots = [],
-			abs = Math.abs;
-		if (horizontal) {
-			var yTop = -Infinity,
-				yBottom = Infinity,
-				yBefore = py - epsilon,
-				yAfter = py + epsilon;
-			for (var i = 0; i < length; i++) {
-				var values = curves[i].values,
-					count = Curve.solveCubic(values, 0, px, roots, 0, 1);
-				for (var j = count - 1; j >= 0; j--) {
-					var y = Curve.getPoint(values, roots[j]).y;
-					if (y < yBefore && y > yTop) {
-						yTop = y;
-					} else if (y > yAfter && y < yBottom) {
-						yBottom = y;
-					}
-				}
-			}
-			yTop = (yTop + py) / 2;
-			yBottom = (yBottom + py) / 2;
-			if (yTop > -Infinity)
-				windLeft = getWinding(new Point(px, yTop), curves).winding;
-			if (yBottom < Infinity)
-				windRight = getWinding(new Point(px, yBottom), curves).winding;
-		} else {
-			var xBefore = px - epsilon,
-				xAfter = px + epsilon,
-				prevWinding,
-				prevXEnd,
-				windLeftOnCurve = 0,
-				windRightOnCurve = 0,
-				isOnCurve = false;
-			for (var i = 0; i < length; i++) {
-				var curve = curves[i],
-					winding = curve.winding,
-					values = curve.values,
-					yStart = values[1],
-					yEnd = values[7];
-				if (curve.last) {
-					prevWinding = curve.last.winding;
-					prevXEnd = curve.last.values[6];
-					isOnCurve = false;
-				}
-				if (py >= yStart && py <= yEnd || py >= yEnd && py <= yStart) {
-					if (winding) {
-						var x = py === yStart ? values[0]
-							: py === yEnd ? values[6]
-							: Curve.solveCubic(values, 1, py, roots, 0, 1) === 1
-							? Curve.getPoint(values, roots[0]).x
-							: null;
-						if (x != null) {
-							if (x >= xBefore && x <= xAfter) {
-								isOnCurve = true;
-							} else if (
-								(py !== yStart || winding !== prevWinding)
-								&& !(py === yStart
-									&& (px - x) * (px - prevXEnd) < 0)) {
-								if (x < xBefore) {
-									windLeft += winding;
-								} else if (x > xAfter) {
-									windRight += winding;
-								}
-							}
-						}
-						prevWinding = winding;
-						prevXEnd = values[6];
-					} else if ((px - values[0]) * (px - values[6]) <= 0) {
-						isOnCurve = true;
-					}
-				}
-				if (isOnCurve && (i >= length - 1 || curves[i + 1].last)) {
-					windLeftOnCurve += 1;
-					windRightOnCurve -= 1;
-				}
-			}
-			if (windLeft === 0 && windRight === 0) {
-				windLeft = windLeftOnCurve;
-				windRight = windRightOnCurve;
-			}
-		}
-		return {
-			winding: Math.max(abs(windLeft), abs(windRight)),
-			contour: !windLeft ^ !windRight
-		};
-	}
-
-	function propagateWinding(segment, path1, path2, monoCurves, operator) {
-		var chain = [],
-			start = segment,
-			totalLength = 0,
-			winding;
-		do {
-			var curve = segment.getCurve(),
-				length = curve.getLength();
-			chain.push({ segment: segment, curve: curve, length: length });
-			totalLength += length;
-			segment = segment.getNext();
-		} while (segment && !segment._intersection && segment !== start);
-		var length = totalLength / 2;
-		for (var j = 0, l = chain.length; j < l; j++) {
-			var entry = chain[j],
-				curveLength = entry.length;
-			if (length <= curveLength) {
-				var curve = entry.curve,
-					path = curve._path,
-					parent = path._parent,
-					t = curve.getTimeAt(length),
-					pt = curve.getPointAtTime(t),
-					hor = Math.abs(curve.getTangentAtTime(t).y)
-							< 1e-7;
-				if (parent instanceof CompoundPath)
-					path = parent;
-				winding = !(operator.subtract && path2 && (
-						path === path1 &&  path2._getWinding(pt, hor) ||
-						path === path2 && !path1._getWinding(pt, hor)))
-							? getWinding(pt, monoCurves, hor)
-							: { winding: 0 };
-				 break;
-			}
-			length -= curveLength;
-		}
-		for (var j = chain.length - 1; j >= 0; j--) {
-			var seg = chain[j].segment;
-			seg._winding = winding.winding;
-			seg._contour = winding.contour;
-		}
-	}
-
-	function tracePaths(segments, operator) {
-		var paths = [],
-			start,
-			otherStart;
-
-		function isValid(seg, excludeContour) {
-			return !!(seg && !seg._visited && (!operator
-					|| operator[seg._winding]
-					|| !excludeContour && operator.unite && seg._contour));
-		}
-
-		function isStart(seg) {
-			return seg === start || seg === otherStart;
-		}
-
-		function findBestIntersection(inter, exclude) {
-			if (!inter._next)
-				return inter;
-			while (inter) {
-				var seg = inter._segment,
-					nextSeg = seg.getNext(),
-					nextInter = nextSeg && nextSeg._intersection;
-				if (seg !== exclude && (isStart(seg) || isStart(nextSeg)
-					|| !seg._visited && !nextSeg._visited
-					&& (!operator || isValid(seg) && (isValid(nextSeg)
-						|| nextInter && isValid(nextInter._segment)))
-					))
-					return inter;
-				inter = inter._next;
-			}
-			return null;
-		}
-
-		for (var i = 0, l = segments.length; i < l; i++) {
-			var path = null,
-				finished = false,
-				seg = segments[i],
-				inter = seg._intersection,
-				handleIn;
-			if (!seg._visited && seg._path._overlapsOnly) {
-				var path1 = seg._path,
-					path2 = inter._segment._path,
-					segments1 = path1._segments,
-					segments2 = path2._segments;
-				if (Base.equals(segments1, segments2)) {
-					if ((operator.unite || operator.intersect)
-							&& path1.getArea()) {
-						paths.push(path1.clone(false));
-					}
-					for (var j = 0, k = segments1.length; j < k; j++) {
-						segments1[j]._visited = segments2[j]._visited = true;
-					}
-				}
-			}
-			if (!isValid(seg, true)
-					|| !seg._path._validOverlapsOnly && inter && inter._overlap)
-				continue;
-			start = otherStart = null;
-			while (true) {
-				inter = inter && findBestIntersection(inter, seg) || inter;
-				var other = inter && inter._segment;
-				if (isStart(seg)) {
-					finished = true;
-				} else if (other) {
-					if (isStart(other)) {
-						finished = true;
-						seg = other;
-					} else if (isValid(other, isValid(seg, true))) {
-						if (operator
-								&& (operator.intersect || operator.subtract)) {
-							seg._visited = true;
-						}
-						seg = other;
-					}
-				}
-				if (finished || seg._visited) {
-					seg._visited = true;
-					break;
-				}
-				if (seg._path._validOverlapsOnly && !isValid(seg))
-					break;
-				if (!path) {
-					path = new Path(Item.NO_INSERT);
-					start = seg;
-					otherStart = other;
-				}
-				var next = seg.getNext();
-				path.add(new Segment(seg._point, handleIn,
-						next && seg._handleOut));
-				seg._visited = true;
-				seg = next || seg._path.getFirstSegment();
-				handleIn = next && next._handleIn;
-				inter = seg._intersection;
-			}
-			if (finished) {
-				path.firstSegment.setHandleIn(handleIn);
-				path.setClosed(true);
-			} else if (path) {
-				var area = path.getArea(true);
-				if (Math.abs(area) >= 2e-7) {
-					console.error('Boolean operation resulted in open path',
-							'segments =', path._segments.length,
-							'length =', path.getLength(),
-							'area=', area);
-				}
-				path = null;
-			}
-			if (path && (path._segments.length > 8
-					|| !Numerical.isZero(path.getArea()))) {
-				paths.push(path);
-				path = null;
-			}
-		}
-		return paths;
-	}
-
-	return {
-		_getWinding: function(point, horizontal) {
-			return getWinding(point, this._getMonoCurves(), horizontal).winding;
-		},
-
-		unite: function(path) {
-			return computeBoolean(this, path, 'unite');
-		},
-
-		intersect: function(path) {
-			return computeBoolean(this, path, 'intersect');
-		},
-
-		subtract: function(path) {
-			return computeBoolean(this, path, 'subtract');
-		},
-
-		exclude: function(path) {
-			return computeBoolean(this, path, 'exclude');
-		},
-
-		divide: function(path) {
-			return createResult(Group, [this.subtract(path),
-					this.intersect(path)], true, this, path);
-		},
-
-		resolveCrossings: function() {
-			var children = this._children,
-				paths = children || [this];
-
-			function hasOverlap(seg) {
-				var inter = seg && seg._intersection;
-				return inter && inter._overlap;
-			}
-
-			var hasOverlaps = false,
-				hasCrossings = false,
-				intersections = this.getIntersections(null, function(inter) {
-					return inter._overlap && (hasOverlaps = true)
-							|| inter.isCrossing() && (hasCrossings = true);
-				});
-			intersections = CurveLocation.expand(intersections);
-			if (hasOverlaps) {
-				var overlaps = divideLocations(intersections, function(inter) {
-					return inter._overlap;
-				});
-				for (var i = overlaps.length - 1; i >= 0; i--) {
-					var seg = overlaps[i]._segment,
-						prev = seg.getPrevious(),
-						next = seg.getNext();
-					if (seg._path && hasOverlap(prev) && hasOverlap(next)) {
-						seg.remove();
-						prev._handleOut.set(0, 0);
-						next._handleIn.set(0, 0);
-						var curve = prev.getCurve();
-						if (curve.isStraight() && curve.getLength() === 0)
-							prev.remove();
-					}
-				}
-			}
-			if (hasCrossings) {
-				divideLocations(intersections, hasOverlaps && function(inter) {
-					var curve1 = inter.getCurve(),
-						curve2 = inter._intersection._curve,
-						seg = inter._segment;
-					if (curve1 && curve2 && curve1._path && curve2._path) {
-						return true;
-					} else if (seg) {
-						seg._intersection = null;
-					}
-				});
-				paths = tracePaths(Base.each(paths, function(path) {
-					this.push.apply(this, path._segments);
-				}, []));
-			}
-			var length = paths.length,
-				item;
-			if (length > 1) {
-				paths = paths.slice().sort(function (a, b) {
-					return b.getBounds().getArea() - a.getBounds().getArea();
-				});
-				var first = paths[0],
-					items = [first],
-					excluded = {},
-					isNonZero = this.getFillRule() === 'nonzero',
-					windings = isNonZero && Base.each(paths, function(path) {
-						this.push(path.isClockwise() ? 1 : -1);
-					}, []);
-				for (var i = 1; i < length; i++) {
-					var path = paths[i],
-						point = path.getInteriorPoint(),
-						isContained = false,
-						container = null,
-						exclude = false;
-					for (var j = i - 1; j >= 0 && !container; j--) {
-						if (paths[j].contains(point)) {
-							if (isNonZero && !isContained) {
-								windings[i] += windings[j];
-								if (windings[i] && windings[j]) {
-									exclude = excluded[i] = true;
-									break;
-								}
-							}
-							isContained = true;
-							container = !excluded[j] && paths[j];
-						}
-					}
-					if (!exclude) {
-						path.setClockwise(container ? !container.isClockwise()
-								: first.isClockwise());
-						items.push(path);
-					}
-				}
-				paths = items;
-				length = items.length;
-			}
-			if (length > 1 && children) {
-				if (paths !== children) {
-					this.setChildren(paths, true);
-				}
-				item = this;
-			} else if (length === 1 && !children) {
-				if (paths[0] !== this)
-					this.setSegments(paths[0].removeSegments());
-				item = this;
-			}
-			if (!item) {
-				item = new CompoundPath(Item.NO_INSERT);
-				item.addChildren(paths, true);
-				item = item.reduce();
-				item.copyAttributes(this);
-				this.replaceWith(item);
-			}
-			return item;
-		}
-	};
-});
-
-Path.inject({
-	_getMonoCurves: function() {
-		var monoCurves = this._monoCurves,
-			last;
-
-		function insertCurve(v) {
-			var y0 = v[1],
-				y1 = v[7],
-				winding = Math.abs((y0 - y1) / (v[0] - v[6]))
-						< 2e-7
-					? 0
-					: y0 > y1
-						? -1
-						: 1,
-				curve = { values: v, winding: winding };
-			monoCurves.push(curve);
-			if (winding)
-				last = curve;
-		}
-
-		function handleCurve(v) {
-			if (Curve.getLength(v) === 0)
-				return;
-			var y0 = v[1],
-				y1 = v[3],
-				y2 = v[5],
-				y3 = v[7];
-			if (Curve.isStraight(v)
-					|| y0 >= y1 === y1 >= y2 && y1 >= y2 === y2 >= y3) {
-				insertCurve(v);
-			} else {
-				var a = 3 * (y1 - y2) - y0 + y3,
-					b = 2 * (y0 + y2) - 4 * y1,
-					c = y1 - y0,
-					tMin = 4e-7,
-					tMax = 1 - tMin,
-					roots = [],
-					n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
-				if (n < 1) {
-					insertCurve(v);
-				} else {
-					roots.sort();
-					var t = roots[0],
-						parts = Curve.subdivide(v, t);
-					insertCurve(parts[0]);
-					if (n > 1) {
-						t = (roots[1] - t) / (1 - t);
-						parts = Curve.subdivide(parts[1], t);
-						insertCurve(parts[0]);
-					}
-					insertCurve(parts[1]);
-				}
-			}
-		}
-
-		if (!monoCurves) {
-			monoCurves = this._monoCurves = [];
-			var curves = this.getCurves(),
-				segments = this._segments;
-			for (var i = 0, l = curves.length; i < l; i++)
-				handleCurve(curves[i].getValues());
-			if (!this._closed && segments.length > 1) {
-				var p1 = segments[segments.length - 1]._point,
-					p2 = segments[0]._point,
-					p1x = p1._x, p1y = p1._y,
-					p2x = p2._x, p2y = p2._y;
-				handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
-			}
-			if (monoCurves.length > 0) {
-				monoCurves[0].last = last;
-			}
-		}
-		return monoCurves;
-	},
-
-	getInteriorPoint: function() {
-		var bounds = this.getBounds(),
-			point = bounds.getCenter(true);
-		if (!this.contains(point)) {
-			var curves = this._getMonoCurves(),
-				roots = [],
-				y = point.y,
-				intercepts = [];
-			for (var i = 0, l = curves.length; i < l; i++) {
-				var values = curves[i].values;
-				if (curves[i].winding === 1
-						&& y > values[1] && y <= values[7]
-						|| y >= values[7] && y < values[1]) {
-					var count = Curve.solveCubic(values, 1, y, roots, 0, 1);
-					for (var j = count - 1; j >= 0; j--) {
-						intercepts.push(Curve.getPoint(values, roots[j]).x);
-					}
-				}
-			}
-			intercepts.sort(function(a, b) { return a - b; });
-			point.x = (intercepts[0] + intercepts[1]) / 2;
-		}
-		return point;
-	}
-});
-
-CompoundPath.inject({
-	_getMonoCurves: function() {
-		var children = this._children,
-			monoCurves = [];
-		for (var i = 0, l = children.length; i < l; i++)
-			monoCurves.push.apply(monoCurves, children[i]._getMonoCurves());
-		return monoCurves;
-	}
-});
-
-var PathIterator = Base.extend({
-	_class: 'PathIterator',
-
-	initialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {
-		var curves = [],
-			parts = [],
-			length = 0,
-			minSpan = 1 / (maxRecursion || 32),
-			segments = path._segments,
-			segment1 = segments[0],
-			segment2;
-
-		function addCurve(segment1, segment2) {
-			var curve = Curve.getValues(segment1, segment2, matrix);
-			curves.push(curve);
-			computeParts(curve, segment1._index, 0, 1);
-		}
-
-		function computeParts(curve, index, t1, t2) {
-			if ((t2 - t1) > minSpan
-					&& !(ignoreStraight && Curve.isStraight(curve))
-					&& !Curve.isFlatEnough(curve, flatness || 0.25)) {
-				var halves = Curve.subdivide(curve, 0.5),
-					tMid = (t1 + t2) / 2;
-				computeParts(halves[0], index, t1, tMid);
-				computeParts(halves[1], index, tMid, t2);
-			} else {
-				var dx = curve[6] - curve[0],
-					dy = curve[7] - curve[1],
-					dist = Math.sqrt(dx * dx + dy * dy);
-				if (dist > 0) {
-					length += dist;
-					parts.push({
-						offset: length,
-						curve: curve,
-						index: index,
-						time: t2,
-					});
-				}
-			}
-		}
-
-		for (var i = 1, l = segments.length; i < l; i++) {
-			segment2 = segments[i];
-			addCurve(segment1, segment2);
-			segment1 = segment2;
-		}
-		if (path._closed)
-			addCurve(segment2, segments[0]);
-		this.curves = curves;
-		this.parts = parts;
-		this.length = length;
-		this.index = 0;
-	},
-
-	_get: function(offset) {
-		var i, j = this.index;
-		for (;;) {
-			i = j;
-			if (j === 0 || this.parts[--j].offset < offset)
-				break;
-		}
-		for (var l = this.parts.length; i < l; i++) {
-			var part = this.parts[i];
-			if (part.offset >= offset) {
-				this.index = i;
-				var prev = this.parts[i - 1];
-				var prevTime = prev && prev.index === part.index ? prev.time : 0,
-					prevOffset = prev ? prev.offset : 0;
-				return {
-					index: part.index,
-					time: prevTime + (part.time - prevTime)
-						* (offset - prevOffset) / (part.offset - prevOffset)
-				};
-			}
-		}
-		var part = this.parts[this.parts.length - 1];
-		return {
-			index: part.index,
-			time: 1
-		};
-	},
-
-	drawPart: function(ctx, from, to) {
-		var start = this._get(from),
-			end = this._get(to);
-		for (var i = start.index, l = end.index; i <= l; i++) {
-			var curve = Curve.getPart(this.curves[i],
-					i === start.index ? start.time : 0,
-					i === end.index ? end.time : 1);
-			if (i === start.index)
-				ctx.moveTo(curve[0], curve[1]);
-			ctx.bezierCurveTo.apply(ctx, curve.slice(2));
-		}
-	}
-}, Base.each(Curve._evaluateMethods,
-	function(name) {
-		this[name + 'At'] = function(offset) {
-			var param = this._get(offset);
-			return Curve[name](this.curves[param.index], param.time);
-		};
-	}, {})
-);
-
-var PathFitter = Base.extend({
-	initialize: function(path) {
-		var points = this.points = [],
-			segments = path._segments,
-			closed = path._closed;
-		for (var i = 0, prev, l = segments.length; i < l; i++) {
-			var point = segments[i].point;
-			if (!prev || !prev.equals(point)) {
-				points.push(prev = point.clone());
-			}
-		}
-		if (closed) {
-			points.unshift(points[points.length - 1]);
-			points.push(points[1]);
-		}
-		this.closed = closed;
-	},
-
-	fit: function(error) {
-		var points = this.points,
-			length = points.length,
-			segments = null;
-		if (length > 0) {
-			segments = [new Segment(points[0])];
-			if (length > 1) {
-				this.fitCubic(segments, error, 0, length - 1,
-						points[1].subtract(points[0]),
-						points[length - 2].subtract(points[length - 1]));
-				if (this.closed) {
-					segments.shift();
-					segments.pop();
-				}
-			}
-		}
-		return segments;
-	},
-
-	fitCubic: function(segments, error, first, last, tan1, tan2) {
-		var points = this.points;
-		if (last - first === 1) {
-			var pt1 = points[first],
-				pt2 = points[last],
-				dist = pt1.getDistance(pt2) / 3;
-			this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
-					pt2.add(tan2.normalize(dist)), pt2]);
-			return;
-		}
-		var uPrime = this.chordLengthParameterize(first, last),
-			maxError = Math.max(error, error * error),
-			split,
-			parametersInOrder = true;
-		for (var i = 0; i <= 4; i++) {
-			var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
-			var max = this.findMaxError(first, last, curve, uPrime);
-			if (max.error < error && parametersInOrder) {
-				this.addCurve(segments, curve);
-				return;
-			}
-			split = max.index;
-			if (max.error >= maxError)
-				break;
-			parametersInOrder = this.reparameterize(first, last, uPrime, curve);
-			maxError = max.error;
-		}
-		var tanCenter = points[split - 1].subtract(points[split + 1]);
-		this.fitCubic(segments, error, first, split, tan1, tanCenter);
-		this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
-	},
-
-	addCurve: function(segments, curve) {
-		var prev = segments[segments.length - 1];
-		prev.setHandleOut(curve[1].subtract(curve[0]));
-		segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
-	},
-
-	generateBezier: function(first, last, uPrime, tan1, tan2) {
-		var epsilon = 1e-12,
-			abs = Math.abs,
-			points = this.points,
-			pt1 = points[first],
-			pt2 = points[last],
-			C = [[0, 0], [0, 0]],
-			X = [0, 0];
-
-		for (var i = 0, l = last - first + 1; i < l; i++) {
-			var u = uPrime[i],
-				t = 1 - u,
-				b = 3 * u * t,
-				b0 = t * t * t,
-				b1 = b * t,
-				b2 = b * u,
-				b3 = u * u * u,
-				a1 = tan1.normalize(b1),
-				a2 = tan2.normalize(b2),
-				tmp = points[first + i]
-					.subtract(pt1.multiply(b0 + b1))
-					.subtract(pt2.multiply(b2 + b3));
-			C[0][0] += a1.dot(a1);
-			C[0][1] += a1.dot(a2);
-			C[1][0] = C[0][1];
-			C[1][1] += a2.dot(a2);
-			X[0] += a1.dot(tmp);
-			X[1] += a2.dot(tmp);
-		}
-
-		var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
-			alpha1, alpha2;
-		if (abs(detC0C1) > epsilon) {
-			var detC0X = C[0][0] * X[1]    - C[1][0] * X[0],
-				detXC1 = X[0]    * C[1][1] - X[1]    * C[0][1];
-			alpha1 = detXC1 / detC0C1;
-			alpha2 = detC0X / detC0C1;
-		} else {
-			var c0 = C[0][0] + C[0][1],
-				c1 = C[1][0] + C[1][1];
-			if (abs(c0) > epsilon) {
-				alpha1 = alpha2 = X[0] / c0;
-			} else if (abs(c1) > epsilon) {
-				alpha1 = alpha2 = X[1] / c1;
-			} else {
-				alpha1 = alpha2 = 0;
-			}
-		}
-
-		var segLength = pt2.getDistance(pt1),
-			eps = epsilon * segLength,
-			handle1,
-			handle2;
-		if (alpha1 < eps || alpha2 < eps) {
-			alpha1 = alpha2 = segLength / 3;
-		} else {
-			var line = pt2.subtract(pt1);
-			handle1 = tan1.normalize(alpha1);
-			handle2 = tan2.normalize(alpha2);
-			if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
-				alpha1 = alpha2 = segLength / 3;
-				handle1 = handle2 = null;
-			}
-		}
-
-		return [pt1,
-				pt1.add(handle1 || tan1.normalize(alpha1)),
-				pt2.add(handle2 || tan2.normalize(alpha2)),
-				pt2];
-	},
-
-	reparameterize: function(first, last, u, curve) {
-		for (var i = first; i <= last; i++) {
-			u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
-		}
-		for (var i = 1, l = u.length; i < l; i++) {
-			if (u[i] <= u[i - 1])
-				return false;
-		}
-		return true;
-	},
-
-	findRoot: function(curve, point, u) {
-		var curve1 = [],
-			curve2 = [];
-		for (var i = 0; i <= 2; i++) {
-			curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);
-		}
-		for (var i = 0; i <= 1; i++) {
-			curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);
-		}
-		var pt = this.evaluate(3, curve, u),
-			pt1 = this.evaluate(2, curve1, u),
-			pt2 = this.evaluate(1, curve2, u),
-			diff = pt.subtract(point),
-			df = pt1.dot(pt1) + diff.dot(pt2);
-		if (Math.abs(df) < 1e-6)
-			return u;
-		return u - diff.dot(pt1) / df;
-	},
-
-	evaluate: function(degree, curve, t) {
-		var tmp = curve.slice();
-		for (var i = 1; i <= degree; i++) {
-			for (var j = 0; j <= degree - i; j++) {
-				tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));
-			}
-		}
-		return tmp[0];
-	},
-
-	chordLengthParameterize: function(first, last) {
-		var u = [0];
-		for (var i = first + 1; i <= last; i++) {
-			u[i - first] = u[i - first - 1]
-					+ this.points[i].getDistance(this.points[i - 1]);
-		}
-		for (var i = 1, m = last - first; i <= m; i++) {
-			u[i] /= u[m];
-		}
-		return u;
-	},
-
-	findMaxError: function(first, last, curve, u) {
-		var index = Math.floor((last - first + 1) / 2),
-			maxDist = 0;
-		for (var i = first + 1; i < last; i++) {
-			var P = this.evaluate(3, curve, u[i - first]);
-			var v = P.subtract(this.points[i]);
-			var dist = v.x * v.x + v.y * v.y;
-			if (dist >= maxDist) {
-				maxDist = dist;
-				index = i;
-			}
-		}
-		return {
-			error: maxDist,
-			index: index
-		};
-	}
-});
-
-var TextItem = Item.extend({
-	_class: 'TextItem',
-	_applyMatrix: false,
-	_canApplyMatrix: false,
-	_serializeFields: {
-		content: null
-	},
-	_boundsOptions: { stroke: false, handle: false },
-
-	initialize: function TextItem(arg) {
-		this._content = '';
-		this._lines = [];
-		var hasProps = arg && Base.isPlainObject(arg)
-				&& arg.x === undefined && arg.y === undefined;
-		this._initialize(hasProps && arg, !hasProps && Point.read(arguments));
-	},
-
-	_equals: function(item) {
-		return this._content === item._content;
-	},
-
-	copyContent: function(source) {
-		this.setContent(source._content);
-	},
-
-	getContent: function() {
-		return this._content;
-	},
-
-	setContent: function(content) {
-		this._content = '' + content;
-		this._lines = this._content.split(/\r\n|\n|\r/mg);
-		this._changed(265);
-	},
-
-	isEmpty: function() {
-		return !this._content;
-	},
-
-	getCharacterStyle: '#getStyle',
-	setCharacterStyle: '#setStyle',
-
-	getParagraphStyle: '#getStyle',
-	setParagraphStyle: '#setStyle'
-});
-
-var PointText = TextItem.extend({
-	_class: 'PointText',
-
-	initialize: function PointText() {
-		TextItem.apply(this, arguments);
-	},
-
-	getPoint: function() {
-		var point = this._matrix.getTranslation();
-		return new LinkedPoint(point.x, point.y, this, 'setPoint');
-	},
-
-	setPoint: function() {
-		var point = Point.read(arguments);
-		this.translate(point.subtract(this._matrix.getTranslation()));
-	},
-
-	_draw: function(ctx, param, viewMatrix) {
-		if (!this._content)
-			return;
-		this._setStyles(ctx, param, viewMatrix);
-		var lines = this._lines,
-			style = this._style,
-			hasFill = style.hasFill(),
-			hasStroke = style.hasStroke(),
-			leading = style.getLeading(),
-			shadowColor = ctx.shadowColor;
-		ctx.font = style.getFontStyle();
-		ctx.textAlign = style.getJustification();
-		for (var i = 0, l = lines.length; i < l; i++) {
-			ctx.shadowColor = shadowColor;
-			var line = lines[i];
-			if (hasFill) {
-				ctx.fillText(line, 0, 0);
-				ctx.shadowColor = 'rgba(0,0,0,0)';
-			}
-			if (hasStroke)
-				ctx.strokeText(line, 0, 0);
-			ctx.translate(0, leading);
-		}
-	},
-
-	_getBounds: function(matrix, options) {
-		var style = this._style,
-			lines = this._lines,
-			numLines = lines.length,
-			justification = style.getJustification(),
-			leading = style.getLeading(),
-			width = this.getView().getTextWidth(style.getFontStyle(), lines),
-			x = 0;
-		if (justification !== 'left')
-			x -= width / (justification === 'center' ? 2: 1);
-		var bounds = new Rectangle(x,
-					numLines ? - 0.75 * leading : 0,
-					width, numLines * leading);
-		return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
-	}
-});
-
-var Color = Base.extend(new function() {
-	var types = {
-		gray: ['gray'],
-		rgb: ['red', 'green', 'blue'],
-		hsb: ['hue', 'saturation', 'brightness'],
-		hsl: ['hue', 'saturation', 'lightness'],
-		gradient: ['gradient', 'origin', 'destination', 'highlight']
-	};
-
-	var componentParsers = {},
-		colorCache = {},
-		colorCtx;
-
-	function fromCSS(string) {
-		var match = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/),
-			components;
-		if (match) {
-			components = [0, 0, 0];
-			for (var i = 0; i < 3; i++) {
-				var value = match[i + 1];
-				components[i] = parseInt(value.length == 1
-						? value + value : value, 16) / 255;
-			}
-		} else if (match = string.match(/^rgba?\((.*)\)$/)) {
-			components = match[1].split(',');
-			for (var i = 0, l = components.length; i < l; i++) {
-				var value = +components[i];
-				components[i] = i < 3 ? value / 255 : value;
-			}
-		} else if (window) {
-			var cached = colorCache[string];
-			if (!cached) {
-				if (!colorCtx) {
-					colorCtx = CanvasProvider.getContext(1, 1);
-					colorCtx.globalCompositeOperation = 'copy';
-				}
-				colorCtx.fillStyle = 'rgba(0,0,0,0)';
-				colorCtx.fillStyle = string;
-				colorCtx.fillRect(0, 0, 1, 1);
-				var data = colorCtx.getImageData(0, 0, 1, 1).data;
-				cached = colorCache[string] = [
-					data[0] / 255,
-					data[1] / 255,
-					data[2] / 255
-				];
-			}
-			components = cached.slice();
-		} else {
-			components = [0, 0, 0];
-		}
-		return components;
-	}
-
-	var hsbIndices = [
-		[0, 3, 1],
-		[2, 0, 1],
-		[1, 0, 3],
-		[1, 2, 0],
-		[3, 1, 0],
-		[0, 1, 2]
-	];
-
-	var converters = {
-		'rgb-hsb': function(r, g, b) {
-			var max = Math.max(r, g, b),
-				min = Math.min(r, g, b),
-				delta = max - min,
-				h = delta === 0 ? 0
-					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
-						: max == g ? (b - r) / delta + 2
-						:            (r - g) / delta + 4) * 60;
-			return [h, max === 0 ? 0 : delta / max, max];
-		},
-
-		'hsb-rgb': function(h, s, b) {
-			h = (((h / 60) % 6) + 6) % 6;
-			var i = Math.floor(h),
-				f = h - i,
-				i = hsbIndices[i],
-				v = [
-					b,
-					b * (1 - s),
-					b * (1 - s * f),
-					b * (1 - s * (1 - f))
-				];
-			return [v[i[0]], v[i[1]], v[i[2]]];
-		},
-
-		'rgb-hsl': function(r, g, b) {
-			var max = Math.max(r, g, b),
-				min = Math.min(r, g, b),
-				delta = max - min,
-				achromatic = delta === 0,
-				h = achromatic ? 0
-					:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
-						: max == g ? (b - r) / delta + 2
-						:            (r - g) / delta + 4) * 60,
-				l = (max + min) / 2,
-				s = achromatic ? 0 : l < 0.5
-						? delta / (max + min)
-						: delta / (2 - max - min);
-			return [h, s, l];
-		},
-
-		'hsl-rgb': function(h, s, l) {
-			h = (((h / 360) % 1) + 1) % 1;
-			if (s === 0)
-				return [l, l, l];
-			var t3s = [ h + 1 / 3, h, h - 1 / 3 ],
-				t2 = l < 0.5 ? l * (1 + s) : l + s - l * s,
-				t1 = 2 * l - t2,
-				c = [];
-			for (var i = 0; i < 3; i++) {
-				var t3 = t3s[i];
-				if (t3 < 0) t3 += 1;
-				if (t3 > 1) t3 -= 1;
-				c[i] = 6 * t3 < 1
-					? t1 + (t2 - t1) * 6 * t3
-					: 2 * t3 < 1
-						? t2
-						: 3 * t3 < 2
-							? t1 + (t2 - t1) * ((2 / 3) - t3) * 6
-							: t1;
-			}
-			return c;
-		},
-
-		'rgb-gray': function(r, g, b) {
-			return [r * 0.2989 + g * 0.587 + b * 0.114];
-		},
-
-		'gray-rgb': function(g) {
-			return [g, g, g];
-		},
-
-		'gray-hsb': function(g) {
-			return [0, 0, g];
-		},
-
-		'gray-hsl': function(g) {
-			return [0, 0, g];
-		},
-
-		'gradient-rgb': function() {
-			return [];
-		},
-
-		'rgb-gradient': function() {
-			return [];
-		}
-
-	};
-
-	return Base.each(types, function(properties, type) {
-		componentParsers[type] = [];
-		Base.each(properties, function(name, index) {
-			var part = Base.capitalize(name),
-				hasOverlap = /^(hue|saturation)$/.test(name),
-				parser = componentParsers[type][index] = name === 'gradient'
-					? function(value) {
-						var current = this._components[0];
-						value = Gradient.read(Array.isArray(value) ? value
-								: arguments, 0, { readNull: true });
-						if (current !== value) {
-							if (current)
-								current._removeOwner(this);
-							if (value)
-								value._addOwner(this);
-						}
-						return value;
-					}
-					: type === 'gradient'
-						? function() {
-							return Point.read(arguments, 0, {
-									readNull: name === 'highlight',
-									clone: true
-							});
-						}
-						: function(value) {
-							return value == null || isNaN(value) ? 0 : value;
-						};
-
-			this['get' + part] = function() {
-				return this._type === type
-					|| hasOverlap && /^hs[bl]$/.test(this._type)
-						? this._components[index]
-						: this._convert(type)[index];
-			};
-
-			this['set' + part] = function(value) {
-				if (this._type !== type
-						&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {
-					this._components = this._convert(type);
-					this._properties = types[type];
-					this._type = type;
-				}
-				this._components[index] = parser.call(this, value);
-				this._changed();
-			};
-		}, this);
-	}, {
-		_class: 'Color',
-		_readIndex: true,
-
-		initialize: function Color(arg) {
-			var slice = Array.prototype.slice,
-				args = arguments,
-				reading = this.__read,
-				read = 0,
-				type,
-				components,
-				alpha,
-				values;
-			if (Array.isArray(arg)) {
-				args = arg;
-				arg = args[0];
-			}
-			var argType = arg != null && typeof arg;
-			if (argType === 'string' && arg in types) {
-				type = arg;
-				arg = args[1];
-				if (Array.isArray(arg)) {
-					components = arg;
-					alpha = args[2];
-				} else {
-					if (reading)
-						read = 1;
-					args = slice.call(args, 1);
-					argType = typeof arg;
-				}
-			}
-			if (!components) {
-				values = argType === 'number'
-						? args
-						: argType === 'object' && arg.length != null
-							? arg
-							: null;
-				if (values) {
-					if (!type)
-						type = values.length >= 3
-								? 'rgb'
-								: 'gray';
-					var length = types[type].length;
-					alpha = values[length];
-					if (reading) {
-						read += values === arguments
-							? length + (alpha != null ? 1 : 0)
-							: 1;
-					}
-					if (values.length > length)
-						values = slice.call(values, 0, length);
-				} else if (argType === 'string') {
-					type = 'rgb';
-					components = fromCSS(arg);
-					if (components.length === 4) {
-						alpha = components[3];
-						components.length--;
-					}
-				} else if (argType === 'object') {
-					if (arg.constructor === Color) {
-						type = arg._type;
-						components = arg._components.slice();
-						alpha = arg._alpha;
-						if (type === 'gradient') {
-							for (var i = 1, l = components.length; i < l; i++) {
-								var point = components[i];
-								if (point)
-									components[i] = point.clone();
-							}
-						}
-					} else if (arg.constructor === Gradient) {
-						type = 'gradient';
-						values = args;
-					} else {
-						type = 'hue' in arg
-							? 'lightness' in arg
-								? 'hsl'
-								: 'hsb'
-							: 'gradient' in arg || 'stops' in arg
-									|| 'radial' in arg
-								? 'gradient'
-								: 'gray' in arg
-									? 'gray'
-									: 'rgb';
-						var properties = types[type],
-							parsers = componentParsers[type];
-						this._components = components = [];
-						for (var i = 0, l = properties.length; i < l; i++) {
-							var value = arg[properties[i]];
-							if (value == null && i === 0 && type === 'gradient'
-									&& 'stops' in arg) {
-								value = {
-									stops: arg.stops,
-									radial: arg.radial
-								};
-							}
-							value = parsers[i].call(this, value);
-							if (value != null)
-								components[i] = value;
-						}
-						alpha = arg.alpha;
-					}
-				}
-				if (reading && type)
-					read = 1;
-			}
-			this._type = type || 'rgb';
-			if (!components) {
-				this._components = components = [];
-				var parsers = componentParsers[this._type];
-				for (var i = 0, l = parsers.length; i < l; i++) {
-					var value = parsers[i].call(this, values && values[i]);
-					if (value != null)
-						components[i] = value;
-				}
-			}
-			this._components = components;
-			this._properties = types[this._type];
-			this._alpha = alpha;
-			if (reading)
-				this.__read = read;
-		},
-
-		_set: '#initialize',
-
-		_serialize: function(options, dictionary) {
-			var components = this.getComponents();
-			return Base.serialize(
-					/^(gray|rgb)$/.test(this._type)
-						? components
-						: [this._type].concat(components),
-					options, true, dictionary);
-		},
-
-		_changed: function() {
-			this._canvasStyle = null;
-			if (this._owner)
-				this._owner._changed(65);
-		},
-
-		_convert: function(type) {
-			var converter;
-			return this._type === type
-					? this._components.slice()
-					: (converter = converters[this._type + '-' + type])
-						? converter.apply(this, this._components)
-						: converters['rgb-' + type].apply(this,
-							converters[this._type + '-rgb'].apply(this,
-								this._components));
-		},
-
-		convert: function(type) {
-			return new Color(type, this._convert(type), this._alpha);
-		},
-
-		getType: function() {
-			return this._type;
-		},
-
-		setType: function(type) {
-			this._components = this._convert(type);
-			this._properties = types[type];
-			this._type = type;
-		},
-
-		getComponents: function() {
-			var components = this._components.slice();
-			if (this._alpha != null)
-				components.push(this._alpha);
-			return components;
-		},
-
-		getAlpha: function() {
-			return this._alpha != null ? this._alpha : 1;
-		},
-
-		setAlpha: function(alpha) {
-			this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);
-			this._changed();
-		},
-
-		hasAlpha: function() {
-			return this._alpha != null;
-		},
-
-		equals: function(color) {
-			var col = Base.isPlainValue(color, true)
-					? Color.read(arguments)
-					: color;
-			return col === this || col && this._class === col._class
-					&& this._type === col._type
-					&& this._alpha === col._alpha
-					&& Base.equals(this._components, col._components)
-					|| false;
-		},
-
-		toString: function() {
-			var properties = this._properties,
-				parts = [],
-				isGradient = this._type === 'gradient',
-				f = Formatter.instance;
-			for (var i = 0, l = properties.length; i < l; i++) {
-				var value = this._components[i];
-				if (value != null)
-					parts.push(properties[i] + ': '
-							+ (isGradient ? value : f.number(value)));
-			}
-			if (this._alpha != null)
-				parts.push('alpha: ' + f.number(this._alpha));
-			return '{ ' + parts.join(', ') + ' }';
-		},
-
-		toCSS: function(hex) {
-			var components = this._convert('rgb'),
-				alpha = hex || this._alpha == null ? 1 : this._alpha;
-			function convert(val) {
-				return Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);
-			}
-			components = [
-				convert(components[0]),
-				convert(components[1]),
-				convert(components[2])
-			];
-			if (alpha < 1)
-				components.push(alpha < 0 ? 0 : alpha);
-			return hex
-					? '#' + ((1 << 24) + (components[0] << 16)
-						+ (components[1] << 8)
-						+ components[2]).toString(16).slice(1)
-					: (components.length == 4 ? 'rgba(' : 'rgb(')
-						+ components.join(',') + ')';
-		},
-
-		toCanvasStyle: function(ctx) {
-			if (this._canvasStyle)
-				return this._canvasStyle;
-			if (this._type !== 'gradient')
-				return this._canvasStyle = this.toCSS();
-			var components = this._components,
-				gradient = components[0],
-				stops = gradient._stops,
-				origin = components[1],
-				destination = components[2],
-				canvasGradient;
-			if (gradient._radial) {
-				var radius = destination.getDistance(origin),
-					highlight = components[3];
-				if (highlight) {
-					var vector = highlight.subtract(origin);
-					if (vector.getLength() > radius)
-						highlight = origin.add(vector.normalize(radius - 0.1));
-				}
-				var start = highlight || origin;
-				canvasGradient = ctx.createRadialGradient(start.x, start.y,
-						0, origin.x, origin.y, radius);
-			} else {
-				canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
-						destination.x, destination.y);
-			}
-			for (var i = 0, l = stops.length; i < l; i++) {
-				var stop = stops[i];
-				canvasGradient.addColorStop(stop._offset || i / (l - 1),
-						stop._color.toCanvasStyle());
-			}
-			return this._canvasStyle = canvasGradient;
-		},
-
-		transform: function(matrix) {
-			if (this._type === 'gradient') {
-				var components = this._components;
-				for (var i = 1, l = components.length; i < l; i++) {
-					var point = components[i];
-					matrix._transformPoint(point, point, true);
-				}
-				this._changed();
-			}
-		},
-
-		statics: {
-			_types: types,
-
-			random: function() {
-				var random = Math.random;
-				return new Color(random(), random(), random());
-			}
-		}
-	});
-},
-new function() {
-	var operators = {
-		add: function(a, b) {
-			return a + b;
-		},
-
-		subtract: function(a, b) {
-			return a - b;
-		},
-
-		multiply: function(a, b) {
-			return a * b;
-		},
-
-		divide: function(a, b) {
-			return a / b;
-		}
-	};
-
-	return Base.each(operators, function(operator, name) {
-		this[name] = function(color) {
-			color = Color.read(arguments);
-			var type = this._type,
-				components1 = this._components,
-				components2 = color._convert(type);
-			for (var i = 0, l = components1.length; i < l; i++)
-				components2[i] = operator(components1[i], components2[i]);
-			return new Color(type, components2,
-					this._alpha != null
-							? operator(this._alpha, color.getAlpha())
-							: null);
-		};
-	}, {
-	});
-});
-
-var Gradient = Base.extend({
-	_class: 'Gradient',
-
-	initialize: function Gradient(stops, radial) {
-		this._id = UID.get();
-		if (stops && this._set(stops))
-			stops = radial = null;
-		if (!this._stops)
-			this.setStops(stops || ['white', 'black']);
-		if (this._radial == null) {
-			this.setRadial(typeof radial === 'string' && radial === 'radial'
-					|| radial || false);
-		}
-	},
-
-	_serialize: function(options, dictionary) {
-		return dictionary.add(this, function() {
-			return Base.serialize([this._stops, this._radial],
-					options, true, dictionary);
-		});
-	},
-
-	_changed: function() {
-		for (var i = 0, l = this._owners && this._owners.length; i < l; i++) {
-			this._owners[i]._changed();
-		}
-	},
-
-	_addOwner: function(color) {
-		if (!this._owners)
-			this._owners = [];
-		this._owners.push(color);
-	},
-
-	_removeOwner: function(color) {
-		var index = this._owners ? this._owners.indexOf(color) : -1;
-		if (index != -1) {
-			this._owners.splice(index, 1);
-			if (this._owners.length === 0)
-				this._owners = undefined;
-		}
-	},
-
-	clone: function() {
-		var stops = [];
-		for (var i = 0, l = this._stops.length; i < l; i++) {
-			stops[i] = this._stops[i].clone();
-		}
-		return new Gradient(stops, this._radial);
-	},
-
-	getStops: function() {
-		return this._stops;
-	},
-
-	setStops: function(stops) {
-		if (stops.length < 2) {
-			throw new Error(
-					'Gradient stop list needs to contain at least two stops.');
-		}
-		var _stops = this._stops;
-		if (_stops) {
-			for (var i = 0, l = _stops.length; i < l; i++)
-				_stops[i]._owner = undefined;
-		}
-		_stops = this._stops = GradientStop.readAll(stops, 0, { clone: true });
-		for (var i = 0, l = _stops.length; i < l; i++)
-			_stops[i]._owner = this;
-		this._changed();
-	},
-
-	getRadial: function() {
-		return this._radial;
-	},
-
-	setRadial: function(radial) {
-		this._radial = radial;
-		this._changed();
-	},
-
-	equals: function(gradient) {
-		if (gradient === this)
-			return true;
-		if (gradient && this._class === gradient._class) {
-			var stops1 = this._stops,
-				stops2 = gradient._stops,
-				length = stops1.length;
-			if (length === stops2.length) {
-				for (var i = 0; i < length; i++) {
-					if (!stops1[i].equals(stops2[i]))
-						return false;
-				}
-				return true;
-			}
-		}
-		return false;
-	}
-});
-
-var GradientStop = Base.extend({
-	_class: 'GradientStop',
-
-	initialize: function GradientStop(arg0, arg1) {
-		var color = arg0,
-			offset = arg1;
-		if (typeof arg0 === 'object' && arg1 === undefined) {
-			if (Array.isArray(arg0) && typeof arg0[0] !== 'number') {
-				color = arg0[0];
-				offset = arg0[1];
-			} else if ('color' in arg0 || 'offset' in arg0
-					|| 'rampPoint' in arg0) {
-				color = arg0.color;
-				offset = arg0.offset || arg0.rampPoint || 0;
-			}
-		}
-		this.setColor(color);
-		this.setOffset(offset);
-	},
-
-	clone: function() {
-		return new GradientStop(this._color.clone(), this._offset);
-	},
-
-	_serialize: function(options, dictionary) {
-		var color = this._color,
-			offset = this._offset;
-		return Base.serialize(offset == null ? [color] : [color, offset],
-				options, true, dictionary);
-	},
-
-	_changed: function() {
-		if (this._owner)
-			this._owner._changed(65);
-	},
-
-	getOffset: function() {
-		return this._offset;
-	},
-
-	setOffset: function(offset) {
-		this._offset = offset;
-		this._changed();
-	},
-
-	getRampPoint: '#getOffset',
-	setRampPoint: '#setOffset',
-
-	getColor: function() {
-		return this._color;
-	},
-
-	setColor: function() {
-		var color = Color.read(arguments, 0, { clone: true });
-		if (color)
-			color._owner = this;
-		this._color = color;
-		this._changed();
-	},
-
-	equals: function(stop) {
-		return stop === this || stop && this._class === stop._class
-				&& this._color.equals(stop._color)
-				&& this._offset == stop._offset
-				|| false;
-	}
-});
-
-var Style = Base.extend(new function() {
-	var itemDefaults = {
-		fillColor: null,
-		fillRule: 'nonzero',
-		strokeColor: null,
-		strokeWidth: 1,
-		strokeCap: 'butt',
-		strokeJoin: 'miter',
-		strokeScaling: true,
-		miterLimit: 10,
-		dashOffset: 0,
-		dashArray: [],
-		shadowColor: null,
-		shadowBlur: 0,
-		shadowOffset: new Point(),
-		selectedColor: null
-	},
-	groupDefaults = Base.set({}, itemDefaults, {
-		fontFamily: 'sans-serif',
-		fontWeight: 'normal',
-		fontSize: 12,
-		leading: null,
-		justification: 'left'
-	}),
-	textDefaults = Base.set({}, groupDefaults, {
-		fillColor: new Color()
-	}),
-	flags = {
-		strokeWidth: 97,
-		strokeCap: 97,
-		strokeJoin: 97,
-		strokeScaling: 105,
-		miterLimit: 97,
-		fontFamily: 9,
-		fontWeight: 9,
-		fontSize: 9,
-		font: 9,
-		leading: 9,
-		justification: 9
-	},
-	item = {
-		beans: true
-	},
-	fields = {
-		_class: 'Style',
-		beans: true,
-
-		initialize: function Style(style, owner, project) {
-			this._values = {};
-			this._owner = owner;
-			this._project = owner && owner._project || project || paper.project;
-			this._defaults = !owner || owner instanceof Group ? groupDefaults
-					: owner instanceof TextItem ? textDefaults
-					: itemDefaults;
-			if (style)
-				this.set(style);
-		}
-	};
-
-	Base.each(groupDefaults, function(value, key) {
-		var isColor = /Color$/.test(key),
-			isPoint = key === 'shadowOffset',
-			part = Base.capitalize(key),
-			flag = flags[key],
-			set = 'set' + part,
-			get = 'get' + part;
-
-		fields[set] = function(value) {
-			var owner = this._owner,
-				children = owner && owner._children;
-			if (children && children.length > 0
-					&& !(owner instanceof CompoundPath)) {
-				for (var i = 0, l = children.length; i < l; i++)
-					children[i]._style[set](value);
-			} else if (key in this._defaults) {
-				var old = this._values[key];
-				if (old !== value) {
-					if (isColor) {
-						if (old && old._owner !== undefined)
-							old._owner = undefined;
-						if (value && value.constructor === Color) {
-							if (value._owner)
-								value = value.clone();
-							value._owner = owner;
-						}
-					}
-					this._values[key] = value;
-					if (owner)
-						owner._changed(flag || 65);
-				}
-			}
-		};
-
-		fields[get] = function(_dontMerge) {
-			var owner = this._owner,
-				children = owner && owner._children,
-				value;
-			if (key in this._defaults && (!children || children.length === 0
-					|| _dontMerge || owner instanceof CompoundPath)) {
-				var value = this._values[key];
-				if (value === undefined) {
-					value = this._defaults[key];
-					if (value && value.clone)
-						value = value.clone();
-				} else {
-					var ctor = isColor ? Color : isPoint ? Point : null;
-					if (ctor && !(value && value.constructor === ctor)) {
-						this._values[key] = value = ctor.read([value], 0,
-								{ readNull: true, clone: true });
-						if (value && isColor)
-							value._owner = owner;
-					}
-				}
-			} else if (children) {
-				for (var i = 0, l = children.length; i < l; i++) {
-					var childValue = children[i]._style[get]();
-					if (i === 0) {
-						value = childValue;
-					} else if (!Base.equals(value, childValue)) {
-						return undefined;
-					}
-				}
-			}
-			return value;
-		};
-
-		item[get] = function(_dontMerge) {
-			return this._style[get](_dontMerge);
-		};
-
-		item[set] = function(value) {
-			this._style[set](value);
-		};
-	});
-
-	Base.each({
-		Font: 'FontFamily',
-		WindingRule: 'FillRule'
-	}, function(value, key) {
-		var get = 'get' + key,
-			set = 'set' + key;
-		fields[get] = item[get] = '#get' + value;
-		fields[set] = item[set] = '#set' + value;
-	});
-
-	Item.inject(item);
-	return fields;
-}, {
-	set: function(style) {
-		var isStyle = style instanceof Style,
-			values = isStyle ? style._values : style;
-		if (values) {
-			for (var key in values) {
-				if (key in this._defaults) {
-					var value = values[key];
-					this[key] = value && isStyle && value.clone
-							? value.clone() : value;
-				}
-			}
-		}
-	},
-
-	equals: function(style) {
-		return style === this || style && this._class === style._class
-				&& Base.equals(this._values, style._values)
-				|| false;
-	},
-
-	hasFill: function() {
-		var color = this.getFillColor();
-		return !!color && color.alpha > 0;
-	},
-
-	hasStroke: function() {
-		var color = this.getStrokeColor();
-		return !!color && color.alpha > 0 && this.getStrokeWidth() > 0;
-	},
-
-	hasShadow: function() {
-		var color = this.getShadowColor();
-		return !!color && color.alpha > 0 && (this.getShadowBlur() > 0
-				|| !this.getShadowOffset().isZero());
-	},
-
-	getView: function() {
-		return this._project._view;
-	},
-
-	getFontStyle: function() {
-		var fontSize = this.getFontSize();
-		return this.getFontWeight()
-				+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')
-				+ this.getFontFamily();
-	},
-
-	getFont: '#getFontFamily',
-	setFont: '#setFontFamily',
-
-	getLeading: function getLeading() {
-		var leading = getLeading.base.call(this),
-			fontSize = this.getFontSize();
-		if (/pt|em|%|px/.test(fontSize))
-			fontSize = this.getView().getPixelSize(fontSize);
-		return leading != null ? leading : fontSize * 1.2;
-	}
-
-});
-
-var DomElement = new function() {
-	function handlePrefix(el, name, set, value) {
-		var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],
-			suffix = name[0].toUpperCase() + name.substring(1);
-		for (var i = 0; i < 6; i++) {
-			var prefix = prefixes[i],
-				key = prefix ? prefix + suffix : name;
-			if (key in el) {
-				if (set) {
-					el[key] = value;
-				} else {
-					return el[key];
-				}
-				break;
-			}
-		}
-	}
-
-	return {
-		getStyles: function(el) {
-			var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
-				view = doc && doc.defaultView;
-			return view && view.getComputedStyle(el, '');
-		},
-
-		getBounds: function(el, viewport) {
-			var doc = el.ownerDocument,
-				body = doc.body,
-				html = doc.documentElement,
-				rect;
-			try {
-				rect = el.getBoundingClientRect();
-			} catch (e) {
-				rect = { left: 0, top: 0, width: 0, height: 0 };
-			}
-			var x = rect.left - (html.clientLeft || body.clientLeft || 0),
-				y = rect.top - (html.clientTop || body.clientTop || 0);
-			if (!viewport) {
-				var view = doc.defaultView;
-				x += view.pageXOffset || html.scrollLeft || body.scrollLeft;
-				y += view.pageYOffset || html.scrollTop || body.scrollTop;
-			}
-			return new Rectangle(x, y, rect.width, rect.height);
-		},
-
-		getViewportBounds: function(el) {
-			var doc = el.ownerDocument,
-				view = doc.defaultView,
-				html = doc.documentElement;
-			return new Rectangle(0, 0,
-				view.innerWidth || html.clientWidth,
-				view.innerHeight || html.clientHeight
-			);
-		},
-
-		getOffset: function(el, viewport) {
-			return DomElement.getBounds(el, viewport).getPoint();
-		},
-
-		getSize: function(el) {
-			return DomElement.getBounds(el, true).getSize();
-		},
-
-		isInvisible: function(el) {
-			return DomElement.getSize(el).equals(new Size(0, 0));
-		},
-
-		isInView: function(el) {
-			return !DomElement.isInvisible(el)
-					&& DomElement.getViewportBounds(el).intersects(
-						DomElement.getBounds(el, true));
-		},
-
-		isInserted: function(el) {
-			return document.body.contains(el);
-		},
-
-		getPrefixed: function(el, name) {
-			return el && handlePrefix(el, name);
-		},
-
-		setPrefixed: function(el, name, value) {
-			if (typeof name === 'object') {
-				for (var key in name)
-					handlePrefix(el, key, true, name[key]);
-			} else {
-				handlePrefix(el, name, true, value);
-			}
-		}
-	};
-};
-
-var DomEvent = {
-	add: function(el, events) {
-		if (el) {
-			for (var type in events) {
-				var func = events[type],
-					parts = type.split(/[\s,]+/g);
-				for (var i = 0, l = parts.length; i < l; i++)
-					el.addEventListener(parts[i], func, false);
-			}
-		}
-	},
-
-	remove: function(el, events) {
-		if (el) {
-			for (var type in events) {
-				var func = events[type],
-					parts = type.split(/[\s,]+/g);
-				for (var i = 0, l = parts.length; i < l; i++)
-					el.removeEventListener(parts[i], func, false);
-			}
-		}
-	},
-
-	getPoint: function(event) {
-		var pos = event.targetTouches
-				? event.targetTouches.length
-					? event.targetTouches[0]
-					: event.changedTouches[0]
-				: event;
-		return new Point(
-			pos.pageX || pos.clientX + document.documentElement.scrollLeft,
-			pos.pageY || pos.clientY + document.documentElement.scrollTop
-		);
-	},
-
-	getTarget: function(event) {
-		return event.target || event.srcElement;
-	},
-
-	getRelatedTarget: function(event) {
-		return event.relatedTarget || event.toElement;
-	},
-
-	getOffset: function(event, target) {
-		return DomEvent.getPoint(event).subtract(DomElement.getOffset(
-				target || DomEvent.getTarget(event)));
-	}
-};
-
-DomEvent.requestAnimationFrame = new function() {
-	var nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),
-		requested = false,
-		callbacks = [],
-		timer;
-
-	function handleCallbacks() {
-		var functions = callbacks;
-		callbacks = [];
-		for (var i = 0, l = functions.length; i < l; i++)
-			functions[i]();
-		requested = nativeRequest && callbacks.length;
-		if (requested)
-			nativeRequest(handleCallbacks);
-	}
-
-	return function(callback) {
-		callbacks.push(callback);
-		if (nativeRequest) {
-			if (!requested) {
-				nativeRequest(handleCallbacks);
-				requested = true;
-			}
-		} else if (!timer) {
-			timer = setInterval(handleCallbacks, 1000 / 60);
-		}
-	};
-};
-
-var View = Base.extend(Emitter, {
-	_class: 'View',
-
-	initialize: function View(project, element) {
-
-		function getSize(name) {
-			return element[name] || parseInt(element.getAttribute(name), 10);
-		}
-
-		function getCanvasSize() {
-			var size = DomElement.getSize(element);
-			return size.isNaN() || size.isZero()
-					? new Size(getSize('width'), getSize('height'))
-					: size;
-		}
-
-		var size;
-		if (window && element) {
-			this._id = element.getAttribute('id');
-			if (this._id == null)
-				element.setAttribute('id', this._id = 'view-' + View._id++);
-			DomEvent.add(element, this._viewEvents);
-			var none = 'none';
-			DomElement.setPrefixed(element.style, {
-				userDrag: none,
-				userSelect: none,
-				touchCallout: none,
-				contentZooming: none,
-				tapHighlightColor: 'rgba(0,0,0,0)'
-			});
-
-			if (PaperScope.hasAttribute(element, 'resize')) {
-				var that = this;
-				DomEvent.add(window, this._windowEvents = {
-					resize: function() {
-						that.setViewSize(getCanvasSize());
-					}
-				});
-			}
-
-			size = getCanvasSize();
-
-			if (PaperScope.hasAttribute(element, 'stats')
-					&& typeof Stats !== 'undefined') {
-				this._stats = new Stats();
-				var stats = this._stats.domElement,
-					style = stats.style,
-					offset = DomElement.getOffset(element);
-				style.position = 'absolute';
-				style.left = offset.x + 'px';
-				style.top = offset.y + 'px';
-				document.body.appendChild(stats);
-			}
-		} else {
-			size = new Size(element);
-			element = null;
-		}
-		this._project = project;
-		this._scope = project._scope;
-		this._element = element;
-		if (!this._pixelRatio)
-			this._pixelRatio = window && window.devicePixelRatio || 1;
-		this._setElementSize(size.width, size.height);
-		this._viewSize = size;
-		View._views.push(this);
-		View._viewsById[this._id] = this;
-		(this._matrix = new Matrix())._owner = this;
-		this._zoom = 1;
-		if (!View._focused)
-			View._focused = this;
-		this._frameItems = {};
-		this._frameItemCount = 0;
-		this._itemEvents = { native: {}, virtual: {} };
-		this._autoUpdate = !paper.agent.node;
-		this._needsUpdate = false;
-	},
-
-	remove: function() {
-		if (!this._project)
-			return false;
-		if (View._focused === this)
-			View._focused = null;
-		View._views.splice(View._views.indexOf(this), 1);
-		delete View._viewsById[this._id];
-		var project = this._project;
-		if (project._view === this)
-			project._view = null;
-		DomEvent.remove(this._element, this._viewEvents);
-		DomEvent.remove(window, this._windowEvents);
-		this._element = this._project = null;
-		this.off('frame');
-		this._animate = false;
-		this._frameItems = {};
-		return true;
-	},
-
-	_events: Base.each(
-		Item._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),
-		function(name) {
-			this[name] = {};
-		}, {
-			onFrame: {
-				install: function() {
-					this.play();
-				},
-
-				uninstall: function() {
-					this.pause();
-				}
-			}
-		}
-	),
-
-	_animate: false,
-	_time: 0,
-	_count: 0,
-
-	getAutoUpdate: function() {
-		return this._autoUpdate;
-	},
-
-	setAutoUpdate: function(autoUpdate) {
-		this._autoUpdate = autoUpdate;
-		if (autoUpdate)
-			this.requestUpdate();
-	},
-
-	update: function() {
-	},
-
-	draw: function() {
-		this.update();
-	},
-
-	requestUpdate: function() {
-		if (!this._requested) {
-			var that = this;
-			DomEvent.requestAnimationFrame(function() {
-				that._requested = false;
-				if (that._animate) {
-					that.requestUpdate();
-					var element = that._element;
-					if ((!DomElement.getPrefixed(document, 'hidden')
-							|| PaperScope.getAttribute(element, 'keepalive')
-								=== 'true') && DomElement.isInView(element)) {
-						that._handleFrame();
-					}
-				}
-				if (that._autoUpdate)
-					that.update();
-			});
-			this._requested = true;
-		}
-	},
-
-	play: function() {
-		this._animate = true;
-		this.requestUpdate();
-	},
-
-	pause: function() {
-		this._animate = false;
-	},
-
-	_handleFrame: function() {
-		paper = this._scope;
-		var now = Date.now() / 1000,
-			delta = this._last ? now - this._last : 0;
-		this._last = now;
-		this.emit('frame', new Base({
-			delta: delta,
-			time: this._time += delta,
-			count: this._count++
-		}));
-		if (this._stats)
-			this._stats.update();
-	},
-
-	_animateItem: function(item, animate) {
-		var items = this._frameItems;
-		if (animate) {
-			items[item._id] = {
-				item: item,
-				time: 0,
-				count: 0
-			};
-			if (++this._frameItemCount === 1)
-				this.on('frame', this._handleFrameItems);
-		} else {
-			delete items[item._id];
-			if (--this._frameItemCount === 0) {
-				this.off('frame', this._handleFrameItems);
-			}
-		}
-	},
-
-	_handleFrameItems: function(event) {
-		for (var i in this._frameItems) {
-			var entry = this._frameItems[i];
-			entry.item.emit('frame', new Base(event, {
-				time: entry.time += event.delta,
-				count: entry.count++
-			}));
-		}
-	},
-
-	_changed: function() {
-		this._project._changed(2049);
-		this._bounds = null;
-	},
-
-	getElement: function() {
-		return this._element;
-	},
-
-	getPixelRatio: function() {
-		return this._pixelRatio;
-	},
-
-	getResolution: function() {
-		return this._pixelRatio * 72;
-	},
-
-	getViewSize: function() {
-		var size = this._viewSize;
-		return new LinkedSize(size.width, size.height, this, 'setViewSize');
-	},
-
-	setViewSize: function() {
-		var size = Size.read(arguments),
-			width = size.width,
-			height = size.height,
-			delta = size.subtract(this._viewSize);
-		if (delta.isZero())
-			return;
-		this._setElementSize(width, height);
-		this._viewSize.set(width, height);
-		this.emit('resize', {
-			size: size,
-			delta: delta
-		});
-		this._changed();
-		if (this._autoUpdate)
-			this.requestUpdate();
-	},
-
-	_setElementSize: function(width, height) {
-		var element = this._element;
-		if (element) {
-			if (element.width !== width)
-				element.width = width;
-			if (element.height !== height)
-				element.height = height;
-		}
-	},
-
-	getBounds: function() {
-		if (!this._bounds)
-			this._bounds = this._matrix.inverted()._transformBounds(
-					new Rectangle(new Point(), this._viewSize));
-		return this._bounds;
-	},
-
-	getSize: function() {
-		return this.getBounds().getSize();
-	},
-
-	getCenter: function() {
-		return this.getBounds().getCenter();
-	},
-
-	setCenter: function() {
-		var center = Point.read(arguments);
-		this.translate(this.getCenter().subtract(center));
-	},
-
-	getZoom: function() {
-		return this._zoom;
-	},
-
-	setZoom: function(zoom) {
-		this.transform(new Matrix().scale(zoom / this._zoom,
-			this.getCenter()));
-		this._zoom = zoom;
-	},
-
-	getMatrix: function() {
-		return this._matrix;
-	},
-
-	setMatrix: function() {
-		var matrix = this._matrix;
-		matrix.initialize.apply(matrix, arguments);
-	},
-
-	isVisible: function() {
-		return DomElement.isInView(this._element);
-	},
-
-	isInserted: function() {
-		return DomElement.isInserted(this._element);
-	},
-
-	getPixelSize: function(size) {
-		var element = this._element,
-			pixels;
-		if (element) {
-			var parent = element.parentNode,
-				temp = document.createElement('div');
-			temp.style.fontSize = size;
-			parent.appendChild(temp);
-			pixels = parseFloat(DomElement.getStyles(temp).fontSize);
-			parent.removeChild(temp);
-		} else {
-			pixels = parseFloat(pixels);
-		}
-		return pixels;
-	},
-
-	getTextWidth: function(font, lines) {
-		return 0;
-	}
-}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
-	var rotate = key === 'rotate';
-	this[key] = function() {
-		var value = (rotate ? Base : Point).read(arguments),
-			center = Point.read(arguments, 0, { readNull: true });
-		return this.transform(new Matrix()[key](value,
-				center || this.getCenter(true)));
-	};
-}, {
-	translate: function() {
-		var mx = new Matrix();
-		return this.transform(mx.translate.apply(mx, arguments));
-	},
-
-	transform: function(matrix) {
-		this._matrix.append(matrix);
-	},
-
-	scrollBy: function() {
-		this.translate(Point.read(arguments).negate());
-	}
-}), {
-
-	projectToView: function() {
-		return this._matrix._transformPoint(Point.read(arguments));
-	},
-
-	viewToProject: function() {
-		return this._matrix._inverseTransform(Point.read(arguments));
-	},
-
-	getEventPoint: function(event) {
-		return this.viewToProject(DomEvent.getOffset(event, this._element));
-	},
-
-}, {
-	statics: {
-		_views: [],
-		_viewsById: {},
-		_id: 0,
-
-		create: function(project, element) {
-			if (document && typeof element === 'string')
-				element = document.getElementById(element);
-			var ctor = window ? CanvasView : View;
-			return new ctor(project, element);
-		}
-	}
-},
-new function() {
-	if (!window)
-		return;
-	var prevFocus,
-		tempFocus,
-		dragging = false,
-		mouseDown = false;
-
-	function getView(event) {
-		var target = DomEvent.getTarget(event);
-		return target.getAttribute && View._viewsById[
-				target.getAttribute('id')];
-	}
-
-	function updateFocus() {
-		var view = View._focused;
-		if (!view || !view.isVisible()) {
-			for (var i = 0, l = View._views.length; i < l; i++) {
-				if ((view = View._views[i]).isVisible()) {
-					View._focused = tempFocus = view;
-					break;
-				}
-			}
-		}
-	}
-
-	function handleMouseMove(view, event, point) {
-		view._handleMouseEvent('mousemove', event, point);
-	}
-
-	var navigator = window.navigator,
-		mousedown, mousemove, mouseup;
-	if (navigator.pointerEnabled || navigator.msPointerEnabled) {
-		mousedown = 'pointerdown MSPointerDown';
-		mousemove = 'pointermove MSPointerMove';
-		mouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';
-	} else {
-		mousedown = 'touchstart';
-		mousemove = 'touchmove';
-		mouseup = 'touchend touchcancel';
-		if (!('ontouchstart' in window && navigator.userAgent.match(
-				/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {
-			mousedown += ' mousedown';
-			mousemove += ' mousemove';
-			mouseup += ' mouseup';
-		}
-	}
-
-	var viewEvents = {},
-		docEvents = {
-			mouseout: function(event) {
-				var view = View._focused,
-					target = DomEvent.getRelatedTarget(event);
-				if (view && (!target || target.nodeName === 'HTML')) {
-					var offset = DomEvent.getOffset(event, view._element),
-						x = offset.x,
-						abs = Math.abs,
-						ax = abs(x),
-						max = 1 << 25,
-						diff = ax - max;
-					offset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;
-					handleMouseMove(view, event, view.viewToProject(offset));
-				}
-			},
-
-			scroll: updateFocus
-		};
-
-	viewEvents[mousedown] = function(event) {
-		var view = View._focused = getView(event);
-		if (!dragging) {
-			dragging = true;
-			view._handleMouseEvent('mousedown', event);
-		}
-	};
-
-	docEvents[mousemove] = function(event) {
-		var view = View._focused;
-		if (!mouseDown) {
-			var target = getView(event);
-			if (target) {
-				if (view !== target) {
-					if (view)
-						handleMouseMove(view, event);
-					if (!prevFocus)
-						prevFocus = view;
-					view = View._focused = tempFocus = target;
-				}
-			} else if (tempFocus && tempFocus === view) {
-				if (prevFocus && !prevFocus.isInserted())
-					prevFocus = null;
-				view = View._focused = prevFocus;
-				prevFocus = null;
-				updateFocus();
-			}
-		}
-		if (view)
-			handleMouseMove(view, event);
-	};
-
-	docEvents[mousedown] = function() {
-		mouseDown = true;
-	};
-
-	docEvents[mouseup] = function(event) {
-		var view = View._focused;
-		if (view && dragging)
-			view._handleMouseEvent('mouseup', event);
-		mouseDown = dragging = false;
-	};
-
-	DomEvent.add(document, docEvents);
-
-	DomEvent.add(window, {
-		load: updateFocus
-	});
-
-	var called = false,
-		prevented = false,
-		fallbacks = {
-			doubleclick: 'click',
-			mousedrag: 'mousemove'
-		},
-		wasInView = false,
-		overView,
-		downPoint,
-		lastPoint,
-		downItem,
-		overItem,
-		dragItem,
-		clickItem,
-		clickTime,
-		dblClick;
-
-	function emitMouseEvent(obj, target, type, event, point, prevPoint,
-			stopItem) {
-		var stopped = false,
-			mouseEvent;
-
-		function emit(obj, type) {
-			if (obj.responds(type)) {
-				if (!mouseEvent) {
-					mouseEvent = new MouseEvent(type, event, point,
-							target || obj,
-							prevPoint ? point.subtract(prevPoint) : null);
-				}
-				if (obj.emit(type, mouseEvent)) {
-					called = true;
-					if (mouseEvent.prevented)
-						prevented = true;
-					if (mouseEvent.stopped)
-						return stopped = true;
-				}
-			} else {
-				var fallback = fallbacks[type];
-				if (fallback)
-					return emit(obj, fallback);
-			}
-		}
-
-		while (obj && obj !== stopItem) {
-			if (emit(obj, type))
-				break;
-			obj = obj._parent;
-		}
-		return stopped;
-	}
-
-	function emitMouseEvents(view, hitItem, type, event, point, prevPoint) {
-		view._project.removeOn(type);
-		prevented = called = false;
-		return (dragItem && emitMouseEvent(dragItem, null, type, event,
-					point, prevPoint)
-			|| hitItem && hitItem !== dragItem
-				&& !hitItem.isDescendant(dragItem)
-				&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
-					point, prevPoint, dragItem)
-			|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
-					point, prevPoint));
-	}
-
-	var itemEventsMap = {
-		mousedown: {
-			mousedown: 1,
-			mousedrag: 1,
-			click: 1,
-			doubleclick: 1
-		},
-		mouseup: {
-			mouseup: 1,
-			mousedrag: 1,
-			click: 1,
-			doubleclick: 1
-		},
-		mousemove: {
-			mousedrag: 1,
-			mousemove: 1,
-			mouseenter: 1,
-			mouseleave: 1
-		}
-	};
-
-	return {
-		_viewEvents: viewEvents,
-
-		_handleMouseEvent: function(type, event, point) {
-			var itemEvents = this._itemEvents,
-				hitItems = itemEvents.native[type],
-				nativeMove = type === 'mousemove',
-				tool = this._scope.tool,
-				view = this;
-
-			function responds(type) {
-				return itemEvents.virtual[type] || view.responds(type)
-						|| tool && tool.responds(type);
-			}
-
-			if (nativeMove && dragging && responds('mousedrag'))
-				type = 'mousedrag';
-			if (!point)
-				point = this.getEventPoint(event);
-
-			var inView = this.getBounds().contains(point),
-				hit = hitItems && inView && view._project.hitTest(point, {
-					tolerance: 0,
-					fill: true,
-					stroke: true
-				}),
-				hitItem = hit && hit.item || null,
-				handle = false,
-				mouse = {};
-			mouse[type.substr(5)] = true;
-
-			if (hitItems && hitItem !== overItem) {
-				if (overItem) {
-					emitMouseEvent(overItem, null, 'mouseleave', event, point);
-				}
-				if (hitItem) {
-					emitMouseEvent(hitItem, null, 'mouseenter', event, point);
-				}
-				overItem = hitItem;
-			}
-			if (wasInView ^ inView) {
-				emitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',
-						event, point);
-				overView = inView ? this : null;
-				handle = true;
-			}
-			if ((inView || mouse.drag) && !point.equals(lastPoint)) {
-				emitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',
-						event, point, lastPoint);
-				handle = true;
-			}
-			wasInView = inView;
-			if (mouse.down && inView || mouse.up && downPoint) {
-				emitMouseEvents(this, hitItem, type, event, point, downPoint);
-				if (mouse.down) {
-					dblClick = hitItem === clickItem
-						&& (Date.now() - clickTime < 300);
-					downItem = clickItem = hitItem;
-					dragItem = !prevented && hitItem;
-					downPoint = point;
-				} else if (mouse.up) {
-					if (!prevented && hitItem === downItem) {
-						clickTime = Date.now();
-						emitMouseEvents(this, hitItem, dblClick ? 'doubleclick'
-								: 'click', event, point, downPoint);
-						dblClick = false;
-					}
-					downItem = dragItem = null;
-				}
-				wasInView = false;
-				handle = true;
-			}
-			lastPoint = point;
-			if (handle && tool) {
-				called = tool._handleMouseEvent(type, event, point, mouse)
-					|| called;
-			}
-
-			if (called && !mouse.move || mouse.down && responds('mouseup'))
-				event.preventDefault();
-		},
-
-		_handleKeyEvent: function(type, event, key, character) {
-			var scope = this._scope,
-				tool = scope.tool,
-				keyEvent;
-
-			function emit(obj) {
-				if (obj.responds(type)) {
-					paper = scope;
-					obj.emit(type, keyEvent = keyEvent
-							|| new KeyEvent(type, event, key, character));
-				}
-			}
-
-			if (this.isVisible()) {
-				emit(this);
-				if (tool && tool.responds(type))
-					emit(tool);
-			}
-		},
-
-		_countItemEvent: function(type, sign) {
-			var itemEvents = this._itemEvents,
-				native = itemEvents.native,
-				virtual = itemEvents.virtual;
-			for (var key in itemEventsMap) {
-				native[key] = (native[key] || 0)
-						+ (itemEventsMap[key][type] || 0) * sign;
-			}
-			virtual[type] = (virtual[type] || 0) + sign;
-		},
-
-		statics: {
-			updateFocus: updateFocus
-		}
-	};
-});
-
-var CanvasView = View.extend({
-	_class: 'CanvasView',
-
-	initialize: function CanvasView(project, canvas) {
-		if (!(canvas instanceof window.HTMLCanvasElement)) {
-			var size = Size.read(arguments, 1);
-			if (size.isZero())
-				throw new Error(
-						'Cannot create CanvasView with the provided argument: '
-						+ [].slice.call(arguments, 1));
-			canvas = CanvasProvider.getCanvas(size);
-		}
-		var ctx = this._context = canvas.getContext('2d');
-		ctx.save();
-		this._pixelRatio = 1;
-		if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {
-			var deviceRatio = window.devicePixelRatio || 1,
-				backingStoreRatio = DomElement.getPrefixed(ctx,
-						'backingStorePixelRatio') || 1;
-			this._pixelRatio = deviceRatio / backingStoreRatio;
-		}
-		View.call(this, project, canvas);
-		this._needsUpdate = true;
-	},
-
-	remove: function remove() {
-		this._context.restore();
-		return remove.base.call(this);
-	},
-
-	_setElementSize: function _setElementSize(width, height) {
-		var pixelRatio = this._pixelRatio;
-		_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);
-		if (pixelRatio !== 1) {
-			var element = this._element,
-				ctx = this._context;
-			if (!PaperScope.hasAttribute(element, 'resize')) {
-				var style = element.style;
-				style.width = width + 'px';
-				style.height = height + 'px';
-			}
-			ctx.restore();
-			ctx.save();
-			ctx.scale(pixelRatio, pixelRatio);
-		}
-	},
-
-	getPixelSize: function getPixelSize(size) {
-		var agent = paper.agent,
-			pixels;
-		if (agent && agent.firefox) {
-			pixels = getPixelSize.base.call(this, size);
-		} else {
-			var ctx = this._context,
-				prevFont = ctx.font;
-			ctx.font = size + ' serif';
-			pixels = parseFloat(ctx.font);
-			ctx.font = prevFont;
-		}
-		return pixels;
-	},
-
-	getTextWidth: function(font, lines) {
-		var ctx = this._context,
-			prevFont = ctx.font,
-			width = 0;
-		ctx.font = font;
-		for (var i = 0, l = lines.length; i < l; i++)
-			width = Math.max(width, ctx.measureText(lines[i]).width);
-		ctx.font = prevFont;
-		return width;
-	},
-
-	update: function() {
-		if (!this._needsUpdate)
-			return false;
-		var project = this._project,
-			ctx = this._context,
-			size = this._viewSize;
-		ctx.clearRect(0, 0, size.width + 1, size.height + 1);
-		if (project)
-			project.draw(ctx, this._matrix, this._pixelRatio);
-		this._needsUpdate = false;
-		return true;
-	}
-});
-
-var Event = Base.extend({
-	_class: 'Event',
-
-	initialize: function Event(event) {
-		this.event = event;
-		this.type = event && event.type;
-	},
-
-	prevented: false,
-	stopped: false,
-
-	preventDefault: function() {
-		this.prevented = true;
-		this.event.preventDefault();
-	},
-
-	stopPropagation: function() {
-		this.stopped = true;
-		this.event.stopPropagation();
-	},
-
-	stop: function() {
-		this.stopPropagation();
-		this.preventDefault();
-	},
-
-	getTimeStamp: function() {
-		return this.event.timeStamp;
-	},
-
-	getModifiers: function() {
-		return Key.modifiers;
-	}
-});
-
-var KeyEvent = Event.extend({
-	_class: 'KeyEvent',
-
-	initialize: function KeyEvent(type, event, key, character) {
-		this.type = type;
-		this.event = event;
-		this.key = key;
-		this.character = character;
-	},
-
-	toString: function() {
-		return "{ type: '" + this.type
-				+ "', key: '" + this.key
-				+ "', character: '" + this.character
-				+ "', modifiers: " + this.getModifiers()
-				+ " }";
-	}
-});
-
-var Key = new function() {
-	var keyLookup = {
-			'\t': 'tab',
-			' ': 'space',
-			'\b': 'backspace',
-			'\x7f': 'delete',
-			'Spacebar': 'space',
-			'Del': 'delete',
-			'Win': 'meta',
-			'Esc': 'escape'
-		},
-
-		charLookup = {
-			'tab': '\t',
-			'space': ' ',
-			'enter': '\r'
-		},
-
-		keyMap = {},
-		charMap = {},
-		metaFixMap,
-		downKey,
-
-		modifiers = new Base({
-			shift: false,
-			control: false,
-			alt: false,
-			meta: false,
-			capsLock: false,
-			space: false
-		}).inject({
-			option: {
-				get: function() {
-					return this.alt;
-				}
-			},
-
-			command: {
-				get: function() {
-					var agent = paper && paper.agent;
-					return agent && agent.mac ? this.meta : this.control;
-				}
-			}
-		});
-
-	function getKey(event) {
-		var key = event.key || event.keyIdentifier;
-		key = /^U\+/.test(key)
-				? String.fromCharCode(parseInt(key.substr(2), 16))
-				: /^Arrow[A-Z]/.test(key) ? key.substr(5)
-				: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
-				: key;
-		return keyLookup[key] ||
-				(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());
-	}
-
-	function handleKey(down, key, character, event) {
-		var type = down ? 'keydown' : 'keyup',
-			view = View._focused,
-			name;
-		keyMap[key] = down;
-		if (down) {
-			charMap[key] = character;
-		} else {
-			delete charMap[key];
-		}
-		if (key.length > 1 && (name = Base.camelize(key)) in modifiers) {
-			modifiers[name] = down;
-			var agent = paper && paper.agent;
-			if (name === 'meta' && agent && agent.mac) {
-				if (down) {
-					metaFixMap = {};
-				} else {
-					for (var k in metaFixMap) {
-						if (k in charMap)
-							handleKey(false, k, metaFixMap[k], event);
-					}
-					metaFixMap = null;
-				}
-			}
-		} else if (down && metaFixMap) {
-			metaFixMap[key] = character;
-		}
-		if (view) {
-			view._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,
-					character);
-		}
-	}
-
-	DomEvent.add(document, {
-		keydown: function(event) {
-			var key = getKey(event),
-				agent = paper && paper.agent;
-			if (key.length > 1 || agent && (agent.chrome && (event.altKey
-						|| agent.mac && event.metaKey
-						|| !agent.mac && event.ctrlKey))) {
-				handleKey(true, key,
-						charLookup[key] || (key.length > 1 ? '' : key), event);
-			} else {
-				downKey = key;
-			}
-		},
-
-		keypress: function(event) {
-			if (downKey) {
-				var key = getKey(event),
-					code = event.charCode,
-					character = code >= 32 ? String.fromCharCode(code)
-						: key.length > 1 ? '' : key;
-				if (key !== downKey) {
-					key = character.toLowerCase();
-				}
-				handleKey(true, key, character, event);
-				downKey = null;
-			}
-		},
-
-		keyup: function(event) {
-			var key = getKey(event);
-			if (key in charMap)
-				handleKey(false, key, charMap[key], event);
-		}
-	});
-
-	DomEvent.add(window, {
-		blur: function(event) {
-			for (var key in charMap)
-				handleKey(false, key, charMap[key], event);
-		}
-	});
-
-	return {
-		modifiers: modifiers,
-
-		isDown: function(key) {
-			return !!keyMap[key];
-		}
-	};
-};
-
-var MouseEvent = Event.extend({
-	_class: 'MouseEvent',
-
-	initialize: function MouseEvent(type, event, point, target, delta) {
-		this.type = type;
-		this.event = event;
-		this.point = point;
-		this.target = target;
-		this.delta = delta;
-	},
-
-	toString: function() {
-		return "{ type: '" + this.type
-				+ "', point: " + this.point
-				+ ', target: ' + this.target
-				+ (this.delta ? ', delta: ' + this.delta : '')
-				+ ', modifiers: ' + this.getModifiers()
-				+ ' }';
-	}
-});
-
-var ToolEvent = Event.extend({
-	_class: 'ToolEvent',
-	_item: null,
-
-	initialize: function ToolEvent(tool, type, event) {
-		this.tool = tool;
-		this.type = type;
-		this.event = event;
-	},
-
-	_choosePoint: function(point, toolPoint) {
-		return point ? point : toolPoint ? toolPoint.clone() : null;
-	},
-
-	getPoint: function() {
-		return this._choosePoint(this._point, this.tool._point);
-	},
-
-	setPoint: function(point) {
-		this._point = point;
-	},
-
-	getLastPoint: function() {
-		return this._choosePoint(this._lastPoint, this.tool._lastPoint);
-	},
-
-	setLastPoint: function(lastPoint) {
-		this._lastPoint = lastPoint;
-	},
-
-	getDownPoint: function() {
-		return this._choosePoint(this._downPoint, this.tool._downPoint);
-	},
-
-	setDownPoint: function(downPoint) {
-		this._downPoint = downPoint;
-	},
-
-	getMiddlePoint: function() {
-		if (!this._middlePoint && this.tool._lastPoint) {
-			return this.tool._point.add(this.tool._lastPoint).divide(2);
-		}
-		return this._middlePoint;
-	},
-
-	setMiddlePoint: function(middlePoint) {
-		this._middlePoint = middlePoint;
-	},
-
-	getDelta: function() {
-		return !this._delta && this.tool._lastPoint
-				? this.tool._point.subtract(this.tool._lastPoint)
-				: this._delta;
-	},
-
-	setDelta: function(delta) {
-		this._delta = delta;
-	},
-
-	getCount: function() {
-		return this.tool[/^mouse(down|up)$/.test(this.type)
-				? '_downCount' : '_moveCount'];
-	},
-
-	setCount: function(count) {
-		this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
-			= count;
-	},
-
-	getItem: function() {
-		if (!this._item) {
-			var result = this.tool._scope.project.hitTest(this.getPoint());
-			if (result) {
-				var item = result.item,
-					parent = item._parent;
-				while (/^(Group|CompoundPath)$/.test(parent._class)) {
-					item = parent;
-					parent = parent._parent;
-				}
-				this._item = item;
-			}
-		}
-		return this._item;
-	},
-
-	setItem: function(item) {
-		this._item = item;
-	},
-
-	toString: function() {
-		return '{ type: ' + this.type
-				+ ', point: ' + this.getPoint()
-				+ ', count: ' + this.getCount()
-				+ ', modifiers: ' + this.getModifiers()
-				+ ' }';
-	}
-});
-
-var Tool = PaperScopeItem.extend({
-	_class: 'Tool',
-	_list: 'tools',
-	_reference: 'tool',
-	_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',
-			'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',
-			'onKeyUp'],
-
-	initialize: function Tool(props) {
-		PaperScopeItem.call(this);
-		this._moveCount = -1;
-		this._downCount = -1;
-		this._set(props);
-	},
-
-	getMinDistance: function() {
-		return this._minDistance;
-	},
-
-	setMinDistance: function(minDistance) {
-		this._minDistance = minDistance;
-		if (minDistance != null && this._maxDistance != null
-				&& minDistance > this._maxDistance) {
-			this._maxDistance = minDistance;
-		}
-	},
-
-	getMaxDistance: function() {
-		return this._maxDistance;
-	},
-
-	setMaxDistance: function(maxDistance) {
-		this._maxDistance = maxDistance;
-		if (this._minDistance != null && maxDistance != null
-				&& maxDistance < this._minDistance) {
-			this._minDistance = maxDistance;
-		}
-	},
-
-	getFixedDistance: function() {
-		return this._minDistance == this._maxDistance
-			? this._minDistance : null;
-	},
-
-	setFixedDistance: function(distance) {
-		this._minDistance = this._maxDistance = distance;
-	},
-
-	_handleMouseEvent: function(type, event, point, mouse) {
-		paper = this._scope;
-		if (mouse.drag && !this.responds(type))
-			type = 'mousemove';
-		var move = mouse.move || mouse.drag,
-			responds = this.responds(type),
-			minDistance = this.minDistance,
-			maxDistance = this.maxDistance,
-			called = false,
-			tool = this;
-		function update(minDistance, maxDistance) {
-			var pt = point,
-				toolPoint = move ? tool._point : (tool._downPoint || pt);
-			if (move) {
-				if (tool._moveCount && pt.equals(toolPoint)) {
-					return false;
-				}
-				if (toolPoint && (minDistance != null || maxDistance != null)) {
-					var vector = pt.subtract(toolPoint),
-						distance = vector.getLength();
-					if (distance < (minDistance || 0))
-						return false;
-					if (maxDistance) {
-						pt = toolPoint.add(vector.normalize(
-								Math.min(distance, maxDistance)));
-					}
-				}
-				tool._moveCount++;
-			}
-			tool._point = pt;
-			tool._lastPoint = toolPoint || pt;
-			if (mouse.down) {
-				tool._moveCount = -1;
-				tool._downPoint = pt;
-				tool._downCount++;
-			}
-			return true;
-		}
-
-		function emit() {
-			if (responds) {
-				called = tool.emit(type, new ToolEvent(tool, type, event))
-						|| called;
-			}
-		}
-
-		if (mouse.down) {
-			update();
-			emit();
-		} else if (mouse.up) {
-			update(null, maxDistance);
-			emit();
-		} else if (responds) {
-			while (update(minDistance, maxDistance))
-				emit();
-		}
-		return called;
-	}
-
-});
-
-var Http = {
-	request: function(options) {
-		var xhr = new window.XMLHttpRequest();
-		xhr.open((options.method || 'get').toUpperCase(), options.url,
-				Base.pick(options.async, true));
-		if (options.mimeType)
-			xhr.overrideMimeType(options.mimeType);
-		xhr.onload = function() {
-			var status = xhr.status;
-			if (status === 0 || status === 200) {
-				if (options.onLoad) {
-					options.onLoad.call(xhr, xhr.responseText);
-				}
-			} else {
-				xhr.onerror();
-			}
-		};
-		xhr.onerror = function() {
-			var status = xhr.status,
-				message = 'Could not load "' + options.url + '" (Status: '
-						+ status + ')';
-			if (options.onError) {
-				options.onError(message, status);
-			} else {
-				throw new Error(message);
-			}
-		};
-		return xhr.send(null);
-	}
-};
-
-var CanvasProvider = {
-	canvases: [],
-
-	getCanvas: function(width, height) {
-		if (!window)
-			return null;
-		var canvas,
-			clear = true;
-		if (typeof width === 'object') {
-			height = width.height;
-			width = width.width;
-		}
-		if (this.canvases.length) {
-			canvas = this.canvases.pop();
-		} else {
-			canvas = document.createElement('canvas');
-			clear = false;
-		}
-		var ctx = canvas.getContext('2d');
-		if (!ctx) {
-			throw new Error('Canvas ' + canvas +
-					' is unable toprovide a 2D context.');
-		}
-		if (canvas.width === width && canvas.height === height) {
-			if (clear)
-				ctx.clearRect(0, 0, width + 1, height + 1);
-		} else {
-			canvas.width = width;
-			canvas.height = height;
-		}
-		ctx.save();
-		return canvas;
-	},
-
-	getContext: function(width, height) {
-		var canvas = this.getCanvas(width, height);
-		return canvas ? canvas.getContext('2d') : null;
-	},
-
-	release: function(obj) {
-		var canvas = obj && obj.canvas ? obj.canvas : obj;
-		if (canvas && canvas.getContext) {
-			canvas.getContext('2d').restore();
-			this.canvases.push(canvas);
-		}
-	}
-};
-
-var BlendMode = new function() {
-	var min = Math.min,
-		max = Math.max,
-		abs = Math.abs,
-		sr, sg, sb, sa,
-		br, bg, bb, ba,
-		dr, dg, db;
-
-	function getLum(r, g, b) {
-		return 0.2989 * r + 0.587 * g + 0.114 * b;
-	}
-
-	function setLum(r, g, b, l) {
-		var d = l - getLum(r, g, b);
-		dr = r + d;
-		dg = g + d;
-		db = b + d;
-		var l = getLum(dr, dg, db),
-			mn = min(dr, dg, db),
-			mx = max(dr, dg, db);
-		if (mn < 0) {
-			var lmn = l - mn;
-			dr = l + (dr - l) * l / lmn;
-			dg = l + (dg - l) * l / lmn;
-			db = l + (db - l) * l / lmn;
-		}
-		if (mx > 255) {
-			var ln = 255 - l,
-				mxl = mx - l;
-			dr = l + (dr - l) * ln / mxl;
-			dg = l + (dg - l) * ln / mxl;
-			db = l + (db - l) * ln / mxl;
-		}
-	}
-
-	function getSat(r, g, b) {
-		return max(r, g, b) - min(r, g, b);
-	}
-
-	function setSat(r, g, b, s) {
-		var col = [r, g, b],
-			mx = max(r, g, b),
-			mn = min(r, g, b),
-			md;
-		mn = mn === r ? 0 : mn === g ? 1 : 2;
-		mx = mx === r ? 0 : mx === g ? 1 : 2;
-		md = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;
-		if (col[mx] > col[mn]) {
-			col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);
-			col[mx] = s;
-		} else {
-			col[md] = col[mx] = 0;
-		}
-		col[mn] = 0;
-		dr = col[0];
-		dg = col[1];
-		db = col[2];
-	}
-
-	var modes = {
-		multiply: function() {
-			dr = br * sr / 255;
-			dg = bg * sg / 255;
-			db = bb * sb / 255;
-		},
-
-		screen: function() {
-			dr = br + sr - (br * sr / 255);
-			dg = bg + sg - (bg * sg / 255);
-			db = bb + sb - (bb * sb / 255);
-		},
-
-		overlay: function() {
-			dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;
-			dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;
-			db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;
-		},
-
-		'soft-light': function() {
-			var t = sr * br / 255;
-			dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;
-			t = sg * bg / 255;
-			dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;
-			t = sb * bb / 255;
-			db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;
-		},
-
-		'hard-light': function() {
-			dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;
-			dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;
-			db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;
-		},
-
-		'color-dodge': function() {
-			dr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));
-			dg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));
-			db = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));
-		},
-
-		'color-burn': function() {
-			dr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);
-			dg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);
-			db = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);
-		},
-
-		darken: function() {
-			dr = br < sr ? br : sr;
-			dg = bg < sg ? bg : sg;
-			db = bb < sb ? bb : sb;
-		},
-
-		lighten: function() {
-			dr = br > sr ? br : sr;
-			dg = bg > sg ? bg : sg;
-			db = bb > sb ? bb : sb;
-		},
-
-		difference: function() {
-			dr = br - sr;
-			if (dr < 0)
-				dr = -dr;
-			dg = bg - sg;
-			if (dg < 0)
-				dg = -dg;
-			db = bb - sb;
-			if (db < 0)
-				db = -db;
-		},
-
-		exclusion: function() {
-			dr = br + sr * (255 - br - br) / 255;
-			dg = bg + sg * (255 - bg - bg) / 255;
-			db = bb + sb * (255 - bb - bb) / 255;
-		},
-
-		hue: function() {
-			setSat(sr, sg, sb, getSat(br, bg, bb));
-			setLum(dr, dg, db, getLum(br, bg, bb));
-		},
-
-		saturation: function() {
-			setSat(br, bg, bb, getSat(sr, sg, sb));
-			setLum(dr, dg, db, getLum(br, bg, bb));
-		},
-
-		luminosity: function() {
-			setLum(br, bg, bb, getLum(sr, sg, sb));
-		},
-
-		color: function() {
-			setLum(sr, sg, sb, getLum(br, bg, bb));
-		},
-
-		add: function() {
-			dr = min(br + sr, 255);
-			dg = min(bg + sg, 255);
-			db = min(bb + sb, 255);
-		},
-
-		subtract: function() {
-			dr = max(br - sr, 0);
-			dg = max(bg - sg, 0);
-			db = max(bb - sb, 0);
-		},
-
-		average: function() {
-			dr = (br + sr) / 2;
-			dg = (bg + sg) / 2;
-			db = (bb + sb) / 2;
-		},
-
-		negation: function() {
-			dr = 255 - abs(255 - sr - br);
-			dg = 255 - abs(255 - sg - bg);
-			db = 255 - abs(255 - sb - bb);
-		}
-	};
-
-	var nativeModes = this.nativeModes = Base.each([
-		'source-over', 'source-in', 'source-out', 'source-atop',
-		'destination-over', 'destination-in', 'destination-out',
-		'destination-atop', 'lighter', 'darker', 'copy', 'xor'
-	], function(mode) {
-		this[mode] = true;
-	}, {});
-
-	var ctx = CanvasProvider.getContext(1, 1);
-	if (ctx) {
-		Base.each(modes, function(func, mode) {
-			var darken = mode === 'darken',
-				ok = false;
-			ctx.save();
-			try {
-				ctx.fillStyle = darken ? '#300' : '#a00';
-				ctx.fillRect(0, 0, 1, 1);
-				ctx.globalCompositeOperation = mode;
-				if (ctx.globalCompositeOperation === mode) {
-					ctx.fillStyle = darken ? '#a00' : '#300';
-					ctx.fillRect(0, 0, 1, 1);
-					ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken
-							? 170 : 51;
-				}
-			} catch (e) {}
-			ctx.restore();
-			nativeModes[mode] = ok;
-		});
-		CanvasProvider.release(ctx);
-	}
-
-	this.process = function(mode, srcContext, dstContext, alpha, offset) {
-		var srcCanvas = srcContext.canvas,
-			normal = mode === 'normal';
-		if (normal || nativeModes[mode]) {
-			dstContext.save();
-			dstContext.setTransform(1, 0, 0, 1, 0, 0);
-			dstContext.globalAlpha = alpha;
-			if (!normal)
-				dstContext.globalCompositeOperation = mode;
-			dstContext.drawImage(srcCanvas, offset.x, offset.y);
-			dstContext.restore();
-		} else {
-			var process = modes[mode];
-			if (!process)
-				return;
-			var dstData = dstContext.getImageData(offset.x, offset.y,
-					srcCanvas.width, srcCanvas.height),
-				dst = dstData.data,
-				src = srcContext.getImageData(0, 0,
-					srcCanvas.width, srcCanvas.height).data;
-			for (var i = 0, l = dst.length; i < l; i += 4) {
-				sr = src[i];
-				br = dst[i];
-				sg = src[i + 1];
-				bg = dst[i + 1];
-				sb = src[i + 2];
-				bb = dst[i + 2];
-				sa = src[i + 3];
-				ba = dst[i + 3];
-				process();
-				var a1 = sa * alpha / 255,
-					a2 = 1 - a1;
-				dst[i] = a1 * dr + a2 * br;
-				dst[i + 1] = a1 * dg + a2 * bg;
-				dst[i + 2] = a1 * db + a2 * bb;
-				dst[i + 3] = sa * alpha + a2 * ba;
-			}
-			dstContext.putImageData(dstData, offset.x, offset.y);
-		}
-	};
-};
-
-var SvgElement = new function() {
-	var svg = 'http://www.w3.org/2000/svg',
-		xmlns = 'http://www.w3.org/2000/xmlns',
-		xlink = 'http://www.w3.org/1999/xlink',
-		attributeNamespace = {
-			href: xlink,
-			xlink: xmlns,
-			xmlns: xmlns + '/',
-			'xmlns:xlink': xmlns + '/'
-		};
-
-	function create(tag, attributes, formatter) {
-		return set(document.createElementNS(svg, tag), attributes, formatter);
-	}
-
-	function get(node, name) {
-		var namespace = attributeNamespace[name],
-			value = namespace
-				? node.getAttributeNS(namespace, name)
-				: node.getAttribute(name);
-		return value === 'null' ? null : value;
-	}
-
-	function set(node, attributes, formatter) {
-		for (var name in attributes) {
-			var value = attributes[name],
-				namespace = attributeNamespace[name];
-			if (typeof value === 'number' && formatter)
-				value = formatter.number(value);
-			if (namespace) {
-				node.setAttributeNS(namespace, name, value);
-			} else {
-				node.setAttribute(name, value);
-			}
-		}
-		return node;
-	}
-
-	return {
-		svg: svg,
-		xmlns: xmlns,
-		xlink: xlink,
-
-		create: create,
-		get: get,
-		set: set
-	};
-};
-
-var SvgStyles = Base.each({
-	fillColor: ['fill', 'color'],
-	fillRule: ['fill-rule', 'string'],
-	strokeColor: ['stroke', 'color'],
-	strokeWidth: ['stroke-width', 'number'],
-	strokeCap: ['stroke-linecap', 'string'],
-	strokeJoin: ['stroke-linejoin', 'string'],
-	strokeScaling: ['vector-effect', 'lookup', {
-		true: 'none',
-		false: 'non-scaling-stroke'
-	}, function(item, value) {
-		return !value
-				&& (item instanceof PathItem
-					|| item instanceof Shape
-					|| item instanceof TextItem);
-	}],
-	miterLimit: ['stroke-miterlimit', 'number'],
-	dashArray: ['stroke-dasharray', 'array'],
-	dashOffset: ['stroke-dashoffset', 'number'],
-	fontFamily: ['font-family', 'string'],
-	fontWeight: ['font-weight', 'string'],
-	fontSize: ['font-size', 'number'],
-	justification: ['text-anchor', 'lookup', {
-		left: 'start',
-		center: 'middle',
-		right: 'end'
-	}],
-	opacity: ['opacity', 'number'],
-	blendMode: ['mix-blend-mode', 'style']
-}, function(entry, key) {
-	var part = Base.capitalize(key),
-		lookup = entry[2];
-	this[key] = {
-		type: entry[1],
-		property: key,
-		attribute: entry[0],
-		toSVG: lookup,
-		fromSVG: lookup && Base.each(lookup, function(value, name) {
-			this[value] = name;
-		}, {}),
-		exportFilter: entry[3],
-		get: 'get' + part,
-		set: 'set' + part
-	};
-}, {});
-
-new function() {
-	var formatter;
-
-	function getTransform(matrix, coordinates, center) {
-		var attrs = new Base(),
-			trans = matrix.getTranslation();
-		if (coordinates) {
-			matrix = matrix._shiftless();
-			var point = matrix._inverseTransform(trans);
-			attrs[center ? 'cx' : 'x'] = point.x;
-			attrs[center ? 'cy' : 'y'] = point.y;
-			trans = null;
-		}
-		if (!matrix.isIdentity()) {
-			var decomposed = matrix.decompose();
-			if (decomposed) {
-				var parts = [],
-					angle = decomposed.rotation,
-					scale = decomposed.scaling,
-					skew = decomposed.skewing;
-				if (trans && !trans.isZero())
-					parts.push('translate(' + formatter.point(trans) + ')');
-				if (angle)
-					parts.push('rotate(' + formatter.number(angle) + ')');
-				if (!Numerical.isZero(scale.x - 1)
-						|| !Numerical.isZero(scale.y - 1))
-					parts.push('scale(' + formatter.point(scale) +')');
-				if (skew && skew.x)
-					parts.push('skewX(' + formatter.number(skew.x) + ')');
-				if (skew && skew.y)
-					parts.push('skewY(' + formatter.number(skew.y) + ')');
-				attrs.transform = parts.join(' ');
-			} else {
-				attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';
-			}
-		}
-		return attrs;
-	}
-
-	function exportGroup(item, options) {
-		var attrs = getTransform(item._matrix),
-			children = item._children;
-		var node = SvgElement.create('g', attrs, formatter);
-		for (var i = 0, l = children.length; i < l; i++) {
-			var child = children[i];
-			var childNode = exportSVG(child, options);
-			if (childNode) {
-				if (child.isClipMask()) {
-					var clip = SvgElement.create('clipPath');
-					clip.appendChild(childNode);
-					setDefinition(child, clip, 'clip');
-					SvgElement.set(node, {
-						'clip-path': 'url(#' + clip.id + ')'
-					});
-				} else {
-					node.appendChild(childNode);
-				}
-			}
-		}
-		return node;
-	}
-
-	function exportRaster(item, options) {
-		var attrs = getTransform(item._matrix, true),
-			size = item.getSize(),
-			image = item.getImage();
-		attrs.x -= size.width / 2;
-		attrs.y -= size.height / 2;
-		attrs.width = size.width;
-		attrs.height = size.height;
-		attrs.href = options.embedImages === false && image && image.src
-				|| item.toDataURL();
-		return SvgElement.create('image', attrs, formatter);
-	}
-
-	function exportPath(item, options) {
-		var matchShapes = options.matchShapes;
-		if (matchShapes) {
-			var shape = item.toShape(false);
-			if (shape)
-				return exportShape(shape, options);
-		}
-		var segments = item._segments,
-			length = segments.length,
-			type,
-			attrs = getTransform(item._matrix);
-		if (matchShapes && length >= 2 && !item.hasHandles()) {
-			if (length > 2) {
-				type = item._closed ? 'polygon' : 'polyline';
-				var parts = [];
-				for(var i = 0; i < length; i++)
-					parts.push(formatter.point(segments[i]._point));
-				attrs.points = parts.join(' ');
-			} else {
-				type = 'line';
-				var start = segments[0]._point,
-					end = segments[1]._point;
-				attrs.set({
-					x1: start.x,
-					y1: start.y,
-					x2: end.x,
-					y2: end.y
-				});
-			}
-		} else {
-			type = 'path';
-			attrs.d = item.getPathData(null, options.precision);
-		}
-		return SvgElement.create(type, attrs, formatter);
-	}
-
-	function exportShape(item) {
-		var type = item._type,
-			radius = item._radius,
-			attrs = getTransform(item._matrix, true, type !== 'rectangle');
-		if (type === 'rectangle') {
-			type = 'rect';
-			var size = item._size,
-				width = size.width,
-				height = size.height;
-			attrs.x -= width / 2;
-			attrs.y -= height / 2;
-			attrs.width = width;
-			attrs.height = height;
-			if (radius.isZero())
-				radius = null;
-		}
-		if (radius) {
-			if (type === 'circle') {
-				attrs.r = radius;
-			} else {
-				attrs.rx = radius.width;
-				attrs.ry = radius.height;
-			}
-		}
-		return SvgElement.create(type, attrs, formatter);
-	}
-
-	function exportCompoundPath(item, options) {
-		var attrs = getTransform(item._matrix);
-		var data = item.getPathData(null, options.precision);
-		if (data)
-			attrs.d = data;
-		return SvgElement.create('path', attrs, formatter);
-	}
-
-	function exportSymbolItem(item, options) {
-		var attrs = getTransform(item._matrix, true),
-			definition = item._definition,
-			node = getDefinition(definition, 'symbol'),
-			definitionItem = definition._item,
-			bounds = definitionItem.getBounds();
-		if (!node) {
-			node = SvgElement.create('symbol', {
-				viewBox: formatter.rectangle(bounds)
-			});
-			node.appendChild(exportSVG(definitionItem, options));
-			setDefinition(definition, node, 'symbol');
-		}
-		attrs.href = '#' + node.id;
-		attrs.x += bounds.x;
-		attrs.y += bounds.y;
-		attrs.width = bounds.width;
-		attrs.height = bounds.height;
-		attrs.overflow = 'visible';
-		return SvgElement.create('use', attrs, formatter);
-	}
-
-	function exportGradient(color) {
-		var gradientNode = getDefinition(color, 'color');
-		if (!gradientNode) {
-			var gradient = color.getGradient(),
-				radial = gradient._radial,
-				origin = color.getOrigin(),
-				destination = color.getDestination(),
-				attrs;
-			if (radial) {
-				attrs = {
-					cx: origin.x,
-					cy: origin.y,
-					r: origin.getDistance(destination)
-				};
-				var highlight = color.getHighlight();
-				if (highlight) {
-					attrs.fx = highlight.x;
-					attrs.fy = highlight.y;
-				}
-			} else {
-				attrs = {
-					x1: origin.x,
-					y1: origin.y,
-					x2: destination.x,
-					y2: destination.y
-				};
-			}
-			attrs.gradientUnits = 'userSpaceOnUse';
-			gradientNode = SvgElement.create((radial ? 'radial' : 'linear')
-					+ 'Gradient', attrs, formatter);
-			var stops = gradient._stops;
-			for (var i = 0, l = stops.length; i < l; i++) {
-				var stop = stops[i],
-					stopColor = stop._color,
-					alpha = stopColor.getAlpha();
-				attrs = {
-					offset: stop._offset || i / (l - 1)
-				};
-				if (stopColor)
-					attrs['stop-color'] = stopColor.toCSS(true);
-				if (alpha < 1)
-					attrs['stop-opacity'] = alpha;
-				gradientNode.appendChild(
-						SvgElement.create('stop', attrs, formatter));
-			}
-			setDefinition(color, gradientNode, 'color');
-		}
-		return 'url(#' + gradientNode.id + ')';
-	}
-
-	function exportText(item) {
-		var node = SvgElement.create('text', getTransform(item._matrix, true),
-				formatter);
-		node.textContent = item._content;
-		return node;
-	}
-
-	var exporters = {
-		Group: exportGroup,
-		Layer: exportGroup,
-		Raster: exportRaster,
-		Path: exportPath,
-		Shape: exportShape,
-		CompoundPath: exportCompoundPath,
-		SymbolItem: exportSymbolItem,
-		PointText: exportText
-	};
-
-	function applyStyle(item, node, isRoot) {
-		var attrs = {},
-			parent = !isRoot && item.getParent(),
-			style = [];
-
-		if (item._name != null)
-			attrs.id = item._name;
-
-		Base.each(SvgStyles, function(entry) {
-			var get = entry.get,
-				type = entry.type,
-				value = item[get]();
-			if (entry.exportFilter
-					? entry.exportFilter(item, value)
-					: !parent || !Base.equals(parent[get](), value)) {
-				if (type === 'color' && value != null) {
-					var alpha = value.getAlpha();
-					if (alpha < 1)
-						attrs[entry.attribute + '-opacity'] = alpha;
-				}
-				if (type === 'style') {
-					style.push(entry.attribute + ': ' + value);
-				} else {
-					attrs[entry.attribute] = value == null ? 'none'
-							: type === 'color' ? value.gradient
-								? exportGradient(value, item)
-								: value.toCSS(true)
-							: type === 'array' ? value.join(',')
-							: type === 'lookup' ? entry.toSVG[value]
-							: value;
-				}
-			}
-		});
-
-		if (style.length)
-			attrs.style = style.join(';');
-
-		if (attrs.opacity === 1)
-			delete attrs.opacity;
-
-		if (!item._visible)
-			attrs.visibility = 'hidden';
-
-		return SvgElement.set(node, attrs, formatter);
-	}
-
-	var definitions;
-	function getDefinition(item, type) {
-		if (!definitions)
-			definitions = { ids: {}, svgs: {} };
-		var id = item._id || item.__id || (item.__id = UID.get('svg'));
-		return item && definitions.svgs[type + '-' + id];
-	}
-
-	function setDefinition(item, node, type) {
-		if (!definitions)
-			getDefinition();
-		var typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;
-		node.id = type + '-' + typeId;
-		definitions.svgs[type + '-' + (item._id || item.__id)] = node;
-	}
-
-	function exportDefinitions(node, options) {
-		var svg = node,
-			defs = null;
-		if (definitions) {
-			svg = node.nodeName.toLowerCase() === 'svg' && node;
-			for (var i in definitions.svgs) {
-				if (!defs) {
-					if (!svg) {
-						svg = SvgElement.create('svg');
-						svg.appendChild(node);
-					}
-					defs = svg.insertBefore(SvgElement.create('defs'),
-							svg.firstChild);
-				}
-				defs.appendChild(definitions.svgs[i]);
-			}
-			definitions = null;
-		}
-		return options.asString
-				? new window.XMLSerializer().serializeToString(svg)
-				: svg;
-	}
-
-	function exportSVG(item, options, isRoot) {
-		var exporter = exporters[item._class],
-			node = exporter && exporter(item, options);
-		if (node) {
-			var onExport = options.onExport;
-			if (onExport)
-				node = onExport(item, node, options) || node;
-			var data = JSON.stringify(item._data);
-			if (data && data !== '{}' && data !== 'null')
-				node.setAttribute('data-paper-data', data);
-		}
-		return node && applyStyle(item, node, isRoot);
-	}
-
-	function setOptions(options) {
-		if (!options)
-			options = {};
-		formatter = new Formatter(options.precision);
-		return options;
-	}
-
-	Item.inject({
-		exportSVG: function(options) {
-			options = setOptions(options);
-			return exportDefinitions(exportSVG(this, options, true), options);
-		}
-	});
-
-	Project.inject({
-		exportSVG: function(options) {
-			options = setOptions(options);
-			var children = this._children,
-				view = this.getView(),
-				bounds = Base.pick(options.bounds, 'view'),
-				mx = options.matrix || bounds === 'view' && view._matrix,
-				matrix = mx && Matrix.read([mx]),
-				rect = bounds === 'view'
-					? new Rectangle([0, 0], view.getViewSize())
-					: bounds === 'content'
-						? Item._getBounds(children, matrix, { stroke: true })
-						: Rectangle.read([bounds], 0, { readNull: true }),
-				attrs = {
-					version: '1.1',
-					xmlns: SvgElement.svg,
-					'xmlns:xlink': SvgElement.xlink,
-				};
-			if (rect) {
-				attrs.width = rect.width;
-				attrs.height = rect.height;
-				if (rect.x || rect.y)
-					attrs.viewBox = formatter.rectangle(rect);
-			}
-			var node = SvgElement.create('svg', attrs, formatter),
-				parent = node;
-			if (matrix && !matrix.isIdentity()) {
-				parent = node.appendChild(SvgElement.create('g',
-						getTransform(matrix), formatter));
-			}
-			for (var i = 0, l = children.length; i < l; i++) {
-				parent.appendChild(exportSVG(children[i], options, true));
-			}
-			return exportDefinitions(node, options);
-		}
-	});
-};
-
-new function() {
-
-	var definitions = {},
-		rootSize;
-
-	function getValue(node, name, isString, allowNull, allowPercent) {
-		var value = SvgElement.get(node, name),
-			res = value == null
-				? allowNull
-					? null
-					: isString ? '' : 0
-				: isString
-					? value
-					: parseFloat(value);
-		return /%\s*$/.test(value)
-			? (res / 100) * (allowPercent ? 1
-				: rootSize[/x|^width/.test(name) ? 'width' : 'height'])
-			: res;
-	}
-
-	function getPoint(node, x, y, allowNull, allowPercent) {
-		x = getValue(node, x || 'x', false, allowNull, allowPercent);
-		y = getValue(node, y || 'y', false, allowNull, allowPercent);
-		return allowNull && (x == null || y == null) ? null
-				: new Point(x, y);
-	}
-
-	function getSize(node, w, h, allowNull, allowPercent) {
-		w = getValue(node, w || 'width', false, allowNull, allowPercent);
-		h = getValue(node, h || 'height', false, allowNull, allowPercent);
-		return allowNull && (w == null || h == null) ? null
-				: new Size(w, h);
-	}
-
-	function convertValue(value, type, lookup) {
-		return value === 'none' ? null
-				: type === 'number' ? parseFloat(value)
-				: type === 'array' ?
-					value ? value.split(/[\s,]+/g).map(parseFloat) : []
-				: type === 'color' ? getDefinition(value) || value
-				: type === 'lookup' ? lookup[value]
-				: value;
-	}
-
-	function importGroup(node, type, options, isRoot) {
-		var nodes = node.childNodes,
-			isClip = type === 'clippath',
-			isDefs = type === 'defs',
-			item = new Group(),
-			project = item._project,
-			currentStyle = project._currentStyle,
-			children = [];
-		if (!isClip && !isDefs) {
-			item = applyAttributes(item, node, isRoot);
-			project._currentStyle = item._style.clone();
-		}
-		if (isRoot) {
-			var defs = node.querySelectorAll('defs');
-			for (var i = 0, l = defs.length; i < l; i++) {
-				importNode(defs[i], options, false);
-			}
-		}
-		for (var i = 0, l = nodes.length; i < l; i++) {
-			var childNode = nodes[i],
-				child;
-			if (childNode.nodeType === 1
-					&& !/^defs$/i.test(childNode.nodeName)
-					&& (child = importNode(childNode, options, false))
-					&& !(child instanceof SymbolDefinition))
-				children.push(child);
-		}
-		item.addChildren(children);
-		if (isClip)
-			item = applyAttributes(item.reduce(), node, isRoot);
-		project._currentStyle = currentStyle;
-		if (isClip || isDefs) {
-			item.remove();
-			item = null;
-		}
-		return item;
-	}
-
-	function importPoly(node, type) {
-		var coords = node.getAttribute('points').match(
-					/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),
-			points = [];
-		for (var i = 0, l = coords.length; i < l; i += 2)
-			points.push(new Point(
-					parseFloat(coords[i]),
-					parseFloat(coords[i + 1])));
-		var path = new Path(points);
-		if (type === 'polygon')
-			path.closePath();
-		return path;
-	}
-
-	function importPath(node) {
-		return PathItem.create(node.getAttribute('d'));
-	}
-
-	function importGradient(node, type) {
-		var id = (getValue(node, 'href', true) || '').substring(1),
-			radial = type === 'radialgradient',
-			gradient;
-		if (id) {
-			gradient = definitions[id].getGradient();
-			if (gradient._radial ^ radial) {
-				gradient = gradient.clone();
-				gradient._radial = radial;
-			}
-		} else {
-			var nodes = node.childNodes,
-				stops = [];
-			for (var i = 0, l = nodes.length; i < l; i++) {
-				var child = nodes[i];
-				if (child.nodeType === 1)
-					stops.push(applyAttributes(new GradientStop(), child));
-			}
-			gradient = new Gradient(stops, radial);
-		}
-		var origin, destination, highlight,
-			scaleToBounds = getValue(node, 'gradientUnits', true) !==
-				'userSpaceOnUse';
-		if (radial) {
-			origin = getPoint(node, 'cx', 'cy', false, scaleToBounds);
-			destination = origin.add(
-					getValue(node, 'r', false, false, scaleToBounds), 0);
-			highlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);
-		} else {
-			origin = getPoint(node, 'x1', 'y1', false, scaleToBounds);
-			destination = getPoint(node, 'x2', 'y2', false, scaleToBounds);
-		}
-		var color = applyAttributes(
-				new Color(gradient, origin, destination, highlight), node);
-		color._scaleToBounds = scaleToBounds;
-		return null;
-	}
-
-	var importers = {
-		'#document': function (node, type, options, isRoot) {
-			var nodes = node.childNodes;
-			for (var i = 0, l = nodes.length; i < l; i++) {
-				var child = nodes[i];
-				if (child.nodeType === 1)
-					return importNode(child, options, isRoot);
-			}
-		},
-		g: importGroup,
-		svg: importGroup,
-		clippath: importGroup,
-		polygon: importPoly,
-		polyline: importPoly,
-		path: importPath,
-		lineargradient: importGradient,
-		radialgradient: importGradient,
-
-		image: function (node) {
-			var raster = new Raster(getValue(node, 'href', true));
-			raster.on('load', function() {
-				var size = getSize(node);
-				this.setSize(size);
-				var center = this._matrix._transformPoint(
-						getPoint(node).add(size.divide(2)));
-				this.translate(center);
-			});
-			return raster;
-		},
-
-		symbol: function(node, type, options, isRoot) {
-			return new SymbolDefinition(
-					importGroup(node, type, options, isRoot), true);
-		},
-
-		defs: importGroup,
-
-		use: function(node) {
-			var id = (getValue(node, 'href', true) || '').substring(1),
-				definition = definitions[id],
-				point = getPoint(node);
-			return definition
-					? definition instanceof SymbolDefinition
-						? definition.place(point)
-						: definition.clone().translate(point)
-					: null;
-		},
-
-		circle: function(node) {
-			return new Shape.Circle(
-					getPoint(node, 'cx', 'cy'),
-					getValue(node, 'r'));
-		},
-
-		ellipse: function(node) {
-			return new Shape.Ellipse({
-				center: getPoint(node, 'cx', 'cy'),
-				radius: getSize(node, 'rx', 'ry')
-			});
-		},
-
-		rect: function(node) {
-			return new Shape.Rectangle(new Rectangle(
-						getPoint(node),
-						getSize(node)
-					), getSize(node, 'rx', 'ry'));
-			},
-
-		line: function(node) {
-			return new Path.Line(
-					getPoint(node, 'x1', 'y1'),
-					getPoint(node, 'x2', 'y2'));
-		},
-
-		text: function(node) {
-			var text = new PointText(getPoint(node).add(
-					getPoint(node, 'dx', 'dy')));
-			text.setContent(node.textContent.trim() || '');
-			return text;
-		}
-	};
-
-	function applyTransform(item, value, name, node) {
-		if (item.transform) {
-			var transforms = (node.getAttribute(name) || '').split(/\)\s*/g),
-				matrix = new Matrix();
-			for (var i = 0, l = transforms.length; i < l; i++) {
-				var transform = transforms[i];
-				if (!transform)
-					break;
-				var parts = transform.split(/\(\s*/),
-					command = parts[0],
-					v = parts[1].split(/[\s,]+/g);
-				for (var j = 0, m = v.length; j < m; j++)
-					v[j] = parseFloat(v[j]);
-				switch (command) {
-				case 'matrix':
-					matrix.append(
-							new Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));
-					break;
-				case 'rotate':
-					matrix.rotate(v[0], v[1], v[2]);
-					break;
-				case 'translate':
-					matrix.translate(v[0], v[1]);
-					break;
-				case 'scale':
-					matrix.scale(v);
-					break;
-				case 'skewX':
-					matrix.skew(v[0], 0);
-					break;
-				case 'skewY':
-					matrix.skew(0, v[0]);
-					break;
-				}
-			}
-			item.transform(matrix);
-		}
-	}
-
-	function applyOpacity(item, value, name) {
-		var key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',
-			color = item[key] && item[key]();
-		if (color)
-			color.setAlpha(parseFloat(value));
-	}
-
-	var attributes = Base.set(Base.each(SvgStyles, function(entry) {
-		this[entry.attribute] = function(item, value) {
-			if (item[entry.set]) {
-				item[entry.set](convertValue(value, entry.type, entry.fromSVG));
-				if (entry.type === 'color') {
-					var color = item[entry.get]();
-					if (color) {
-						if (color._scaleToBounds) {
-							var bounds = item.getBounds();
-							color.transform(new Matrix()
-								.translate(bounds.getPoint())
-								.scale(bounds.getSize()));
-						}
-						if (item instanceof Shape) {
-							color.transform(new Matrix().translate(
-								item.getPosition(true).negate()));
-						}
-					}
-				}
-			}
-		};
-	}, {}), {
-		id: function(item, value) {
-			definitions[value] = item;
-			if (item.setName)
-				item.setName(value);
-		},
-
-		'clip-path': function(item, value) {
-			var clip = getDefinition(value);
-			if (clip) {
-				clip = clip.clone();
-				clip.setClipMask(true);
-				if (item instanceof Group) {
-					item.insertChild(0, clip);
-				} else {
-					return new Group(clip, item);
-				}
-			}
-		},
-
-		gradientTransform: applyTransform,
-		transform: applyTransform,
-
-		'fill-opacity': applyOpacity,
-		'stroke-opacity': applyOpacity,
-
-		visibility: function(item, value) {
-			if (item.setVisible)
-				item.setVisible(value === 'visible');
-		},
-
-		display: function(item, value) {
-			if (item.setVisible)
-				item.setVisible(value !== null);
-		},
-
-		'stop-color': function(item, value) {
-			if (item.setColor)
-				item.setColor(value);
-		},
-
-		'stop-opacity': function(item, value) {
-			if (item._color)
-				item._color.setAlpha(parseFloat(value));
-		},
-
-		offset: function(item, value) {
-			if (item.setOffset) {
-				var percent = value.match(/(.*)%$/);
-				item.setOffset(percent ? percent[1] / 100 : parseFloat(value));
-			}
-		},
-
-		viewBox: function(item, value, name, node, styles) {
-			var rect = new Rectangle(convertValue(value, 'array')),
-				size = getSize(node, null, null, true),
-				group,
-				matrix;
-			if (item instanceof Group) {
-				var scale = size ? size.divide(rect.getSize()) : 1,
-				matrix = new Matrix().scale(scale)
-						.translate(rect.getPoint().negate());
-				group = item;
-			} else if (item instanceof SymbolDefinition) {
-				if (size)
-					rect.setSize(size);
-				group = item._item;
-			}
-			if (group)  {
-				if (getAttribute(node, 'overflow', styles) !== 'visible') {
-					var clip = new Shape.Rectangle(rect);
-					clip.setClipMask(true);
-					group.addChild(clip);
-				}
-				if (matrix)
-					group.transform(matrix);
-			}
-		}
-	});
-
-	function getAttribute(node, name, styles) {
-		var attr = node.attributes[name],
-			value = attr && attr.value;
-		if (!value) {
-			var style = Base.camelize(name);
-			value = node.style[style];
-			if (!value && styles.node[style] !== styles.parent[style])
-				value = styles.node[style];
-		}
-		return !value ? undefined
-				: value === 'none' ? null
-				: value;
-	}
-
-	function applyAttributes(item, node, isRoot) {
-		var parent = node.parentNode,
-			styles = {
-				node: DomElement.getStyles(node) || {},
-				parent: !isRoot && !/^defs$/i.test(parent.tagName)
-						&& DomElement.getStyles(parent) || {}
-			};
-		Base.each(attributes, function(apply, name) {
-			var value = getAttribute(node, name, styles);
-			item = value !== undefined && apply(item, value, name, node, styles)
-					|| item;
-		});
-		return item;
-	}
-
-	function getDefinition(value) {
-		var match = value && value.match(/\((?:["'#]*)([^"')]+)/),
-			res = match && definitions[match[1]
-				.replace(window.location.href.split('#')[0] + '#', '')];
-		if (res && res._scaleToBounds) {
-			res = res.clone();
-			res._scaleToBounds = true;
-		}
-		return res;
-	}
-
-	function importNode(node, options, isRoot) {
-		var type = node.nodeName.toLowerCase(),
-			isElement = type !== '#document',
-			body = document.body,
-			container,
-			parent,
-			next;
-		if (isRoot && isElement) {
-			rootSize = getSize(node, null, null, true)
-					|| paper.getView().getSize();
-			container = SvgElement.create('svg', {
-				style: 'stroke-width: 1px; stroke-miterlimit: 10'
-			});
-			parent = node.parentNode;
-			next = node.nextSibling;
-			container.appendChild(node);
-			body.appendChild(container);
-		}
-		var settings = paper.settings,
-			applyMatrix = settings.applyMatrix,
-			insertItems = settings.insertItems;
-		settings.applyMatrix = false;
-		settings.insertItems = false;
-		var importer = importers[type],
-			item = importer && importer(node, type, options, isRoot) || null;
-		settings.insertItems = insertItems;
-		settings.applyMatrix = applyMatrix;
-		if (item) {
-			if (isElement && !(item instanceof Group))
-				item = applyAttributes(item, node, isRoot);
-			var onImport = options.onImport,
-				data = isElement && node.getAttribute('data-paper-data');
-			if (onImport)
-				item = onImport(node, item, options) || item;
-			if (options.expandShapes && item instanceof Shape) {
-				item.remove();
-				item = item.toPath();
-			}
-			if (data)
-				item._data = JSON.parse(data);
-		}
-		if (container) {
-			body.removeChild(container);
-			if (parent) {
-				if (next) {
-					parent.insertBefore(node, next);
-				} else {
-					parent.appendChild(node);
-				}
-			}
-		}
-		if (isRoot) {
-			definitions = {};
-			if (item && Base.pick(options.applyMatrix, applyMatrix))
-				item.matrix.apply(true, true);
-		}
-		return item;
-	}
-
-	function importSVG(source, options, owner) {
-		if (!source)
-			return null;
-		options = typeof options === 'function' ? { onLoad: options }
-				: options || {};
-		var scope = paper,
-			item = null;
-
-		function onLoad(svg) {
-			try {
-				var node = typeof svg === 'object' ? svg : new window.DOMParser()
-						.parseFromString(svg, 'image/svg+xml');
-				if (!node.nodeName) {
-					node = null;
-					throw new Error('Unsupported SVG source: ' + source);
-				}
-				paper = scope;
-				item = importNode(node, options, true);
-				if (!options || options.insert !== false) {
-					owner._insertItem(undefined, item);
-				}
-				var onLoad = options.onLoad;
-				if (onLoad)
-					onLoad(item, svg);
-			} catch (e) {
-				onError(e);
-			}
-		}
-
-		function onError(message, status) {
-			var onError = options.onError;
-			if (onError) {
-				onError(message, status);
-			} else {
-				throw new Error(message);
-			}
-		}
-
-		if (typeof source === 'string' && !/^.*</.test(source)) {
-			var node = document.getElementById(source);
-			if (node) {
-				onLoad(node);
-			} else {
-				Http.request({
-					url: source,
-					async: true,
-					onLoad: onLoad,
-					onError: onError
-				});
-			}
-		} else if (typeof File !== 'undefined' && source instanceof File) {
-			var reader = new FileReader();
-			reader.onload = function() {
-				onLoad(reader.result);
-			};
-			reader.onerror = function() {
-				onError(reader.error);
-			};
-			return reader.readAsText(source);
-		} else {
-			onLoad(source);
-		}
-
-		return item;
-	}
-
-	Item.inject({
-		importSVG: function(node, options) {
-			return importSVG(node, options, this);
-		}
-	});
-
-	Project.inject({
-		importSVG: function(node, options) {
-			this.activate();
-			return importSVG(node, options, this);
-		}
-	});
-};
-
-Base.exports.PaperScript = function() {
-	var exports, define,
-		scope = this;
-!function(e,r){return"object"==typeof exports&&"object"==typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):void r(e.acorn||(e.acorn={}))}(this,function(e){"use strict";function r(e){fe=e||{};for(var r in he)Object.prototype.hasOwnProperty.call(fe,r)||(fe[r]=he[r]);me=fe.sourceFile||null}function t(e,r){var t=ve(de,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=be,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;r<e.length;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;a<e.length;++a){for(var o=0;o<n.length;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;a<n.length;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return new Function("str",t)}function a(){this.line=Ae,this.column=be-Se}function o(){Ae=1,be=Se=0,Ee=!0,u()}function i(e,r){ge=be,fe.locations&&(ke=new a),we=e,u(),Ce=r,Ee=e.beforeExpr}function s(){var e=fe.onComment&&fe.locations&&new a,r=be,n=de.indexOf("*/",be+=2);if(-1===n&&t(be-2,"Unterminated comment"),be=n+2,fe.locations){Kr.lastIndex=r;for(var o;(o=Kr.exec(de))&&o.index<be;)++Ae,Se=o.index+o[0].length}fe.onComment&&fe.onComment(!0,de.slice(r+2,n),r,be,e,fe.locations&&new a)}function c(){for(var e=be,r=fe.onComment&&fe.locations&&new a,t=de.charCodeAt(be+=2);pe>be&&10!==t&&13!==t&&8232!==t&&8233!==t;)++be,t=de.charCodeAt(be);fe.onComment&&fe.onComment(!1,de.slice(e+2,be),e,be,r,fe.locations&&new a)}function u(){for(;pe>be;){var e=de.charCodeAt(be);if(32===e)++be;else if(13===e){++be;var r=de.charCodeAt(be);10===r&&++be,fe.locations&&(++Ae,Se=be)}else if(10===e||8232===e||8233===e)++be,fe.locations&&(++Ae,Se=be);else if(e>8&&14>e)++be;else if(47===e){var r=de.charCodeAt(be+1);if(42===r)s();else{if(47!==r)break;c()}}else if(160===e)++be;else{if(!(e>=5760&&Jr.test(String.fromCharCode(e))))break;++be}}}function l(){var e=de.charCodeAt(be+1);return e>=48&&57>=e?E(!0):(++be,i(xr))}function f(){var e=de.charCodeAt(be+1);return Ee?(++be,k()):61===e?x(Er,2):x(wr,1)}function d(){var e=de.charCodeAt(be+1);return 61===e?x(Er,2):x(jr,1)}function p(e){var r=de.charCodeAt(be+1);return r===e?x(124===e?Ir:Lr,2):61===r?x(Er,2):x(124===e?Ur:Rr,1)}function m(){var e=de.charCodeAt(be+1);return 61===e?x(Er,2):x(Fr,1)}function h(e){var r=de.charCodeAt(be+1);return r===e?45==r&&62==de.charCodeAt(be+2)&&Gr.test(de.slice(Le,be))?(be+=3,c(),u(),g()):x(Ar,2):61===r?x(Er,2):x(qr,1)}function v(e){var r=de.charCodeAt(be+1),t=1;return r===e?(t=62===e&&62===de.charCodeAt(be+2)?3:2,61===de.charCodeAt(be+t)?x(Er,t+1):x(Tr,t)):33==r&&60==e&&45==de.charCodeAt(be+2)&&45==de.charCodeAt(be+3)?(be+=4,c(),u(),g()):(61===r&&(t=61===de.charCodeAt(be+2)?3:2),x(Vr,t))}function b(e){var r=de.charCodeAt(be+1);return 61===r?x(Or,61===de.charCodeAt(be+2)?3:2):x(61===e?Cr:Sr,1)}function y(e){switch(e){case 46:return l();case 40:return++be,i(hr);case 41:return++be,i(vr);case 59:return++be,i(yr);case 44:return++be,i(br);case 91:return++be,i(fr);case 93:return++be,i(dr);case 123:return++be,i(pr);case 125:return++be,i(mr);case 58:return++be,i(gr);case 63:return++be,i(kr);case 48:var r=de.charCodeAt(be+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return d();case 124:case 38:return p(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(Sr,1)}return!1}function g(e){if(e?be=ye+1:ye=be,fe.locations&&(xe=new a),e)return k();if(be>=pe)return i(Be);var r=de.charCodeAt(be);if(Qr(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$r.test(o))return L();t(be,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=de.slice(be,be+r);be+=r,i(e,t)}function k(){for(var e,r,n="",a=be;;){be>=pe&&t(a,"Unterminated regular expression");var o=de.charAt(be);if(Gr.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++be}var n=de.slice(a,be);++be;var s=I();s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag");try{var c=new RegExp(n,s)}catch(u){u instanceof SyntaxError&&t(a,u.message),t(u)}return i(qe,c)}function w(e,r){for(var t=be,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=de.charCodeAt(be);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++be,n=n*e+i}return be===t||null!=r&&be-t!==r?null:n}function C(){be+=2;var e=w(16);return null==e&&t(ye+2,"Expected hexadecimal number"),Qr(de.charCodeAt(be))&&t(be,"Identifier directly after number"),i(Te,e)}function E(e){var r=be,n=!1,a=48===de.charCodeAt(be);e||null!==w(10)||t(r,"Invalid number"),46===de.charCodeAt(be)&&(++be,w(10),n=!0);var o=de.charCodeAt(be);69!==o&&101!==o||(o=de.charCodeAt(++be),43!==o&&45!==o||++be,null===w(10)&&t(r,"Invalid number"),n=!0),Qr(de.charCodeAt(be))&&t(be,"Identifier directly after number");var s,c=de.slice(r,be);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Oe?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(Te,s)}function A(e){be++;for(var r="";;){be>=pe&&t(ye,"Unterminated string constant");var n=de.charCodeAt(be);if(n===e)return++be,i(je,r);if(92===n){n=de.charCodeAt(++be);var a=/^[0-7]+/.exec(de.slice(be,be+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,-1);if("0"===a&&(a=null),++be,a)Oe&&t(be-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),be+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+="	";break;case 98:r+="\b";break;case 118:r+="\x0B";break;case 102:r+="\f";break;case 48:r+="\x00";break;case 13:10===de.charCodeAt(be)&&++be;case 10:fe.locations&&(Se=be,++Ae);break;default:r+=String.fromCharCode(n)}}else 13!==n&&10!==n&&8232!==n&&8233!==n||t(ye,"Unterminated string constant"),r+=String.fromCharCode(n),++be}}function S(e){var r=w(16,e);return null===r&&t(ye,"Bad character escape sequence"),r}function I(){Br=!1;for(var e,r=!0,n=be;;){var a=de.charCodeAt(be);if(Yr(a))Br&&(e+=de.charAt(be)),++be;else{if(92!==a)break;Br||(e=de.slice(n,be)),Br=!0,117!=de.charCodeAt(++be)&&t(be,"Expecting Unicode escape sequence \\uXXXX"),++be;var o=S(4),i=String.fromCharCode(o);i||t(be-1,"Invalid Unicode escape"),(r?Qr(o):Yr(o))||t(be-4,"Invalid Unicode escape"),e+=i}r=!1}return Br?e:de.slice(n,be)}function L(){var e=I(),r=De;return!Br&&Wr(e)&&(r=lr[e]),i(r,e)}function U(){Ie=ye,Le=ge,Ue=ke,g()}function F(e){if(Oe=e,be=ye,fe.locations)for(;Se>be;)Se=de.lastIndexOf("\n",Se-2)+1,--Ae;u(),g()}function R(){this.type=null,this.start=ye,this.end=null}function O(){this.start=xe,this.end=null,null!==me&&(this.source=me)}function V(){var e=new R;return fe.locations&&(e.loc=new O),fe.directSourceFile&&(e.sourceFile=fe.directSourceFile),fe.ranges&&(e.range=[ye,0]),e}function T(e){var r=new R;return r.start=e.start,fe.locations&&(r.loc=new O,r.loc.start=e.loc.start),fe.ranges&&(r.range=[e.range[0],0]),r}function q(e,r){return e.type=r,e.end=Le,fe.locations&&(e.loc.end=Ue),fe.ranges&&(e.range[1]=Le),e}function j(e){return fe.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return we===e?(U(),!0):void 0}function B(){return!fe.strictSemicolons&&(we===Be||we===mr||Gr.test(de.slice(Le,ye)))}function M(){D(yr)||B()||X()}function z(e){we===e?U():X()}function X(){t(ye,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Oe&&"Identifier"===e.type&&Nr(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ie=Le=be,fe.locations&&(Ue=new a),Fe=Oe=null,Re=[],g();var r=e||V(),t=!0;for(e||(r.body=[]);we!==Be;){var n=J();r.body.push(n),t&&j(n)&&F(!0),t=!1}return q(r,"Program")}function J(){(we===wr||we===Er&&"/="==Ce)&&g(!0);var e=we,r=V();switch(e){case Me:case Ne:U();var n=e===Me;D(yr)||B()?r.label=null:we!==De?X():(r.label=le(),M());for(var a=0;a<Re.length;++a){var o=Re[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Re.length&&t(r.start,"Unsyntactic "+e.keyword),q(r,n?"BreakStatement":"ContinueStatement");case We:return U(),M(),q(r,"DebuggerStatement");case Pe:return U(),Re.push(Zr),r.body=J(),Re.pop(),z(tr),r.test=P(),M(),q(r,"DoWhileStatement");case _e:if(U(),Re.push(Zr),z(hr),we===yr)return $(r,null);if(we===rr){var i=V();return U(),G(i,!0),q(i,"VariableDeclaration"),1===i.declarations.length&&D(ur)?_(r,i):$(r,i)}var i=K(!1,!0);return D(ur)?(N(i),_(r,i)):$(r,i);case Ge:return U(),ce(r,!0);case Ke:return U(),r.test=P(),r.consequent=J(),r.alternate=D(He)?J():null,q(r,"IfStatement");case Qe:return Fe||fe.allowReturnOutsideFunction||t(ye,"'return' outside of function"),U(),D(yr)||B()?r.argument=null:(r.argument=K(),M()),q(r,"ReturnStatement");case Ye:U(),r.discriminant=P(),r.cases=[],z(pr),Re.push(et);for(var s,c;we!=mr;)if(we===ze||we===Je){var u=we===ze;s&&q(s,"SwitchCase"),r.cases.push(s=V()),s.consequent=[],U(),u?s.test=K():(c&&t(Ie,"Multiple default clauses"),c=!0,s.test=null),z(gr)}else s||X(),s.consequent.push(J());return s&&q(s,"SwitchCase"),U(),Re.pop(),q(r,"SwitchStatement");case Ze:return U(),Gr.test(de.slice(Le,ye))&&t(Le,"Illegal newline after throw"),r.argument=K(),M(),q(r,"ThrowStatement");case er:if(U(),r.block=H(),r.handler=null,we===Xe){var l=V();U(),z(hr),l.param=le(),Oe&&Nr(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(vr),l.guard=null,l.body=H(),r.handler=q(l,"CatchClause")}return r.guardedHandlers=Ve,r.finalizer=D($e)?H():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),q(r,"TryStatement");case rr:return U(),G(r),M(),q(r,"VariableDeclaration");case tr:return U(),r.test=P(),Re.push(Zr),r.body=J(),Re.pop(),q(r,"WhileStatement");case nr:return Oe&&t(ye,"'with' in strict mode"),U(),r.object=P(),r.body=J(),q(r,"WithStatement");case pr:return H();case yr:return U(),q(r,"EmptyStatement");default:var f=Ce,d=K();if(e===De&&"Identifier"===d.type&&D(gr)){for(var a=0;a<Re.length;++a)Re[a].name===f&&t(d.start,"Label '"+f+"' is already declared");var p=we.isLoop?"loop":we===Ye?"switch":null;return Re.push({name:f,kind:p}),r.body=J(),Re.pop(),r.label=d,q(r,"LabeledStatement")}return r.expression=d,M(),q(r,"ExpressionStatement")}}function P(){z(hr);var e=K();return z(vr),e}function H(e){var r,t=V(),n=!0,a=!1;for(t.body=[],z(pr);!D(mr);){var o=J();t.body.push(o),n&&e&&j(o)&&(r=a,F(a=!0)),n=!1}return a&&!r&&F(!1),q(t,"BlockStatement")}function $(e,r){return e.init=r,z(yr),e.test=we===yr?null:K(),z(yr),e.update=we===vr?null:K(),z(vr),e.body=J(),Re.pop(),q(e,"ForStatement")}function _(e,r){return e.left=r,e.right=K(),z(vr),e.body=J(),Re.pop(),q(e,"ForInStatement")}function G(e,r){for(e.declarations=[],e.kind="var";;){var n=V();if(n.id=le(),Oe&&Nr(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(Cr)?K(!0,r):null,e.declarations.push(q(n,"VariableDeclarator")),!D(br))break}return e}function K(e,r){var t=Q(r);if(!e&&we===br){var n=T(t);for(n.expressions=[t];D(br);)n.expressions.push(Q(r));return q(n,"SequenceExpression")}return t}function Q(e){var r=Y(e);if(we.isAssign){var t=T(r);return t.operator=Ce,t.left=r,U(),t.right=Q(e),N(r),q(t,"AssignmentExpression")}return r}function Y(e){var r=Z(e);if(D(kr)){var t=T(r);return t.test=r,t.consequent=K(!0),z(gr),t.alternate=K(!0,e),q(t,"ConditionalExpression")}return r}function Z(e){return ee(re(),-1,e)}function ee(e,r,t){var n=we.binop;if(null!=n&&(!t||we!==ur)&&n>r){var a=T(e);a.left=e,a.operator=Ce;var o=we;U(),a.right=ee(re(),n,t);var i=q(a,o===Ir||o===Lr?"LogicalExpression":"BinaryExpression");return ee(i,r,t)}return e}function re(){if(we.prefix){var e=V(),r=we.isUpdate;return e.operator=Ce,e.prefix=!0,Ee=!0,U(),e.argument=re(),r?N(e.argument):Oe&&"delete"===e.operator&&"Identifier"===e.argument.type&&t(e.start,"Deleting local variable in strict mode"),q(e,r?"UpdateExpression":"UnaryExpression")}for(var n=te();we.postfix&&!B();){var e=T(n);e.operator=Ce,e.prefix=!1,e.argument=n,N(n),U(),n=q(e,"UpdateExpression")}return n}function te(){return ne(ae())}function ne(e,r){if(D(xr)){var t=T(e);return t.object=e,t.property=le(!0),t.computed=!1,ne(q(t,"MemberExpression"),r)}if(D(fr)){var t=T(e);return t.object=e,t.property=K(),t.computed=!0,z(dr),ne(q(t,"MemberExpression"),r)}if(!r&&D(hr)){var t=T(e);return t.callee=e,t.arguments=ue(vr,!1),ne(q(t,"CallExpression"),r)}return e}function ae(){switch(we){case or:var e=V();return U(),q(e,"ThisExpression");case De:return le();case Te:case je:case qe:var e=V();return e.value=Ce,e.raw=de.slice(ye,ge),U(),q(e,"Literal");case ir:case sr:case cr:var e=V();return e.value=we.atomValue,e.raw=we.keyword,U(),q(e,"Literal");case hr:var r=xe,t=ye;U();var n=K();return n.start=t,n.end=ge,fe.locations&&(n.loc.start=r,n.loc.end=ke),fe.ranges&&(n.range=[t,ge]),z(vr),n;case fr:var e=V();return U(),e.elements=ue(dr,!0,!0),q(e,"ArrayExpression");case pr:return ie();case Ge:var e=V();return U(),ce(e,!1);case ar:return oe();default:X()}}function oe(){var e=V();return U(),e.callee=ne(ae(),!0),D(hr)?e.arguments=ue(vr,!1):e.arguments=Ve,q(e,"NewExpression")}function ie(){var e=V(),r=!0,n=!1;for(e.properties=[],U();!D(mr);){if(r)r=!1;else if(z(br),fe.allowTrailingCommas&&D(mr))break;var a,o={key:se()},i=!1;if(D(gr)?(o.value=K(!0),a=o.kind="init"):fe.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=se(),we!==hr&&X(),o.value=ce(V(),!1)):X(),"Identifier"===o.key.type&&(Oe||n))for(var s=0;s<e.properties.length;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Oe&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return q(e,"ObjectExpression")}function se(){return we===Te||we===je?ae():le(!0)}function ce(e,r){we===De?e.id=le():r?X():e.id=null,e.params=[];var n=!0;for(z(hr);!D(vr);)n?n=!1:z(br),e.params.push(le());var a=Fe,o=Re;if(Fe=!0,Re=[],e.body=H(!0),Fe=a,Re=o,Oe||e.body.body.length&&j(e.body.body[0]))for(var i=e.id?-1:0;i<e.params.length;++i){var s=0>i?e.id:e.params[i];if((Xr(s.name)||Nr(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return q(e,r?"FunctionDeclaration":"FunctionExpression")}function ue(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(br),r&&fe.allowTrailingCommas&&D(e))break;t&&we===br?n.push(null):n.push(K(!0))}return n}function le(e){var r=V();return e&&"everywhere"==fe.forbidReserved&&(e=!1),we===De?(!e&&(fe.forbidReserved&&(3===fe.ecmaVersion?Mr:zr)(Ce)||Oe&&Xr(Ce))&&-1==de.slice(ye,ge).indexOf("\\")&&t(ye,"The keyword '"+Ce+"' is reserved"),r.name=Ce):e&&we.keyword?r.name=we.keyword:X(),Ee=!1,U(),q(r,"Identifier")}e.version="0.5.0";var fe,de,pe,me;e.parse=function(e,t){return de=String(e),pe=de.length,r(t),o(),W(fe.program)};var he=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,allowReturnOutsideFunction:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null},ve=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kr.lastIndex=n;var a=Kr.exec(e);if(!(a&&a.index<r))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return Le=ge,g(e),a.start=ye,a.end=ge,a.startLoc=xe,a.endLoc=ke,a.type=we,a.value=Ce,a}de=String(e),pe=de.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(be=e,fe.locations){Ae=1,Se=Kr.lastIndex=0;for(var t;(t=Kr.exec(de))&&t.index<e;)++Ae,Se=t.index+t[0].length}Ee=r,u()},n};var be,ye,ge,xe,ke,we,Ce,Ee,Ae,Se,Ie,Le,Ue,Fe,Re,Oe,Ve=[],Te={type:"num"},qe={type:"regexp"},je={type:"string"},De={type:"name"},Be={type:"eof"},Me={keyword:"break"},ze={keyword:"case",beforeExpr:!0},Xe={keyword:"catch"},Ne={keyword:"continue"},We={keyword:"debugger"},Je={keyword:"default"},Pe={keyword:"do",isLoop:!0},He={keyword:"else",beforeExpr:!0},$e={keyword:"finally"},_e={keyword:"for",isLoop:!0},Ge={keyword:"function"},Ke={keyword:"if"},Qe={keyword:"return",beforeExpr:!0},Ye={keyword:"switch"},Ze={keyword:"throw",beforeExpr:!0},er={keyword:"try"},rr={keyword:"var"},tr={keyword:"while",isLoop:!0},nr={keyword:"with"},ar={keyword:"new",beforeExpr:!0},or={keyword:"this"},ir={keyword:"null",atomValue:null},sr={keyword:"true",atomValue:!0},cr={keyword:"false",atomValue:!1},ur={keyword:"in",binop:7,beforeExpr:!0},lr={"break":Me,"case":ze,"catch":Xe,"continue":Ne,"debugger":We,"default":Je,"do":Pe,"else":He,"finally":$e,"for":_e,"function":Ge,"if":Ke,"return":Qe,"switch":Ye,"throw":Ze,"try":er,"var":rr,"while":tr,"with":nr,"null":ir,"true":sr,"false":cr,"new":ar,"in":ur,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":or,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},fr={type:"[",beforeExpr:!0},dr={type:"]"},pr={type:"{",beforeExpr:!0},mr={type:"}"},hr={type:"(",beforeExpr:!0},vr={type:")"},br={type:",",beforeExpr:!0},yr={type:";",beforeExpr:!0},gr={type:":",beforeExpr:!0},xr={type:"."},kr={type:"?",beforeExpr:!0},wr={binop:10,beforeExpr:!0},Cr={isAssign:!0,beforeExpr:!0},Er={isAssign:!0,beforeExpr:!0},Ar={postfix:!0,prefix:!0,isUpdate:!0},Sr={prefix:!0,beforeExpr:!0},Ir={binop:1,beforeExpr:!0},Lr={binop:2,beforeExpr:!0},Ur={binop:3,beforeExpr:!0},Fr={binop:4,beforeExpr:!0},Rr={binop:5,beforeExpr:!0},Or={binop:6,beforeExpr:!0},Vr={binop:7,beforeExpr:!0},Tr={binop:8,beforeExpr:!0},qr={binop:9,prefix:!0,beforeExpr:!0},jr={binop:10,beforeExpr:!0};e.tokTypes={bracketL:fr,bracketR:dr,braceL:pr,braceR:mr,parenL:hr,parenR:vr,comma:br,semi:yr,colon:gr,dot:xr,question:kr,slash:wr,eq:Cr,name:De,eof:Be,num:Te,regexp:qe,string:je};for(var Dr in lr)e.tokTypes["_"+Dr]=lr[Dr];var Br,Mr=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),zr=n("class enum extends super const export import"),Xr=n("implements interface let package private protected public static yield"),Nr=n("eval arguments"),Wr=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Jr=/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/,Pr="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",Hr="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$r=new RegExp("["+Pr+"]"),_r=new RegExp("["+Pr+Hr+"]"),Gr=/[\n\r\u2028\u2029]/,Kr=/\r\n|[\n\r\u2028\u2029]/g,Qr=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$r.test(String.fromCharCode(e))},Yr=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&_r.test(String.fromCharCode(e))},Zr={kind:"loop"},et={kind:"switch"}});
-
-	var binaryOperators = {
-		'+': '__add',
-		'-': '__subtract',
-		'*': '__multiply',
-		'/': '__divide',
-		'%': '__modulo',
-		'==': '__equals',
-		'!=': '__equals'
-	};
-
-	var unaryOperators = {
-		'-': '__negate',
-		'+': null
-	};
-
-	var fields = Base.each(
-		['add', 'subtract', 'multiply', 'divide', 'modulo', 'equals', 'negate'],
-		function(name) {
-			this['__' + name] = '#' + name;
-		},
-		{}
-	);
-	Point.inject(fields);
-	Size.inject(fields);
-	Color.inject(fields);
-
-	function __$__(left, operator, right) {
-		var handler = binaryOperators[operator];
-		if (left && left[handler]) {
-			var res = left[handler](right);
-			return operator === '!=' ? !res : res;
-		}
-		switch (operator) {
-		case '+': return left + right;
-		case '-': return left - right;
-		case '*': return left * right;
-		case '/': return left / right;
-		case '%': return left % right;
-		case '==': return left == right;
-		case '!=': return left != right;
-		}
-	}
-
-	function $__(operator, value) {
-		var handler = unaryOperators[operator];
-		if (handler && value && value[handler])
-			return value[handler]();
-		switch (operator) {
-		case '+': return +value;
-		case '-': return -value;
-		}
-	}
-
-	function parse(code, options) {
-		return scope.acorn.parse(code, options);
-	}
-
-	function compile(code, options) {
-		if (!code)
-			return '';
-		options = options || {};
-
-		var insertions = [];
-
-		function getOffset(offset) {
-			for (var i = 0, l = insertions.length; i < l; i++) {
-				var insertion = insertions[i];
-				if (insertion[0] >= offset)
-					break;
-				offset += insertion[1];
-			}
-			return offset;
-		}
-
-		function getCode(node) {
-			return code.substring(getOffset(node.range[0]),
-					getOffset(node.range[1]));
-		}
-
-		function getBetween(left, right) {
-			return code.substring(getOffset(left.range[1]),
-					getOffset(right.range[0]));
-		}
-
-		function replaceCode(node, str) {
-			var start = getOffset(node.range[0]),
-				end = getOffset(node.range[1]),
-				insert = 0;
-			for (var i = insertions.length - 1; i >= 0; i--) {
-				if (start > insertions[i][0]) {
-					insert = i + 1;
-					break;
-				}
-			}
-			insertions.splice(insert, 0, [start, str.length - end + start]);
-			code = code.substring(0, start) + str + code.substring(end);
-		}
-
-		function walkAST(node, parent) {
-			if (!node)
-				return;
-			for (var key in node) {
-				if (key === 'range' || key === 'loc')
-					continue;
-				var value = node[key];
-				if (Array.isArray(value)) {
-					for (var i = 0, l = value.length; i < l; i++)
-						walkAST(value[i], node);
-				} else if (value && typeof value === 'object') {
-					walkAST(value, node);
-				}
-			}
-			switch (node.type) {
-			case 'UnaryExpression':
-				if (node.operator in unaryOperators
-						&& node.argument.type !== 'Literal') {
-					var arg = getCode(node.argument);
-					replaceCode(node, '$__("' + node.operator + '", '
-							+ arg + ')');
-				}
-				break;
-			case 'BinaryExpression':
-				if (node.operator in binaryOperators
-						&& node.left.type !== 'Literal') {
-					var left = getCode(node.left),
-						right = getCode(node.right),
-						between = getBetween(node.left, node.right),
-						operator = node.operator;
-					replaceCode(node, '__$__(' + left + ','
-							+ between.replace(new RegExp('\\' + operator),
-								'"' + operator + '"')
-							+ ', ' + right + ')');
-				}
-				break;
-			case 'UpdateExpression':
-			case 'AssignmentExpression':
-				var parentType = parent && parent.type;
-				if (!(
-						parentType === 'ForStatement'
-						|| parentType === 'BinaryExpression'
-							&& /^[=!<>]/.test(parent.operator)
-						|| parentType === 'MemberExpression' && parent.computed
-				)) {
-					if (node.type === 'UpdateExpression') {
-						var arg = getCode(node.argument),
-							exp = '__$__(' + arg + ', "' + node.operator[0]
-									+ '", 1)',
-							str = arg + ' = ' + exp;
-						if (!node.prefix
-								&& (parentType === 'AssignmentExpression'
-									|| parentType === 'VariableDeclarator')) {
-							if (getCode(parent.left || parent.id) === arg)
-								str = exp;
-							str = arg + '; ' + str;
-						}
-						replaceCode(node, str);
-					} else {
-						if (/^.=$/.test(node.operator)
-								&& node.left.type !== 'Literal') {
-							var left = getCode(node.left),
-								right = getCode(node.right);
-							replaceCode(node, left + ' = __$__(' + left + ', "'
-									+ node.operator[0] + '", ' + right + ')');
-						}
-					}
-				}
-				break;
-			}
-		}
-
-		function encodeVLQ(value) {
-			var res = '',
-				base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-			value = (Math.abs(value) << 1) + (value < 0 ? 1 : 0);
-			while (value || !res) {
-				var next = value & (32 - 1);
-				value >>= 5;
-				if (value)
-					next |= 32;
-				res += base64[next];
-			}
-			return res;
-		}
-
-		var url = options.url || '',
-			agent = paper.agent,
-			version = agent.versionNumber,
-			offsetCode = false,
-			sourceMaps = options.sourceMaps,
-			source = options.source || code,
-			lineBreaks = /\r\n|\n|\r/mg,
-			offset = options.offset || 0,
-			map;
-		if (sourceMaps && (agent.chrome && version >= 30
-				|| agent.webkit && version >= 537.76
-				|| agent.firefox && version >= 23
-				|| agent.node)) {
-			if (agent.node) {
-				offset -= 2;
-			} else if (window && url && !window.location.href.indexOf(url)) {
-				var html = document.getElementsByTagName('html')[0].innerHTML;
-				offset = html.substr(0, html.indexOf(code) + 1).match(
-						lineBreaks).length + 1;
-			}
-			offsetCode = offset > 0 && !(
-					agent.chrome && version >= 36 ||
-					agent.safari && version >= 600 ||
-					agent.firefox && version >= 40 ||
-					agent.node);
-			var mappings = ['AA' + encodeVLQ(offsetCode ? 0 : offset) + 'A'];
-			mappings.length = (code.match(lineBreaks) || []).length + 1
-					+ (offsetCode ? offset : 0);
-			map = {
-				version: 3,
-				file: url,
-				names:[],
-				mappings: mappings.join(';AACA'),
-				sourceRoot: '',
-				sources: [url],
-				sourcesContent: [source]
-			};
-		}
-		walkAST(parse(code, { ranges: true }));
-		if (map) {
-			if (offsetCode) {
-				code = new Array(offset + 1).join('\n') + code;
-			}
-			if (/^(inline|both)$/.test(sourceMaps)) {
-				code += "\n//# sourceMappingURL=data:application/json;base64,"
-						+ window.btoa(unescape(encodeURIComponent(
-							JSON.stringify(map))));
-			}
-			code += "\n//# sourceURL=" + (url || 'paperscript');
-		}
-		return {
-			url: url,
-			source: source,
-			code: code,
-			map: map
-		};
-	}
-
-	function execute(code, scope, options) {
-		paper = scope;
-		var view = scope.getView(),
-			tool = /\btool\.\w+|\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\b/
-					.test(code) && !/\bnew\s+Tool\b/.test(code)
-						? new Tool() : null,
-			toolHandlers = tool ? tool._events : [],
-			handlers = ['onFrame', 'onResize'].concat(toolHandlers),
-			params = [],
-			args = [],
-			func,
-			compiled = typeof code === 'object' ? code : compile(code, options);
-		code = compiled.code;
-		function expose(scope, hidden) {
-			for (var key in scope) {
-				if ((hidden || !/^_/.test(key)) && new RegExp('([\\b\\s\\W]|^)'
-						+ key.replace(/\$/g, '\\$') + '\\b').test(code)) {
-					params.push(key);
-					args.push(scope[key]);
-				}
-			}
-		}
-		expose({ __$__: __$__, $__: $__, paper: scope, view: view, tool: tool },
-				true);
-		expose(scope);
-		handlers = Base.each(handlers, function(key) {
-			if (new RegExp('\\s+' + key + '\\b').test(code)) {
-				params.push(key);
-				this.push(key + ': ' + key);
-			}
-		}, []).join(', ');
-		if (handlers)
-			code += '\nreturn { ' + handlers + ' };';
-		var agent = paper.agent;
-		if (document && (agent.chrome
-				|| agent.firefox && agent.versionNumber < 40)) {
-			var script = document.createElement('script'),
-				head = document.head || document.getElementsByTagName('head')[0];
-			if (agent.firefox)
-				code = '\n' + code;
-			script.appendChild(document.createTextNode(
-				'paper._execute = function(' + params + ') {' + code + '\n}'
-			));
-			head.appendChild(script);
-			func = paper._execute;
-			delete paper._execute;
-			head.removeChild(script);
-		} else {
-			func = Function(params, code);
-		}
-		var res = func.apply(scope, args) || {};
-		Base.each(toolHandlers, function(key) {
-			var value = res[key];
-			if (value)
-				tool[key] = value;
-		});
-		if (view) {
-			if (res.onResize)
-				view.setOnResize(res.onResize);
-			view.emit('resize', {
-				size: view.size,
-				delta: new Point()
-			});
-			if (res.onFrame)
-				view.setOnFrame(res.onFrame);
-			view.requestUpdate();
-		}
-		return compiled;
-	}
-
-	function loadScript(script) {
-		if (/^text\/(?:x-|)paperscript$/.test(script.type)
-				&& PaperScope.getAttribute(script, 'ignore') !== 'true') {
-			var canvasId = PaperScope.getAttribute(script, 'canvas'),
-				canvas = document.getElementById(canvasId),
-				src = script.src || script.getAttribute('data-src'),
-				async = PaperScope.hasAttribute(script, 'async'),
-				scopeAttribute = 'data-paper-scope';
-			if (!canvas)
-				throw new Error('Unable to find canvas with id "'
-						+ canvasId + '"');
-			var scope = PaperScope.get(canvas.getAttribute(scopeAttribute))
-						|| new PaperScope().setup(canvas);
-			canvas.setAttribute(scopeAttribute, scope._id);
-			if (src) {
-				Http.request({
-					url: src,
-					async: async,
-					mimeType: 'text/plain',
-					onLoad: function(code) {
-						execute(code, scope, src);
-					}
-				});
-			} else {
-				execute(script.innerHTML, scope, script.baseURI);
-			}
-			script.setAttribute('data-paper-ignore', 'true');
-			return scope;
-		}
-	}
-
-	function loadAll() {
-		Base.each(document && document.getElementsByTagName('script'),
-				loadScript);
-	}
-
-	function load(script) {
-		return script ? loadScript(script) : loadAll();
-	}
-
-	if (window) {
-		if (document.readyState === 'complete') {
-			setTimeout(loadAll);
-		} else {
-			DomEvent.add(window, { load: loadAll });
-		}
-	}
-
-	return {
-		compile: compile,
-		execute: execute,
-		load: load,
-		parse: parse
-	};
-
-}.call(this);
-
-paper = new (PaperScope.inject(Base.exports, {
-	enumerable: true,
-	Base: Base,
-	Numerical: Numerical,
-	Key: Key,
-	DomEvent: DomEvent,
-	DomElement: DomElement,
-	document: document,
-	window: window,
-	Symbol: SymbolDefinition,
-	PlacedSymbol: SymbolItem
-}))();
-
-if (paper.agent.node)
-	require('./node/extend')(paper);
-
-if (typeof define === 'function' && define.amd) {
-	define('paper', paper);
-} else if (typeof module === 'object' && module) {
-	module.exports = paper;
-}
-
-return paper;
-}.call(this, typeof self === 'object' ? self : null);
diff --git a/dist/paper-full.js b/dist/paper-full.js
new file mode 120000
index 00000000..37e257c7
--- /dev/null
+++ b/dist/paper-full.js
@@ -0,0 +1 @@
+../src/load.js
\ No newline at end of file
diff --git a/dist/paper-full.min.js b/dist/paper-full.min.js
deleted file mode 100644
index ca636a6b..00000000
--- a/dist/paper-full.min.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/*!
- * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
- * http://paperjs.org/
- *
- * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
- * http://scratchdisk.com/ & http://jonathanpuckey.com/
- *
- * Distributed under the MIT license. See LICENSE file for details.
- *
- * All rights reserved.
- *
- * Date: Sat Jul 9 20:56:58 2016 +0200
- *
- ***
- *
- * Straps.js - Class inheritance library with support for bean-style accessors
- *
- * Copyright (c) 2006 - 2016 Juerg Lehni
- * http://scratchdisk.com/
- *
- * Distributed under the MIT license.
- *
- ***
- *
- * Acorn.js
- * http://marijnhaverbeke.nl/acorn/
- *
- * Acorn is a tiny, fast JavaScript parser written in JavaScript,
- * created by Marijn Haverbeke and released under an MIT license.
- *
- */
-var paper=function(t,e){var n=t?t.window:require("./node/window"),i=n&&n.document;t=t||n;var r=new function(){function t(t,e,n,i,a){function o(s,o){o=o||(o=u(e,s))&&(o.get?o:o.value),"string"==typeof o&&"#"===o[0]&&(o=t[o.substring(1)]||o);var l,f="function"==typeof o,d=o,_=a||f&&!o.base?o&&o.get?s in t:t[s]:null;a&&_||(f&&_&&(o.base=_),f&&i!==!1&&(l=s.match(/^([gs]et|is)(([A-Z])(.*))$/))&&(h[l[3].toLowerCase()+l[4]]=l[2]),d&&!f&&d.get&&"function"==typeof d.get&&r.isPlainObject(d)||(d={value:d,writable:!0}),(u(t,s)||{configurable:!0}).configurable&&(d.configurable=!0,d.enumerable=n),c(t,s,d))}var h={};if(e){for(var l in e)e.hasOwnProperty(l)&&!s.test(l)&&o(l);for(var l in h){var f=h[l],d=t["set"+f],_=t["get"+f]||d&&t["is"+f];!_||i!==!0&&0!==_.length||o(l,{get:_,set:d})}}return t}function n(t,e,n){return t&&("length"in t&&!t.getLength&&"number"==typeof t.length?a:o).call(t,e,n=n||t),n}function i(t,e,n){for(var i=n,r=e.length;i<r;i++){var s=e[i];for(var a in s)s.hasOwnProperty(a)&&(t[a]=s[a])}return t}var s=/^(statics|enumerable|beans|preserve)$/,a=[].forEach||function(t,e){for(var n=0,i=this.length;n<i;n++)t.call(e,this[n],n,this)},o=function(t,e){for(var n in this)this.hasOwnProperty(n)&&t.call(e,this[n],n,this)},h=Object.create||function(t){return{__proto__:t}},u=Object.getOwnPropertyDescriptor||function(t,e){var n=t.__lookupGetter__&&t.__lookupGetter__(e);return n?{get:n,set:t.__lookupSetter__(e),enumerable:!0,configurable:!0}:t.hasOwnProperty(e)?{value:t[e],enumerable:!0,configurable:!0,writable:!0}:null},l=Object.defineProperty||function(t,e,n){return(n.get||n.set)&&t.__defineGetter__?(n.get&&t.__defineGetter__(e,n.get),n.set&&t.__defineSetter__(e,n.set)):t[e]=n.value,t},c=function(t,e,n){return delete t[e],l(t,e,n)};return t(function(){i(this,arguments,0)},{inject:function(e){if(e){var n=e.statics===!0?e:e.statics,i=e.beans,r=e.preserve;n!==e&&t(this.prototype,e,e.enumerable,i,r),t(this,n,!0,i,r)}for(var s=1,a=arguments.length;s<a;s++)this.inject(arguments[s]);return this},extend:function(){for(var e,n,i,r=this,s=0,a=arguments.length;s<a&&(!e||!n);s++)i=arguments[s],e=e||i.initialize,n=n||i.prototype;return e=e||function(){r.apply(this,arguments)},n=e.prototype=n||h(this.prototype),c(n,"constructor",{value:e,writable:!0,configurable:!0}),t(e,this,!0),arguments.length&&this.inject.apply(e,arguments),e.base=r,e}},!0).inject({inject:function(){for(var e=0,n=arguments.length;e<n;e++){var i=arguments[e];i&&t(this,i,i.enumerable,i.beans,i.preserve)}return this},extend:function(){var t=h(this);return t.inject.apply(t,arguments)},each:function(t,e){return n(this,t,e)},set:function(){return i(this,arguments,0)},clone:function(){return new this.constructor(this)},statics:{each:n,create:h,define:c,describe:u,set:function(t){return i(t,arguments,1)},clone:function(t){return i(new t.constructor,arguments,0)},isPlainObject:function(t){var e=null!=t&&t.constructor;return e&&(e===Object||e===r||"Object"===e.name)},pick:function(t,n){return t!==e?t:n}}})};"undefined"!=typeof module&&(module.exports=r),r.inject({toString:function(){return null!=this._id?(this._class||"Object")+(this._name?" '"+this._name+"'":" @"+this._id):"{ "+r.each(this,function(t,e){if(!/^_/.test(e)){var n=typeof t;this.push(e+": "+("number"===n?h.instance.number(t):"string"===n?"'"+t+"'":t))}},[]).join(", ")+" }"},getClassName:function(){return this._class||""},importJSON:function(t){return r.importJSON(t,this)},exportJSON:function(t){return r.exportJSON(this,t)},toJSON:function(){return r.serialize(this)},_set:function(t){if(t&&r.isPlainObject(t))return r.filter(this,t)},statics:{exports:{enumerable:!0},extend:function rt(){var t=rt.base.apply(this,arguments),e=t.prototype._class;return e&&!r.exports[e]&&(r.exports[e]=t),t},equals:function(t,e){if(t===e)return!0;if(t&&t.equals)return t.equals(e);if(e&&e.equals)return e.equals(t);if(t&&e&&"object"==typeof t&&"object"==typeof e){if(Array.isArray(t)&&Array.isArray(e)){var n=t.length;if(n!==e.length)return!1;for(;n--;)if(!r.equals(t[n],e[n]))return!1}else{var i=Object.keys(t),n=i.length;if(n!==Object.keys(e).length)return!1;for(;n--;){var s=i[n];if(!e.hasOwnProperty(s)||!r.equals(t[s],e[s]))return!1}}return!0}return!1},read:function(t,n,i,s){if(this===r){var a=this.peek(t,n);return t.__index++,a}var o=this.prototype,h=o._readIndex,u=n||h&&t.__index||0;s||(s=t.length-u);var l=t[u];return l instanceof this||i&&i.readNull&&null==l&&s<=1?(h&&(t.__index=u+1),l&&i&&i.clone?l.clone():l):(l=r.create(this.prototype),h&&(l.__read=!0),l=l.initialize.apply(l,u>0||s<t.length?Array.prototype.slice.call(t,u,u+s):t)||l,h&&(t.__index=u+l.__read,l.__read=e),l)},peek:function(t,e){return t[t.__index=e||t.__index||0]},remain:function(t){return t.length-(t.__index||0)},readAll:function(t,e,n){for(var i,r=[],s=e||0,a=t.length;s<a;s++)r.push(Array.isArray(i=t[s])?this.read(i,0,n):this.read(t,s,n,1));return r},readNamed:function(t,n,i,s,a){var o=this.getNamed(t,n),h=o!==e;if(h){var u=t._filtered;u||(u=t._filtered=r.create(t[0]),u._filtering=t[0]),u[n]=e}return this.read(h?[o]:t,i,s,a)},getNamed:function(t,n){var i=t[0];if(t._hasObject===e&&(t._hasObject=1===t.length&&r.isPlainObject(i)),t._hasObject)return n?i[n]:t._filtered||i},hasNamed:function(t,e){return!!this.getNamed(t,e)},filter:function(t,n,i){for(var r=Object.keys(n._filtering||n),s=0,a=r.length;s<a;s++){var o=r[s];if(!i||!i[o]){var h=n[o];h!==e&&(t[o]=h)}}return t},isPlainValue:function(t,e){return this.isPlainObject(t)||Array.isArray(t)||e&&"string"==typeof t},serialize:function(t,e,n,i){e=e||{};var s,a=!i;if(a&&(e.formatter=new h(e.precision),i={length:0,definitions:{},references:{},add:function(t,e){var n="#"+t._id,i=this.references[n];if(!i){this.length++;var r=e.call(t),s=t._class;s&&r[0]!==s&&r.unshift(s),this.definitions[n]=r,i=this.references[n]=[n]}return i}}),t&&t._serialize){s=t._serialize(e,i);var o=t._class;!o||t._compactSerialize||!a&&n||s[0]===o||s.unshift(o)}else if(Array.isArray(t)){s=[];for(var u=0,l=t.length;u<l;u++)s[u]=r.serialize(t[u],e,n,i)}else if(r.isPlainObject(t)){s={};for(var c=Object.keys(t),u=0,l=c.length;u<l;u++){var f=c[u];s[f]=r.serialize(t[f],e,n,i)}}else s="number"==typeof t?e.formatter.number(t,e.precision):t;return a&&i.length>0?[["dictionary",i.definitions],s]:s},deserialize:function(t,e,n,i,s){var a=t,o=!n,h=o&&t&&t.length&&"dictionary"===t[0][0];if(n=n||{},Array.isArray(t)){var u=t[0],l="dictionary"===u;if(1==t.length&&/^#/.test(u))return n.dictionary[u];u=r.exports[u],a=[];for(var c=u?1:0,f=t.length;c<f;c++)a.push(r.deserialize(t[c],e,n,l,h));if(u){var d=a;e?a=e(u,d,o||s):(a=r.create(u.prototype),u.apply(a,d))}}else if(r.isPlainObject(t)){a={},i&&(n.dictionary=a);for(var _ in t)a[_]=r.deserialize(t[_],e,n)}return h?a[1]:a},exportJSON:function(t,e){var n=r.serialize(t,e);return e&&e.asString===!1?n:JSON.stringify(n)},importJSON:function(t,e){return r.deserialize("string"==typeof t?JSON.parse(t):t,function(t,n,i){var s=i&&e&&e.constructor===t,a=s?e:r.create(t.prototype);if(1===n.length&&a instanceof w&&(s||!(a instanceof b))){var o=n[0];r.isPlainObject(o)&&(o.insert=!1)}return(s?a._set:t).apply(a,n),s&&(e=null),a})},splice:function(t,n,i,r){var s=n&&n.length,a=i===e;i=a?t.length:i,i>t.length&&(i=t.length);for(var o=0;o<s;o++)n[o]._index=i+o;if(a)return t.push.apply(t,n),[];var h=[i,r];n&&h.push.apply(h,n);for(var u=t.splice.apply(t,h),o=0,l=u.length;o<l;o++)u[o]._index=e;for(var o=i+s,l=t.length;o<l;o++)t[o]._index=o;return u},capitalize:function(t){return t.replace(/\b[a-z]/g,function(t){return t.toUpperCase()})},camelize:function(t){return t.replace(/-(.)/g,function(t,e){return e.toUpperCase()})},hyphenate:function(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}}});var s={on:function(t,e){if("string"!=typeof t)r.each(t,function(t,e){this.on(e,t)},this);else{var n=this._eventTypes,i=n&&n[t],s=this._callbacks=this._callbacks||{};s=s[t]=s[t]||[],s.indexOf(e)===-1&&(s.push(e),i&&i.install&&1===s.length&&i.install.call(this,t))}return this},off:function(t,e){if("string"!=typeof t)return void r.each(t,function(t,e){this.off(e,t)},this);var n,i=this._eventTypes,s=i&&i[t],a=this._callbacks&&this._callbacks[t];return a&&(!e||(n=a.indexOf(e))!==-1&&1===a.length?(s&&s.uninstall&&s.uninstall.call(this,t),delete this._callbacks[t]):n!==-1&&a.splice(n,1)),this},once:function(t,e){return this.on(t,function(){e.apply(this,arguments),this.off(t,e)})},emit:function(t,e){var n=this._callbacks&&this._callbacks[t];if(!n)return!1;var i=[].slice.call(arguments,1),r=e&&e.target&&!e.currentTarget;n=n.slice(),r&&(e.currentTarget=this);for(var s=0,a=n.length;s<a;s++)if(n[s].apply(this,i)===!1){e&&e.stop&&e.stop();break}return r&&delete e.currentTarget,!0},responds:function(t){return!(!this._callbacks||!this._callbacks[t])},attach:"#on",detach:"#off",fire:"#emit",_installEvents:function(t){var e=this._eventTypes,n=this._callbacks,i=t?"install":"uninstall";if(e)for(var r in n)if(n[r].length>0){var s=e[r],a=s&&s[i];a&&a.call(this,r)}},statics:{inject:function st(t){var e=t._events;if(e){var n={};r.each(e,function(e,i){var s="string"==typeof e,a=s?e:i,o=r.capitalize(a),h=a.substring(2).toLowerCase();n[h]=s?{}:e,a="_"+a,t["get"+o]=function(){return this[a]},t["set"+o]=function(t){var e=this[a];e&&this.off(h,e),t&&this.on(h,t),this[a]=t}}),t._eventTypes=n}return st.base.apply(this,arguments)}}},a=r.extend({_class:"PaperScope",initialize:function at(){paper=this,this.settings=new r({applyMatrix:!0,insertItems:!0,handleSize:4,hitTolerance:0}),this.project=null,this.projects=[],this.tools=[],this.palettes=[],this._id=at._id++,at._scopes[this._id]=this;var e=at.prototype;if(!this.support){var n=tt.getContext(1,1)||{};e.support={nativeDash:"setLineDash"in n||"mozDash"in n,nativeBlendModes:et.nativeModes},tt.release(n)}if(!this.agent){var i=t.navigator.userAgent.toLowerCase(),s=(/(darwin|win|mac|linux|freebsd|sunos)/.exec(i)||[])[0],a="darwin"===s?"mac":s,o=e.agent=e.browser={platform:a};a&&(o[a]=!0),i.replace(/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,function(t,e,n,i,r){if(!o.chrome){var s="opera"===e?i:/^(node|trident)$/.test(e)?r:n;o.version=s,o.versionNumber=parseFloat(s),e="trident"===e?"msie":e,o.name=e,o[e]=!0}}),o.chrome&&delete o.webkit,o.atom&&delete o.chrome}},version:"0.10.2",getView:function(){var t=this.project;return t&&t._view},getPaper:function(){return this},execute:function(t,e){paper.PaperScript.execute(t,this,e),Z.updateFocus()},install:function(t){var e=this;r.each(["project","view","tool"],function(n){r.define(t,n,{configurable:!0,get:function(){return e[n]}})});for(var n in this)!/^_/.test(n)&&this[n]&&(t[n]=this[n])},setup:function(t){return paper=this,this.project=new y(t),this},createCanvas:function(t,e){return tt.getCanvas(t,e)},activate:function(){paper=this},clear:function(){for(var t=this.projects,e=this.tools,n=this.palettes,i=t.length-1;i>=0;i--)t[i].remove();for(var i=e.length-1;i>=0;i--)e[i].remove();for(var i=n.length-1;i>=0;i--)n[i].remove()},remove:function(){this.clear(),delete a._scopes[this._id]},statics:new function(){function t(t){return t+="Attribute",function(e,n){return e[t](n)||e[t]("data-paper-"+n)}}return{_scopes:{},_id:0,get:function(t){return this._scopes[t]||null},getAttribute:t("get"),hasAttribute:t("has")}}}),o=r.extend(s,{initialize:function(t){this._scope=paper,this._index=this._scope[this._list].push(this)-1,!t&&this._scope[this._reference]||this.activate()},activate:function(){if(!this._scope)return!1;var t=this._scope[this._reference];return t&&t!==this&&t.emit("deactivate"),this._scope[this._reference]=this,this.emit("activate",t),!0},isActive:function(){return this._scope[this._reference]===this},remove:function(){return null!=this._index&&(r.splice(this._scope[this._list],null,this._index,1),this._scope[this._reference]==this&&(this._scope[this._reference]=null),this._scope=null,!0)},getView:function(){return this._scope.getView()}}),h=r.extend({initialize:function(t){this.precision=r.pick(t,5),this.multiplier=Math.pow(10,this.precision)},number:function(t){return this.precision<16?Math.round(t*this.multiplier)/this.multiplier:t},pair:function(t,e,n){return this.number(t)+(n||",")+this.number(e)},point:function(t,e){return this.number(t.x)+(e||",")+this.number(t.y)},size:function(t,e){return this.number(t.width)+(e||",")+this.number(t.height)},rectangle:function(t,e){return this.point(t,e)+(e||",")+this.size(t,e)}});h.instance=new h;var u=new function(){function t(t,e,n){return t<e?e:t>n?n:t}function e(t,e,n){function i(t){var e=134217729*t,n=t-e,i=n+e,r=t-i;return[i,r]}var r=e*e-t*n,a=e*e+t*n;if(3*s(r)<a){var o=i(t),h=i(e),u=i(n),l=e*e,c=h[0]*h[0]-l+2*h[0]*h[1]+h[1]*h[1],f=t*n,d=o[0]*u[0]-f+o[0]*u[1]+o[1]*u[0]+o[1]*u[1];r=l-f+(c-d)}return r}function n(){var t=Math.max.apply(Math,arguments);return t&&(t<1e-8||t>1e8)?o(2,-Math.round(h(t))):0}var i=[[.5773502691896257],[0,.7745966692414834],[.33998104358485626,.8611363115940526],[0,.5384693101056831,.906179845938664],[.2386191860831969,.6612093864662645,.932469514203152],[0,.4058451513773972,.7415311855993945,.9491079123427585],[.1834346424956498,.525532409916329,.7966664774136267,.9602898564975363],[0,.3242534234038089,.6133714327005904,.8360311073266358,.9681602395076261],[.14887433898163122,.4333953941292472,.6794095682990244,.8650633666889845,.9739065285171717],[0,.26954315595234496,.5190961292068118,.7301520055740494,.8870625997680953,.978228658146057],[.1252334085114689,.3678314989981802,.5873179542866175,.7699026741943047,.9041172563704749,.9815606342467192],[0,.2304583159551348,.44849275103644687,.6423493394403402,.8015780907333099,.9175983992229779,.9841830547185881],[.10805494870734367,.31911236892788974,.5152486363581541,.6872929048116855,.827201315069765,.9284348836635735,.9862838086968123],[0,.20119409399743451,.3941513470775634,.5709721726085388,.7244177313601701,.8482065834104272,.937273392400706,.9879925180204854],[.09501250983763744,.2816035507792589,.45801677765722737,.6178762444026438,.755404408355003,.8656312023878318,.9445750230732326,.9894009349916499]],r=[[1],[.8888888888888888,.5555555555555556],[.6521451548625461,.34785484513745385],[.5688888888888889,.47862867049936647,.23692688505618908],[.46791393457269104,.3607615730481386,.17132449237917036],[.4179591836734694,.3818300505051189,.27970539148927664,.1294849661688697],[.362683783378362,.31370664587788727,.22238103445337448,.10122853629037626],[.3302393550012598,.31234707704000286,.26061069640293544,.1806481606948574,.08127438836157441],[.29552422471475287,.26926671930999635,.21908636251598204,.1494513491505806,.06667134430868814],[.2729250867779006,.26280454451024665,.23319376459199048,.18629021092773426,.1255803694649046,.05566856711617366],[.24914704581340277,.2334925365383548,.20316742672306592,.16007832854334622,.10693932599531843,.04717533638651183],[.2325515532308739,.22628318026289723,.2078160475368885,.17814598076194574,.13887351021978725,.09212149983772845,.04048400476531588],[.2152638534631578,.2051984637212956,.18553839747793782,.15720316715819355,.12151857068790319,.08015808715976021,.03511946033175186],[.2025782419255613,.19843148532711158,.1861610000155622,.16626920581699392,.13957067792615432,.10715922046717194,.07036604748810812,.03075324199611727],[.1894506104550685,.18260341504492358,.16915651939500254,.14959598881657674,.12462897125553388,.09515851168249279,.062253523938647894,.027152459411754096]],s=Math.abs,a=Math.sqrt,o=Math.pow,h=Math.log2||function(t){return Math.log(t)*Math.LOG2E},l=1e-12,c=1.12e-16;return{TOLERANCE:1e-6,EPSILON:l,MACHINE_EPSILON:c,CURVETIME_EPSILON:4e-7,GEOMETRIC_EPSILON:2e-7,WINDING_EPSILON:2e-7,TRIGONOMETRIC_EPSILON:1e-7,CLIPPING_EPSILON:1e-9,KAPPA:4*(a(2)-1)/3,isZero:function(t){return t>=-l&&t<=l},clamp:t,integrate:function(t,e,n,s){for(var a=i[s-2],o=r[s-2],h=.5*(n-e),u=h+e,l=0,c=s+1>>1,f=1&s?o[l++]*t(u):0;l<c;){var d=h*a[l];f+=o[l++]*(t(u+d)+t(u-d))}return h*f},findRoot:function(t,e,n,i,r,a,o){for(var h=0;h<a;h++){var u=t(n),l=u/e(n),c=n-l;if(s(l)<o)return c;u>0?(r=n,n=c<=i?.5*(i+r):c):(i=n,n=c>=r?.5*(i+r):c)}return n},solveQuadratic:function(i,r,o,h,u,f){var d,_=1/0;if(s(i)<l){if(s(r)<l)return s(o)<l?-1:0;d=-o/r}else{r*=-.5;var g=e(i,r,o);if(g&&s(g)<c){var v=n(s(i),s(r),s(o));v&&(i*=v,r*=v,o*=v,g=e(i,r,o))}if(g>=-c){var p=g<0?0:a(g),m=r+(r<0?-p:p);0===m?(d=o/i,_=-d):(d=m/i,_=o/m)}}var y=0,w=null==u,x=u-l,b=f+l;return isFinite(d)&&(w||d>x&&d<b)&&(h[y++]=w?d:t(d,u,f)),_!==d&&isFinite(_)&&(w||_>x&&_<b)&&(h[y++]=w?_:t(_,u,f)),y},solveCubic:function(e,i,r,h,f,d,_){function g(t){v=t;var n=e*v;p=n+i,m=p*v+r,y=(n+p)*v+m,w=m*v+h}var v,p,m,y,w,x=n(s(e),s(i),s(r),s(h));if(x&&(e*=x,i*=x,r*=x,h*=x),s(e)<l)e=i,p=r,m=h,v=1/0;else if(s(h)<l)p=i,m=r,v=0;else{g(-(i/e)/3);var b=w/e,C=o(s(b),1/3),S=b<0?-1:1,k=-y/e,I=k>0?1.324717957244746*Math.max(C,a(k)):C,P=v-S*I;if(P!==v){do g(P),P=0===y?v:v-w/y/(1+c);while(S*P>S*v);s(e)*v*v>s(h/v)&&(m=-h/v,p=(m-r)/v)}}var M=u.solveQuadratic(e,p,m,f,d,_),A=null==d;return isFinite(v)&&(0===M||M>0&&v!==f[0]&&v!==f[1])&&(A||v>d-l&&v<_+l)&&(f[M++]=A?v:t(v,d,_)),M}}},l={_id:1,_pools:{},get:function(t){if(t){var e=this._pools[t];return e||(e=this._pools[t]={_id:1}),e._id++}return this._id++}},c=r.extend({_class:"Point",_readIndex:!0,initialize:function(t,e){var n=typeof t;if("number"===n){var i="number"==typeof e;this.x=t,this.y=i?e:t,this.__read&&(this.__read=i?2:1)}else if("undefined"===n||null===t)this.x=this.y=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===n?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.x=r[0],this.y=r.length>1?r[1]:r[0]):"x"in r?(this.x=r.x,this.y=r.y):"width"in r?(this.x=r.width,this.y=r.height):"angle"in r?(this.x=r.length,this.y=0,this.setAngle(r.angle)):(this.x=this.y=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.x=t,this.y=e,this},equals:function(t){return this===t||t&&(this.x===t.x&&this.y===t.y||Array.isArray(t)&&this.x===t[0]&&this.y===t[1])||!1},clone:function(){return new c(this.x,this.y)},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y)]},getLength:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},setLength:function(t){if(this.isZero()){var e=this._angle||0;this.set(Math.cos(e)*t,Math.sin(e)*t)}else{var n=t/this.getLength();u.isZero(n)&&this.getAngle(),this.set(this.x*n,this.y*n)}},getAngle:function(){return 180*this.getAngleInRadians.apply(this,arguments)/Math.PI},setAngle:function(t){this.setAngleInRadians.call(this,t*Math.PI/180)},getAngleInDegrees:"#getAngle",setAngleInDegrees:"#setAngle",getAngleInRadians:function(){if(arguments.length){var t=c.read(arguments),e=this.getLength()*t.getLength();if(u.isZero(e))return NaN;var n=this.dot(t)/e;return Math.acos(n<-1?-1:n>1?1:n)}return this.isZero()?this._angle||0:this._angle=Math.atan2(this.y,this.x)},setAngleInRadians:function(t){if(this._angle=t,!this.isZero()){var e=this.getLength();this.set(Math.cos(t)*e,Math.sin(t)*e)}},getQuadrant:function(){return this.x>=0?this.y>=0?1:4:this.y>=0?2:3}},{beans:!1,getDirectedAngle:function(){var t=c.read(arguments);return 180*Math.atan2(this.cross(t),this.dot(t))/Math.PI},getDistance:function(){var t=c.read(arguments),e=t.x-this.x,n=t.y-this.y,i=e*e+n*n,s=r.read(arguments);return s?i:Math.sqrt(i)},normalize:function(t){t===e&&(t=1);var n=this.getLength(),i=0!==n?t/n:0,r=new c(this.x*i,this.y*i);return i>=0&&(r._angle=this._angle),r},rotate:function(t,e){if(0===t)return this.clone();t=t*Math.PI/180;var n=e?this.subtract(e):this,i=Math.sin(t),r=Math.cos(t);return n=new c(n.x*r-n.y*i,n.x*i+n.y*r),e?n.add(e):n},transform:function(t){return t?t._transformPoint(this):this},add:function(){var t=c.read(arguments);return new c(this.x+t.x,this.y+t.y)},subtract:function(){var t=c.read(arguments);return new c(this.x-t.x,this.y-t.y)},multiply:function(){var t=c.read(arguments);return new c(this.x*t.x,this.y*t.y)},divide:function(){var t=c.read(arguments);return new c(this.x/t.x,this.y/t.y)},modulo:function(){var t=c.read(arguments);return new c(this.x%t.x,this.y%t.y)},negate:function(){return new c((-this.x),(-this.y))},isInside:function(){return g.read(arguments).contains(this)},isClose:function(){var t=c.read(arguments),e=r.read(arguments);return this.getDistance(t)<=e},isCollinear:function(){var t=c.read(arguments);return c.isCollinear(this.x,this.y,t.x,t.y)},isColinear:"#isCollinear",isOrthogonal:function(){var t=c.read(arguments);return c.isOrthogonal(this.x,this.y,t.x,t.y)},isZero:function(){return u.isZero(this.x)&&u.isZero(this.y)},isNaN:function(){return isNaN(this.x)||isNaN(this.y)},dot:function(){var t=c.read(arguments);return this.x*t.x+this.y*t.y},cross:function(){var t=c.read(arguments);return this.x*t.y-this.y*t.x},project:function(){var t=c.read(arguments),e=t.isZero()?0:this.dot(t)/t.dot(t);return new c(t.x*e,t.y*e)},statics:{min:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.min(t.x,e.x),Math.min(t.y,e.y))},max:function(){var t=c.read(arguments),e=c.read(arguments);return new c(Math.max(t.x,e.x),Math.max(t.y,e.y))},random:function(){return new c(Math.random(),Math.random())},isCollinear:function(t,e,n,i){return Math.abs(t*i-e*n)<=1e-7*Math.sqrt((t*t+e*e)*(n*n+i*i))},isOrthogonal:function(t,e,n,i){return Math.abs(t*n+e*i)<=1e-7*Math.sqrt((t*t+e*e)*(n*n+i*i))}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new c(e(this.x),e(this.y))}},{})),f=c.extend({initialize:function(t,e,n,i){this._x=t,this._y=e,this._owner=n,this._setter=i},set:function(t,e,n){return this._x=t,this._y=e,n||this._owner[this._setter](this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner[this._setter](this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner[this._setter](this)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){return"setPosition"===this._setter?4:0}}),d=r.extend({_class:"Size",_readIndex:!0,initialize:function(t,e){var n=typeof t;if("number"===n){var i="number"==typeof e;this.width=t,this.height=i?e:t,this.__read&&(this.__read=i?2:1)}else if("undefined"===n||null===t)this.width=this.height=0,this.__read&&(this.__read=null===t?1:0);else{var r="string"===n?t.split(/[\s,]+/)||[]:t;Array.isArray(r)?(this.width=r[0],this.height=r.length>1?r[1]:r[0]):"width"in r?(this.width=r.width,this.height=r.height):"x"in r?(this.width=r.x,this.height=r.y):(this.width=this.height=0,this.__read&&(this.__read=0)),this.__read&&(this.__read=1)}},set:function(t,e){return this.width=t,this.height=e,this},equals:function(t){return t===this||t&&(this.width===t.width&&this.height===t.height||Array.isArray(t)&&this.width===t[0]&&this.height===t[1])||!1},clone:function(){return new d(this.width,this.height)},toString:function(){var t=h.instance;return"{ width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.width),e.number(this.height)]},add:function(){var t=d.read(arguments);return new d(this.width+t.width,this.height+t.height)},subtract:function(){var t=d.read(arguments);return new d(this.width-t.width,this.height-t.height)},multiply:function(){var t=d.read(arguments);return new d(this.width*t.width,this.height*t.height)},divide:function(){var t=d.read(arguments);return new d(this.width/t.width,this.height/t.height)},modulo:function(){var t=d.read(arguments);return new d(this.width%t.width,this.height%t.height)},negate:function(){return new d((-this.width),(-this.height))},isZero:function(){return u.isZero(this.width)&&u.isZero(this.height)},isNaN:function(){return isNaN(this.width)||isNaN(this.height)},statics:{min:function(t,e){return new d(Math.min(t.width,e.width),Math.min(t.height,e.height))},max:function(t,e){return new d(Math.max(t.width,e.width),Math.max(t.height,e.height))},random:function(){return new d(Math.random(),Math.random())}}},r.each(["round","ceil","floor","abs"],function(t){var e=Math[t];this[t]=function(){return new d(e(this.width),e(this.height))}},{})),_=d.extend({initialize:function(t,e,n,i){this._width=t,this._height=e,this._owner=n,this._setter=i},set:function(t,e,n){return this._width=t,this._height=e,n||this._owner[this._setter](this),this},getWidth:function(){return this._width},setWidth:function(t){this._width=t,this._owner[this._setter](this)},getHeight:function(){return this._height},setHeight:function(t){this._height=t,this._owner[this._setter](this)}}),g=r.extend({_class:"Rectangle",_readIndex:!0,beans:!0,initialize:function(t,n,i,s){var a=typeof t,o=0;if("number"===a?(this.x=t,this.y=n,this.width=i,this.height=s,o=4):"undefined"===a||null===t?(this.x=this.y=this.width=this.height=0,o=null===t?1:0):1===arguments.length&&(Array.isArray(t)?(this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],o=1):t.x!==e||t.width!==e?(this.x=t.x||0,this.y=t.y||0,this.width=t.width||0,this.height=t.height||0,o=1):t.from===e&&t.to===e&&(this.x=this.y=this.width=this.height=0,this._set(t),o=1)),!o){var h=c.readNamed(arguments,"from"),u=r.peek(arguments);if(this.x=h.x,this.y=h.y,u&&u.x!==e||r.hasNamed(arguments,"to")){var l=c.readNamed(arguments,"to");this.width=l.x-h.x,this.height=l.y-h.y,this.width<0&&(this.x=l.x,this.width=-this.width),this.height<0&&(this.y=l.y,this.height=-this.height)}else{var f=d.read(arguments);this.width=f.width,this.height=f.height}o=arguments.__index}this.__read&&(this.__read=o)},set:function(t,e,n,i){return this.x=t,this.y=e,this.width=n,this.height=i,this},clone:function(){return new g(this.x,this.y,this.width,this.height)},equals:function(t){var e=r.isPlainValue(t)?g.read(arguments):t;return e===this||e&&this.x===e.x&&this.y===e.y&&this.width===e.width&&this.height===e.height||!1},toString:function(){var t=h.instance;return"{ x: "+t.number(this.x)+", y: "+t.number(this.y)+", width: "+t.number(this.width)+", height: "+t.number(this.height)+" }"},_serialize:function(t){var e=t.formatter;return[e.number(this.x),e.number(this.y),e.number(this.width),e.number(this.height)]},getPoint:function(t){var e=t?c:f;return new e(this.x,this.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.x=t.x,this.y=t.y},getSize:function(t){var e=t?d:_;return new e(this.width,this.height,this,"setSize")},setSize:function(){var t=d.read(arguments);this._fixX&&(this.x+=(this.width-t.width)*this._fixX),this._fixY&&(this.y+=(this.height-t.height)*this._fixY),this.width=t.width,this.height=t.height,this._fixW=1,this._fixH=1},getLeft:function(){return this.x},setLeft:function(t){this._fixW||(this.width-=t-this.x),this.x=t,this._fixX=0},getTop:function(){return this.y},setTop:function(t){this._fixH||(this.height-=t-this.y),this.y=t,this._fixY=0},getRight:function(){return this.x+this.width},setRight:function(t){this._fixX!==e&&1!==this._fixX&&(this._fixW=0),this._fixW?this.x=t-this.width:this.width=t-this.x,this._fixX=1},getBottom:function(){return this.y+this.height},setBottom:function(t){this._fixY!==e&&1!==this._fixY&&(this._fixH=0),this._fixH?this.y=t-this.height:this.height=t-this.y,this._fixY=1},getCenterX:function(){return this.x+.5*this.width},setCenterX:function(t){this.x=t-.5*this.width,this._fixX=.5},getCenterY:function(){return this.y+.5*this.height},setCenterY:function(t){this.y=t-.5*this.height,this._fixY=.5},getCenter:function(t){var e=t?c:f;return new e(this.getCenterX(),this.getCenterY(),this,"setCenter")},setCenter:function(){var t=c.read(arguments);return this.setCenterX(t.x),this.setCenterY(t.y),this},getArea:function(){return this.width*this.height},isEmpty:function(){return 0===this.width||0===this.height},contains:function(t){return t&&t.width!==e||4===(Array.isArray(t)?t:arguments).length?this._containsRectangle(g.read(arguments)):this._containsPoint(c.read(arguments))},_containsPoint:function(t){var e=t.x,n=t.y;return e>=this.x&&n>=this.y&&e<=this.x+this.width&&n<=this.y+this.height},_containsRectangle:function(t){var e=t.x,n=t.y;return e>=this.x&&n>=this.y&&e+t.width<=this.x+this.width&&n+t.height<=this.y+this.height},intersects:function(){var t=g.read(arguments);return t.x+t.width>this.x&&t.y+t.height>this.y&&t.x<this.x+this.width&&t.y<this.y+this.height},touches:function(){var t=g.read(arguments);return t.x+t.width>=this.x&&t.y+t.height>=this.y&&t.x<=this.x+this.width&&t.y<=this.y+this.height},intersect:function(){var t=g.read(arguments),e=Math.max(this.x,t.x),n=Math.max(this.y,t.y),i=Math.min(this.x+this.width,t.x+t.width),r=Math.min(this.y+this.height,t.y+t.height);return new g(e,n,i-e,r-n)},unite:function(){var t=g.read(arguments),e=Math.min(this.x,t.x),n=Math.min(this.y,t.y),i=Math.max(this.x+this.width,t.x+t.width),r=Math.max(this.y+this.height,t.y+t.height);return new g(e,n,i-e,r-n)},include:function(){var t=c.read(arguments),e=Math.min(this.x,t.x),n=Math.min(this.y,t.y),i=Math.max(this.x+this.width,t.x),r=Math.max(this.y+this.height,t.y);return new g(e,n,i-e,r-n)},expand:function(){var t=d.read(arguments),e=t.width,n=t.height;return new g(this.x-e/2,this.y-n/2,this.width+e,this.height+n)},scale:function(t,n){return this.expand(this.width*t-this.width,this.height*(n===e?t:n)-this.height)}},r.each([["Top","Left"],["Top","Right"],["Bottom","Left"],["Bottom","Right"],["Left","Center"],["Top","Center"],["Right","Center"],["Bottom","Center"]],function(t,e){var n=t.join(""),i=/^[RL]/.test(n);e>=4&&(t[1]+=i?"Y":"X");var r=t[i?0:1],s=t[i?1:0],a="get"+r,o="get"+s,h="set"+r,u="set"+s,l="get"+n,d="set"+n;this[l]=function(t){var e=t?c:f;return new e(this[a](),this[o](),this,d)},this[d]=function(){var t=c.read(arguments);this[h](t.x),this[u](t.y)}},{beans:!0})),v=g.extend({initialize:function(t,e,n,i,r,s){this.set(t,e,n,i,!0),this._owner=r,this._setter=s},set:function(t,e,n,i,r){return this._x=t,this._y=e,this._width=n,this._height=i,r||this._owner[this._setter](this),this}},new function(){var t=g.prototype;return r.each(["x","y","width","height"],function(t){var e=r.capitalize(t),n="_"+t;this["get"+e]=function(){return this[n]},this["set"+e]=function(t){this[n]=t,this._dontNotify||this._owner[this._setter](this)}},r.each(["Point","Size","Center","Left","Top","Right","Bottom","CenterX","CenterY","TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],function(e){var n="set"+e;this[n]=function(){this._dontNotify=!0,t[n].apply(this,arguments),this._dontNotify=!1,this._owner[this._setter](this)}},{isSelected:function(){return!!(2&this._owner._selection)},setSelected:function(t){var e=this._owner;e.changeSelection&&e.changeSelection(2,t)}}))}),p=r.extend({_class:"Matrix",initialize:function ot(t){var e=arguments.length,n=!0;if(6===e?this.set.apply(this,arguments):1===e?t instanceof ot?this.set(t._a,t._b,t._c,t._d,t._tx,t._ty):Array.isArray(t)?this.set.apply(this,t):n=!1:0===e?this.reset():n=!1,!n)throw new Error("Unsupported matrix parameters")},set:function(t,e,n,i,r,s,a){return this._a=t,this._b=e,this._c=n,this._d=i,this._tx=r,this._ty=s,a||this._changed(),this},_serialize:function(t,e){return r.serialize(this.getValues(),t,!0,e)},_changed:function(){var t=this._owner;t&&(t._applyMatrix?t.transform(null,!0):t._changed(9))},clone:function(){return new p(this._a,this._b,this._c,this._d,this._tx,this._ty)},equals:function(t){return t===this||t&&this._a===t._a&&this._b===t._b&&this._c===t._c&&this._d===t._d&&this._tx===t._tx&&this._ty===t._ty},toString:function(){var t=h.instance;return"[["+[t.number(this._a),t.number(this._c),t.number(this._tx)].join(", ")+"], ["+[t.number(this._b),t.number(this._d),t.number(this._ty)].join(", ")+"]]"},reset:function(t){return this._a=this._d=1,this._b=this._c=this._tx=this._ty=0,t||this._changed(),this},apply:function(t,e){var n=this._owner;return!!n&&(n.transform(null,!0,r.pick(t,!0),e),this.isIdentity())},translate:function(){var t=c.read(arguments),e=t.x,n=t.y;return this._tx+=e*this._a+n*this._c,
-this._ty+=e*this._b+n*this._d,this._changed(),this},scale:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});return e&&this.translate(e),this._a*=t.x,this._b*=t.x,this._c*=t.y,this._d*=t.y,e&&this.translate(e.negate()),this._changed(),this},rotate:function(t){t*=Math.PI/180;var e=c.read(arguments,1),n=e.x,i=e.y,r=Math.cos(t),s=Math.sin(t),a=n-n*r+i*s,o=i-n*s-i*r,h=this._a,u=this._b,l=this._c,f=this._d;return this._a=r*h+s*l,this._b=r*u+s*f,this._c=-s*h+r*l,this._d=-s*u+r*f,this._tx+=a*h+o*l,this._ty+=a*u+o*f,this._changed(),this},shear:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0});e&&this.translate(e);var n=this._a,i=this._b;return this._a+=t.y*this._c,this._b+=t.y*this._d,this._c+=t.x*n,this._d+=t.x*i,e&&this.translate(e.negate()),this._changed(),this},skew:function(){var t=c.read(arguments),e=c.read(arguments,0,{readNull:!0}),n=Math.PI/180,i=new c(Math.tan(t.x*n),Math.tan(t.y*n));return this.shear(i,e)},append:function(t){if(t){var e=this._a,n=this._b,i=this._c,r=this._d,s=t._a,a=t._c,o=t._b,h=t._d,u=t._tx,l=t._ty;this._a=s*e+o*i,this._c=a*e+h*i,this._b=s*n+o*r,this._d=a*n+h*r,this._tx+=u*e+l*i,this._ty+=u*n+l*r,this._changed()}return this},prepend:function(t){if(t){var e=this._a,n=this._b,i=this._c,r=this._d,s=this._tx,a=this._ty,o=t._a,h=t._c,u=t._b,l=t._d,c=t._tx,f=t._ty;this._a=o*e+h*n,this._c=o*i+h*r,this._b=u*e+l*n,this._d=u*i+l*r,this._tx=o*s+h*a+c,this._ty=u*s+l*a+f,this._changed()}return this},appended:function(t){return this.clone().append(t)},prepended:function(t){return this.clone().prepend(t)},invert:function(){var t=this._a,e=this._b,n=this._c,i=this._d,r=this._tx,s=this._ty,a=t*i-e*n,o=null;return a&&!isNaN(a)&&isFinite(r)&&isFinite(s)&&(this._a=i/a,this._b=-e/a,this._c=-n/a,this._d=t/a,this._tx=(n*s-i*r)/a,this._ty=(e*r-t*s)/a,o=this),o},inverted:function(){return this.clone().invert()},concatenate:"#append",preConcatenate:"#prepend",chain:"#appended",_shiftless:function(){return new p(this._a,this._b,this._c,this._d,0,0)},_orNullIfIdentity:function(){return this.isIdentity()?null:this},isIdentity:function(){return 1===this._a&&0===this._b&&0===this._c&&1===this._d&&0===this._tx&&0===this._ty},isInvertible:function(){var t=this._a*this._d-this._c*this._b;return t&&!isNaN(t)&&isFinite(this._tx)&&isFinite(this._ty)},isSingular:function(){return!this.isInvertible()},transform:function(t,e,n){return arguments.length<3?this._transformPoint(c.read(arguments)):this._transformCoordinates(t,e,n)},_transformPoint:function(t,e,n){var i=t.x,r=t.y;return e||(e=new c),e.set(i*this._a+r*this._c+this._tx,i*this._b+r*this._d+this._ty,n)},_transformCoordinates:function(t,e,n){for(var i=0,r=2*n;i<r;i+=2){var s=t[i],a=t[i+1];e[i]=s*this._a+a*this._c+this._tx,e[i+1]=s*this._b+a*this._d+this._ty}return e},_transformCorners:function(t){var e=t.x,n=t.y,i=e+t.width,r=n+t.height,s=[e,n,i,n,i,r,e,r];return this._transformCoordinates(s,s,4)},_transformBounds:function(t,e,n){for(var i=this._transformCorners(t),r=i.slice(0,2),s=r.slice(),a=2;a<8;a++){var o=i[a],h=1&a;o<r[h]?r[h]=o:o>s[h]&&(s[h]=o)}return e||(e=new g),e.set(r[0],r[1],s[0]-r[0],s[1]-r[1],n)},inverseTransform:function(){return this._inverseTransform(c.read(arguments))},_inverseTransform:function(t,e,n){var i=this._a,r=this._b,s=this._c,a=this._d,o=this._tx,h=this._ty,u=i*a-r*s,l=null;if(u&&!isNaN(u)&&isFinite(o)&&isFinite(h)){var f=t.x-this._tx,d=t.y-this._ty;e||(e=new c),l=e.set((f*a-d*s)/u,(d*i-f*r)/u,n)}return l},decompose:function(){var t,e,n,i=this._a,r=this._b,s=this._c,a=this._d,o=i*a-r*s,h=Math.sqrt,u=Math.atan2,l=180/Math.PI;if(0!==i||0!==r){var f=h(i*i+r*r);t=Math.acos(i/f)*(r>0?1:-1),e=[f,o/f],n=[u(i*s+r*a,f*f),0]}else if(0!==s||0!==a){var d=h(s*s+a*a);t=Math.asin(s/d)*(a>0?1:-1),e=[o/d,d],n=[0,u(i*s+r*a,d*d)]}else t=0,n=e=[0,0];return{translation:this.getTranslation(),rotation:t*l,scaling:new c(e),skewing:new c(n[0]*l,n[1]*l)}},getValues:function(){return[this._a,this._b,this._c,this._d,this._tx,this._ty]},getTranslation:function(){return new c(this._tx,this._ty)},getScaling:function(){return(this.decompose()||{}).scaling},getRotation:function(){return(this.decompose()||{}).rotation},applyToContext:function(t){this.isIdentity()||t.transform(this._a,this._b,this._c,this._d,this._tx,this._ty)}},r.each(["a","b","c","d","tx","ty"],function(t){var e=r.capitalize(t),n="_"+t;this["get"+e]=function(){return this[n]},this["set"+e]=function(t){this[n]=t,this._changed()}},{})),m=r.extend({_class:"Line",initialize:function(t,e,n,i,r){var s=!1;arguments.length>=4?(this._px=t,this._py=e,this._vx=n,this._vy=i,s=r):(this._px=t.x,this._py=t.y,this._vx=e.x,this._vy=e.y,s=n),s||(this._vx-=this._px,this._vy-=this._py)},getPoint:function(){return new c(this._px,this._py)},getVector:function(){return new c(this._vx,this._vy)},getLength:function(){return this.getVector().getLength()},intersect:function(t,e){return m.intersect(this._px,this._py,this._vx,this._vy,t._px,t._py,t._vx,t._vy,!0,e)},getSide:function(t,e){return m.getSide(this._px,this._py,this._vx,this._vy,t.x,t.y,!0,e)},getDistance:function(t){return Math.abs(m.getSignedDistance(this._px,this._py,this._vx,this._vy,t.x,t.y,!0))},isCollinear:function(t){return c.isCollinear(this._vx,this._vy,t._vx,t._vy)},isOrthogonal:function(t){return c.isOrthogonal(this._vx,this._vy,t._vx,t._vy)},statics:{intersect:function(t,e,n,i,r,s,a,o,h,l){h||(n-=t,i-=e,a-=r,o-=s);var f=n*o-i*a;if(!u.isZero(f)){var d=t-r,_=e-s,g=(a*_-o*d)/f,v=(n*_-i*d)/f,p=1e-12,m=-p,y=1+p;if(l||m<g&&g<y&&m<v&&v<y)return l||(g=g<=0?0:g>=1?1:g),new c(t+g*n,e+g*i)}},getSide:function(t,e,n,i,r,s,a,o){a||(n-=t,i-=e);var h=r-t,u=s-e,l=h*i-u*n;return 0!==l||o||(l=(h*n+h*n)/(n*n+i*i),l>=0&&l<=1&&(l=0)),l<0?-1:l>0?1:0},getSignedDistance:function(t,e,n,i,r,s,a){return a||(n-=t,i-=e),0===n?i>0?r-t:t-r:0===i?n<0?s-e:e-s:((r-t)*i-(s-e)*n)/Math.sqrt(n*n+i*i)}}}),y=o.extend({_class:"Project",_list:"projects",_reference:"project",_compactSerialize:!0,initialize:function(t){o.call(this,!0),this._children=[],this._namedChildren={},this._activeLayer=null,this._currentStyle=new V(null,null,this),this._view=Z.create(this,t||tt.getCanvas(1,1)),this._selectionItems={},this._selectionCount=0,this._updateVersion=0},_serialize:function(t,e){return r.serialize(this._children,t,!0,e)},_changed:function(t,e){if(1&t){var n=this._view;n&&(n._needsUpdate=!0,!n._requested&&n._autoUpdate&&n.requestUpdate())}var i=this._changes;if(i&&e){var r=this._changesById,s=e._id,a=r[s];a?a.flags|=t:i.push(r[s]={item:e,flags:t})}},clear:function(){for(var t=this._children,e=t.length-1;e>=0;e--)t[e].remove()},isEmpty:function(){return 0===this._children.length},remove:function ht(){return!!ht.base.call(this)&&(this._view&&this._view.remove(),!0)},getView:function(){return this._view},getCurrentStyle:function(){return this._currentStyle},setCurrentStyle:function(t){this._currentStyle.initialize(t)},getIndex:function(){return this._index},getOptions:function(){return this._scope.settings},getLayers:function(){return this._children},getActiveLayer:function(){return this._activeLayer||new b({project:this,insert:!0})},getSymbolDefinitions:function(){var t=[],e={};return this.getItems({"class":k,match:function(n){var i=n._definition,r=i._id;return e[r]||(e[r]=!0,t.push(i)),!1}}),t},getSymbols:"getSymbolDefinitions",getSelectedItems:function(){var t=this._selectionItems,e=[];for(var n in t){var i=t[n],r=i._selection;1&r&&i.isInserted()?e.push(i):r||this._updateSelection(i)}return e},_updateSelection:function(t){var e=t._id,n=this._selectionItems;t._selection?n[e]!==t&&(this._selectionCount++,n[e]=t):n[e]===t&&(this._selectionCount--,delete n[e])},selectAll:function(){for(var t=this._children,e=0,n=t.length;e<n;e++)t[e].setFullySelected(!0)},deselectAll:function(){var t=this._selectionItems;for(var e in t)t[e].setFullySelected(!1)},addLayer:function(t){return this.insertLayer(e,t)},insertLayer:function(t,e){if(e instanceof b){e._remove(!1,!0),r.splice(this._children,[e],t,0),e._setProject(this,!0);var n=e._name;n&&e.setName(n),this._changes&&e._changed(5),this._activeLayer||(this._activeLayer=e)}else e=null;return e},_insertItem:function(t,n,i,r){return n=this.insertLayer(t,n)||(this._activeLayer||this._insertItem(e,new b(w.NO_INSERT),!0,!0)).insertChild(t,n,i),r&&n.activate&&n.activate(),n},getItems:function(t){return w._getItems(this,t)},getItem:function(t){return w._getItems(this,t,null,null,!0)[0]||null},importJSON:function(t){this.activate();var e=this._activeLayer;return r.importJSON(t,e&&e.isEmpty()&&e)},removeOn:function(t){var e=this._removeSets;if(e){"mouseup"===t&&(e.mousedrag=null);var n=e[t];if(n){for(var i in n){var r=n[i];for(var s in e){var a=e[s];a&&a!=n&&delete a[r._id]}r.remove()}e[t]=null}}},draw:function(t,e,n){this._updateVersion++,t.save(),e.applyToContext(t);for(var i=this._children,s=new r({offset:new c(0,0),pixelRatio:n,viewMatrix:e.isIdentity()?null:e,matrices:[new p],updateMatrix:!0}),a=0,o=i.length;a<o;a++)i[a].draw(t,s);if(t.restore(),this._selectionCount>0){t.save(),t.strokeWidth=1;var h=this._selectionItems,u=this._scope.settings.handleSize,l=this._updateVersion;for(var f in h)h[f]._drawSelection(t,e,u,h,l);t.restore()}}}),w=r.extend(s,{statics:{extend:function ut(t){return t._serializeFields&&(t._serializeFields=r.set({},this.prototype._serializeFields,t._serializeFields)),ut.base.apply(this,arguments)},NO_INSERT:{insert:!1}},_class:"Item",_name:null,_applyMatrix:!0,_canApplyMatrix:!0,_canScaleStroke:!1,_pivot:null,_visible:!0,_blendMode:"normal",_opacity:1,_locked:!1,_guide:!1,_clipMask:!1,_selection:0,_selectBounds:!0,_selectChildren:!1,_serializeFields:{name:null,applyMatrix:null,matrix:new p,pivot:null,visible:!0,blendMode:"normal",opacity:1,locked:!1,guide:!1,clipMask:!1,selected:!1,data:{}}},new function(){var t=["onMouseDown","onMouseUp","onMouseDrag","onClick","onDoubleClick","onMouseMove","onMouseEnter","onMouseLeave"];return r.each(t,function(t){this._events[t]={install:function(t){this.getView()._countItemEvent(t,1)},uninstall:function(t){this.getView()._countItemEvent(t,-1)}}},{_events:{onFrame:{install:function(){this.getView()._animateItem(this,!0)},uninstall:function(){this.getView()._animateItem(this,!1)}},onLoad:{},onError:{}},statics:{_itemHandlers:t}})},{initialize:function(){},_initialize:function(t,n){var i=t&&r.isPlainObject(t),s=i&&t.internal===!0,a=this._matrix=new p,o=i&&t.project||paper.project,h=paper.settings;return this._id=s?null:l.get(),this._parent=this._index=null,this._applyMatrix=this._canApplyMatrix&&h.applyMatrix,n&&a.translate(n),a._owner=this,this._style=new V(o._currentStyle,this,o),s||i&&t.insert===!1||!h.insertItems&&(!i||t.insert!==!0)?this._setProject(o):(i&&t.parent||o)._insertItem(e,this,!0,!0),i&&t!==w.NO_INSERT&&r.filter(this,t,{internal:!0,insert:!0,project:!0,parent:!0}),i},_serialize:function(t,e){function n(n){for(var a in n){var o=s[a];r.equals(o,"leading"===a?1.2*n.fontSize:n[a])||(i[a]=r.serialize(o,t,"data"!==a,e))}}var i={},s=this;return n(this._serializeFields),this instanceof x||n(this._style._defaults),[this._class,i]},_changed:function(t){var n=this._symbol,i=this._parent||n,r=this._project;8&t&&(this._bounds=this._position=this._decomposed=this._globalMatrix=e),i&&40&t&&w._clearBoundsCache(i),2&t&&w._clearBoundsCache(this),r&&r._changed(t,this),n&&n._changed(t)},set:function(t){return t&&this._set(t),this},getId:function(){return this._id},getName:function(){return this._name},setName:function(t){if(this._name&&this._removeNamed(),t===+t+"")throw new Error("Names consisting only of numbers are not supported.");var n=this._getOwner();if(t&&n){var i=n._children,r=n._namedChildren;(r[t]=r[t]||[]).push(this),t in i||(i[t]=this)}this._name=t||e,this._changed(128)},getStyle:function(){return this._style},setStyle:function(t){this.getStyle().set(t)}},r.each(["locked","visible","blendMode","opacity","guide"],function(t){var e=r.capitalize(t),t="_"+t;this["get"+e]=function(){return this[t]},this["set"+e]=function(e){e!=this[t]&&(this[t]=e,this._changed("_locked"===t?128:129))}},{}),{beans:!0,getSelection:function(){return this._selection},setSelection:function(t){if(t!==this._selection){this._selection=t;var e=this._project;e&&(e._updateSelection(this),this._changed(129))}},changeSelection:function(t,e){var n=this._selection;this.setSelection(e?n|t:n&~t)},isSelected:function(){if(this._selectChildren)for(var t=this._children,e=0,n=t.length;e<n;e++)if(t[e].isSelected())return!0;return!!(1&this._selection)},setSelected:function(t){if(this._selectChildren)for(var e=this._children,n=0,i=e.length;n<i;n++)e[n].setSelected(t);this.changeSelection(1,t)},isFullySelected:function(){var t=this._children,e=!!(1&this._selection);if(t&&e){for(var n=0,i=t.length;n<i;n++)if(!t[n].isFullySelected())return!1;return!0}return e},setFullySelected:function(t){var e=this._children;if(e)for(var n=0,i=e.length;n<i;n++)e[n].setFullySelected(t);this.changeSelection(1,t)},isClipMask:function(){return this._clipMask},setClipMask:function(t){this._clipMask!=(t=!!t)&&(this._clipMask=t,t&&(this.setFillColor(null),this.setStrokeColor(null)),this._changed(129),this._parent&&this._parent._changed(1024))},getData:function(){return this._data||(this._data={}),this._data},setData:function(t){this._data=t},getPosition:function(t){var e=this._position,n=t?c:f;if(!e){var i=this._pivot;e=this._position=i?this._matrix._transformPoint(i):this.getBounds().getCenter(!0)}return new n(e.x,e.y,this,"setPosition")},setPosition:function(){this.translate(c.read(arguments).subtract(this.getPosition(!0)))},getPivot:function(t){var e=this._pivot;if(e){var n=t?c:f;e=new n(e.x,e.y,this,"setPivot")}return e},setPivot:function(){this._pivot=c.read(arguments,0,{clone:!0,readNull:!0}),this._position=e}},r.each({getStrokeBounds:{stroke:!0},getHandleBounds:{handle:!0},getInternalBounds:{internal:!0}},function(t,e){this[e]=function(e){return this.getBounds(e,t)}},{beans:!0,getBounds:function(t,e){var n=e||t instanceof p,i=r.set({},n?e:t,this._boundsOptions);i.stroke&&!this.getStrokeScaling()||(i.cacheItem=this);var s=this._getCachedBounds(n&&t,i);return 0===arguments.length?new v(s.x,s.y,s.width,s.height,this,"setBounds"):s},setBounds:function(){var t=g.read(arguments),e=this.getBounds(),n=this._matrix,i=new p,r=t.getCenter();i.translate(r),t.width==e.width&&t.height==e.height||(n.isInvertible()||(n.initialize(n._backup||(new p).translate(n.getTranslation())),e=this.getBounds()),i.scale(0!==e.width?t.width/e.width:0,0!==e.height?t.height/e.height:0)),r=e.getCenter(),i.translate(-r.x,-r.y),this.transform(i)},_getBounds:function(t,e){var n=this._children;return n&&0!==n.length?(w._updateBoundsCache(this,e.cacheItem),w._getBounds(n,t,e)):new g},_getCachedBounds:function(t,e){t=t&&t._orNullIfIdentity();var n=e.internal,i=e.cacheItem,r=n?null:this._matrix._orNullIfIdentity(),s=i&&(!t||t.equals(r))&&[e.stroke?1:0,e.handle?1:0,n?1:0].join("");if(w._updateBoundsCache(this._parent||this._symbol,i),s&&this._bounds&&s in this._bounds)return this._bounds[s].rect.clone();var a=this._getBounds(t||r,e);if(s){this._bounds||(this._bounds={});this._bounds[s]={rect:a.clone(),internal:e.internal}}return a},_getStrokeMatrix:function(t,e){var n=this.getStrokeScaling()?null:e&&e.internal?this:this._parent||this._symbol&&this._symbol._item,i=n?n.getViewMatrix().invert():t;return i&&i._shiftless()},statics:{_updateBoundsCache:function(t,e){if(t&&e){var n=e._id,i=t._boundsCache=t._boundsCache||{ids:{},list:[]};i.ids[n]||(i.list.push(e),i.ids[n]=e)}},_clearBoundsCache:function(t){var n=t._boundsCache;if(n){t._bounds=t._position=t._boundsCache=e;for(var i=0,r=n.list,s=r.length;i<s;i++){var a=r[i];a!==t&&(a._bounds=a._position=e,a._boundsCache&&w._clearBoundsCache(a))}}},_getBounds:function(t,e,n){var i=1/0,r=-i,s=i,a=r;n=n||{};for(var o=0,h=t.length;o<h;o++){var u=t[o];if(u._visible&&!u.isEmpty()){var l=u._getCachedBounds(e&&e.appended(u._matrix),n);i=Math.min(l.x,i),s=Math.min(l.y,s),r=Math.max(l.x+l.width,r),a=Math.max(l.y+l.height,a)}}return isFinite(i)?new g(i,s,r-i,a-s):new g}}}),{beans:!0,_decompose:function(){return this._decomposed||(this._decomposed=this._matrix.decompose())},getRotation:function(){var t=this._decompose();return t&&t.rotation},setRotation:function(t){var e=this.getRotation();null!=e&&null!=t&&this.rotate(t-e)},getScaling:function(t){var e=this._decompose(),n=e&&e.scaling,i=t?c:f;return n&&new i(n.x,n.y,this,"setScaling")},setScaling:function(){var t=this.getScaling(),e=c.read(arguments,0,{clone:!0,readNull:!0});t&&e&&this.scale(e.x/t.x,e.y/t.y)},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},getGlobalMatrix:function(t){var e=this._globalMatrix,n=this._project._updateVersion;if(e&&e._updateVersion!==n&&(e=null),!e){e=this._globalMatrix=this._matrix.clone();var i=this._parent;i&&e.prepend(i.getGlobalMatrix(!0)),e._updateVersion=n}return t?e:e.clone()},getViewMatrix:function(){return this.getGlobalMatrix().prepend(this.getView()._matrix)},getApplyMatrix:function(){return this._applyMatrix},setApplyMatrix:function(t){(this._applyMatrix=this._canApplyMatrix&&!!t)&&this.transform(null,!0)},getTransformContent:"#getApplyMatrix",setTransformContent:"#setApplyMatrix"},{getProject:function(){return this._project},_setProject:function(t,e){if(this._project!==t){this._project&&this._installEvents(!1),this._project=t;for(var n=this._children,i=0,r=n&&n.length;i<r;i++)n[i]._setProject(t);e=!0}e&&this._installEvents(!0)},getView:function(){return this._project._view},_installEvents:function lt(t){lt.base.call(this,t);for(var e=this._children,n=0,i=e&&e.length;n<i;n++)e[n]._installEvents(t)},getLayer:function(){for(var t=this;t=t._parent;)if(t instanceof b)return t;return null},getParent:function(){return this._parent},setParent:function(t){return t.addChild(this)},_getOwner:"#getParent",getChildren:function(){return this._children},setChildren:function(t,e){this.removeChildren(),this.addChildren(t,e)},getFirstChild:function(){return this._children&&this._children[0]||null},getLastChild:function(){return this._children&&this._children[this._children.length-1]||null},getNextSibling:function(){var t=this._getOwner();return t&&t._children[this._index+1]||null},getPreviousSibling:function(){var t=this._getOwner();return t&&t._children[this._index-1]||null},getIndex:function(){return this._index},equals:function(t){return t===this||t&&this._class===t._class&&this._style.equals(t._style)&&this._matrix.equals(t._matrix)&&this._locked===t._locked&&this._visible===t._visible&&this._blendMode===t._blendMode&&this._opacity===t._opacity&&this._clipMask===t._clipMask&&this._guide===t._guide&&this._equals(t)||!1},_equals:function(t){return r.equals(this._children,t._children)},clone:function(t){var n=new this.constructor(w.NO_INSERT),i=this._children,s=r.pick(t?t.insert:e,t===e||t===!0),a=r.pick(t?t.deep:e,!0);i&&n.copyAttributes(this),i&&!a||n.copyContent(this),i||n.copyAttributes(this),s&&n.insertAbove(this);var o=this._name,h=this._parent;if(o&&h){for(var i=h._children,u=o,l=1;i[o];)o=u+" "+l++;o!==u&&n.setName(o)}return n},copyContent:function(t){for(var e=t._children,n=0,i=e&&e.length;n<i;n++)this.addChild(e[n].clone(!1),!0)},copyAttributes:function(t,e){this.setStyle(t._style);for(var n=["_locked","_visible","_blendMode","_opacity","_clipMask","_guide"],i=0,s=n.length;i<s;i++){var a=n[i];t.hasOwnProperty(a)&&(this[a]=t[a])}e||this._matrix.initialize(t._matrix),this.setApplyMatrix(t._applyMatrix),this.setPivot(t._pivot),this.setSelection(t._selection);var o=t._data,h=t._name;this._data=o?r.clone(o):null,h&&this.setName(h)},rasterize:function(t,n){var i=this.getStrokeBounds(),s=(t||this.getView().getResolution())/72,a=i.getTopLeft().floor(),o=i.getBottomRight().ceil(),h=new d(o.subtract(a)),u=new S(w.NO_INSERT);if(!h.isZero()){var l=tt.getCanvas(h.multiply(s)),c=l.getContext("2d"),f=(new p).scale(s).translate(a.negate());c.save(),f.applyToContext(c),this.draw(c,new r({matrices:[f]})),c.restore(),u.setCanvas(l)}return u.transform((new p).translate(a.add(h.divide(2))).scale(1/s)),(n===e||n)&&u.insertAbove(this),u},contains:function(){return!!this._contains(this._matrix._inverseTransform(c.read(arguments)))},_contains:function(t){var e=this._children;if(e){for(var n=e.length-1;n>=0;n--)if(e[n].contains(t))return!0;return!1}return t.isInside(this.getInternalBounds())},isInside:function(){return g.read(arguments).contains(this.getBounds())},_asPathItem:function(){return new E.Rectangle({rectangle:this.getInternalBounds(),matrix:this._matrix,insert:!1})},intersects:function(t,e){return t instanceof w&&this._asPathItem().getIntersections(t._asPathItem(),null,e,!0).length>0}},new function(){function t(){return this._hitTest(c.read(arguments),P.getOptions(arguments))}function e(){var t=c.read(arguments),e=P.getOptions(arguments),n=e.match,i=[];return e=r.set({},e,{match:function(t){n&&!n(t)||i.push(t)}}),this._hitTest(t,e),i}function n(t,e,n,i){var r=this._children;if(r)for(var s=r.length-1;s>=0;s--){var a=r[s],o=a!==i&&a._hitTest(t,e,n);if(o)return o}return null}return y.inject({hitTest:t,hitTestAll:e,_hitTest:n}),{hitTest:t,hitTestAll:e,_hitTestChildren:n}},{_hitTest:function(t,e,n){function i(t){return!g||t&&g(t)?t:null}function s(e,n){var i=c["get"+n]();if(t.subtract(i).divide(l).length<=1)return new P(e,v,{name:r.hyphenate(n),point:i})}if(this._locked||!this._visible||this._guide&&!e.guides||this.isEmpty())return null;var a=this._matrix,o=n?n.appended(a):this.getGlobalMatrix().prepend(this.getView()._matrix),h=this.getStrokeScaling()?null:o.inverted()._shiftless(),u=Math.max(e.tolerance,1e-6),l=e._tolerancePadding=new d(E._getStrokePadding(u,h));if(t=a._inverseTransform(t),!t||!this._children&&!this.getBounds({internal:!0,stroke:!0,handle:!0}).expand(l.multiply(2))._containsPoint(t))return null;var c,f,_=!(e.guides&&!this._guide||e.selected&&!this.isSelected()||e.type&&e.type!==r.hyphenate(this._class)||e["class"]&&!(this instanceof e["class"])),g=e.match,v=this;if(_&&(e.center||e.bounds)&&this._parent){if(c=this.getInternalBounds(),e.center&&(f=s("center","Center")),!f&&e.bounds)for(var p=["TopLeft","TopRight","BottomLeft","BottomRight","LeftCenter","TopCenter","RightCenter","BottomCenter"],m=0;m<8&&!f;m++)f=s("bounds",p[m]);f=i(f)}return f||(f=this._hitTestChildren(t,e,o)||_&&i(this._hitTestSelf(t,e,o,h))||null),f&&f.point&&(f.point=a.transform(f.point)),f},_hitTestSelf:function(t,e){if(e.fill&&this.hasFill()&&this._contains(t))return new P("fill",this)},matches:function(t,e){function n(t,e){for(var i in t)if(t.hasOwnProperty(i)){var s=t[i],a=e[i];if(r.isPlainObject(s)&&r.isPlainObject(a)){if(!n(s,a))return!1}else if(!r.equals(s,a))return!1}return!0}var i=typeof t;if("object"===i){for(var s in t)if(t.hasOwnProperty(s)&&!this.matches(s,t[s]))return!1;return!0}if("function"===i)return t(this);if("match"===t)return e(this);var a=/^(empty|editable)$/.test(t)?this["is"+r.capitalize(t)]():"type"===t?r.hyphenate(this._class):this[t];if("class"===t){if("function"==typeof e)return this instanceof e;a=this._class}if("function"==typeof e)return!!e(a);if(e){if(e.test)return e.test(a);if(r.isPlainObject(e))return n(e,a)}return r.equals(a,e)},getItems:function(t){return w._getItems(this,t,this._matrix)},getItem:function(t){return w._getItems(this,t,this._matrix,null,!0)[0]||null},statics:{_getItems:function ct(t,e,n,i,s){if(!i){var a="object"==typeof e&&e,o=a&&a.overlapping,h=a&&a.inside,u=o||h,l=u&&g.read([u]);i={items:[],recursive:a&&a.recursive!==!1,inside:!!h,overlapping:!!o,rect:l,path:o&&new E.Rectangle({rectangle:l,insert:!1})},a&&(e=r.filter({},e,{recursive:!0,inside:!0,overlapping:!0}))}var c=t._children,f=i.items,l=i.rect;n=l&&(n||new p);for(var d=0,_=c&&c.length;d<_;d++){var v=c[d],m=n&&n.appended(v._matrix),y=!0;if(l){var u=v.getBounds(m);if(!l.intersects(u))continue;l.contains(u)||i.overlapping&&(u.contains(l)||i.path.intersects(v,m))||(y=!1)}if(y&&v.matches(e)&&(f.push(v),s))break;if(i.recursive!==!1&&ct(v,e,m,i,s),s&&f.length>0)break}return f}}},{importJSON:function(t){var e=r.importJSON(t,this);return e!==this?this.addChild(e):e},addChild:function(t,n){return this.insertChild(e,t,n)},insertChild:function(t,e,n){var i=e?this.insertChildren(t,[e],n):null;return i&&i[0]},addChildren:function(t,e){return this.insertChildren(this._children.length,t,e)},insertChildren:function(t,e,n,i){var s=this._children;if(s&&e&&e.length>0){e=Array.prototype.slice.apply(e);for(var a=e.length-1;a>=0;a--){var o=e[a];o&&(!i||o instanceof i)?o._remove(!1,!0):e.splice(a,1)}r.splice(s,e,t,0);for(var h=this._project,u=h._changes,a=0,l=e.length;a<l;a++){var o=e[a],c=o._name;o._parent=this,o._setProject(h,!0),c&&o.setName(c),u&&this._changed(5)}this._changed(11)}else e=null;return e},_insertItem:"#insertChild",_insertAt:function(t,e,n){var i=this;if(i!==t){var r=t&&t._getOwner();r?(i._remove(!1,!0),r._insertItem(t._index+e,i,n)):i=null}return i},insertAbove:function(t,e){return this._insertAt(t,1,e)},insertBelow:function(t,e){return this._insertAt(t,0,e)},sendToBack:function(){var t=this._getOwner();return t?t._insertItem(0,this):null},bringToFront:function(){var t=this._getOwner();return t?t._insertItem(e,this):null},appendTop:"#addChild",appendBottom:function(t){return this.insertChild(0,t)},moveAbove:"#insertAbove",moveBelow:"#insertBelow",copyTo:function(t){return t._insertItem(e,this.clone(!1))},reduce:function(t){var e=this._children;if(e&&1===e.length){var n=e[0].reduce(t);return this._parent?(n.insertAbove(this),this.remove()):n.remove(),n}return this},_removeNamed:function(){var t=this._getOwner();if(t){var e=t._children,n=t._namedChildren,i=this._name,r=n[i],s=r?r.indexOf(this):-1;s!==-1&&(e[i]==this&&delete e[i],r.splice(s,1),r.length?e[i]=r[0]:delete n[i])}},_remove:function(t,e){var n=this._getOwner(),i=this._project,s=this._index;return!!n&&(null!=s&&(i._activeLayer===this&&(i._activeLayer=this.getNextSibling()||this.getPreviousSibling()),r.splice(n._children,null,s,1)),this._name&&this._removeNamed(),this._installEvents(!1),t&&i._changes&&this._changed(5),e&&n._changed(11,this),this._parent=null,!0)},remove:function(){return this._remove(!0,!0)},replaceWith:function(t){var e=t&&t.insertBelow(this);return e&&this.remove(),e},removeChildren:function(t,e){if(!this._children)return null;t=t||0,e=r.pick(e,this._children.length);for(var n=r.splice(this._children,null,t,e-t),i=n.length-1;i>=0;i--)n[i]._remove(!0,!1);return n.length>0&&this._changed(11),n},clear:"#removeChildren",reverseChildren:function(){if(this._children){this._children.reverse();for(var t=0,e=this._children.length;t<e;t++)this._children[t]._index=t;this._changed(11)}},isEmpty:function(){return!this._children||0===this._children.length},isEditable:function(){for(var t=this;t;){if(!t._visible||t._locked)return!1;t=t._parent}return!0},hasFill:function(){return this.getStyle().hasFill()},hasStroke:function(){return this.getStyle().hasStroke()},hasShadow:function(){return this.getStyle().hasShadow()},_getOrder:function(t){function e(t){var e=[];do e.unshift(t);while(t=t._parent);return e}for(var n=e(this),i=e(t),r=0,s=Math.min(n.length,i.length);r<s;r++)if(n[r]!=i[r])return n[r]._index<i[r]._index?1:-1;return 0},hasChildren:function(){return this._children&&this._children.length>0},isInserted:function(){return!!this._parent&&this._parent.isInserted()},isAbove:function(t){return this._getOrder(t)===-1},isBelow:function(t){return 1===this._getOrder(t)},isParent:function(t){return this._parent===t},isChild:function(t){return t&&t._parent===this},isDescendant:function(t){for(var e=this;e=e._parent;)if(e===t)return!0;return!1},isAncestor:function(t){return!!t&&t.isDescendant(this)},isSibling:function(t){return this._parent===t._parent},isGroupedWith:function(t){for(var e=this._parent;e;){if(e._parent&&/^(Group|Layer|CompoundPath)$/.test(e._class)&&t.isDescendant(e))return!0;e=e._parent}return!1}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var n=(e?r:c).read(arguments),i=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](n,i||this.getPosition(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t,e,n,i){t&&t.isIdentity()&&(t=null);var r=this._matrix,s=(e||this._applyMatrix)&&(!r.isIdentity()||t||e&&n&&this._children);if(!t&&!s)return this;if(t&&(!t.isInvertible()&&r.isInvertible()&&(r._backup=r.getValues()),r.prepend(t)),s=s&&this._transformContent(r,n,i)){var a=this._pivot,o=this._style,h=o.getFillColor(!0),u=o.getStrokeColor(!0);a&&r._transformPoint(a,a,!0),h&&h.transform(r),u&&u.transform(r),r.reset(!0),i&&this._canApplyMatrix&&(this._applyMatrix=!0)}var l=this._bounds,c=this._position;this._changed(9);var f=l&&t&&t.decompose();if(f&&!f.shearing&&f.rotation%90===0){for(var d in l){var _=l[d];if(s||!_.internal){var g=_.rect;t._transformBounds(g,g)}}var v=this._boundsGetter,g=l[v&&v.getBounds||v||"getBounds"];g&&(this._position=g.getCenter(!0)),this._bounds=l}else t&&c&&(this._position=t._transformPoint(c,c));return this},_transformContent:function(t,e,n){var i=this._children;if(i){for(var r=0,s=i.length;r<s;r++)i[r].transform(t,!0,e,n);return!0}},globalToLocal:function(){return this.getGlobalMatrix(!0)._inverseTransform(c.read(arguments))},localToGlobal:function(){return this.getGlobalMatrix(!0)._transformPoint(c.read(arguments))},parentToLocal:function(){return this._matrix._inverseTransform(c.read(arguments))},localToParent:function(){return this._matrix._transformPoint(c.read(arguments))},fitBounds:function(t,e){t=g.read(arguments);var n=this.getBounds(),i=n.height/n.width,r=t.height/t.width,s=(e?i>r:i<r)?t.width/n.width:t.height/n.height,a=new g(new c,new d(n.width*s,n.height*s));a.setCenter(t.getCenter()),this.setBounds(a)}}),{_setStyles:function(t,e,n){var i=this._style;if(i.hasFill()&&(t.fillStyle=i.getFillColor().toCanvasStyle(t)),i.hasStroke()){t.strokeStyle=i.getStrokeColor().toCanvasStyle(t),t.lineWidth=i.getStrokeWidth();var r=i.getStrokeJoin(),s=i.getStrokeCap(),a=i.getMiterLimit();if(r&&(t.lineJoin=r),s&&(t.lineCap=s),a&&(t.miterLimit=a),paper.support.nativeDash){var o=i.getDashArray(),h=i.getDashOffset();o&&o.length&&("setLineDash"in t?(t.setLineDash(o),t.lineDashOffset=h):(t.mozDash=o,t.mozDashOffset=h))}}if(i.hasShadow()){var u=e.pixelRatio||1,l=n._shiftless().prepend((new p).scale(u,u)),f=l.transform(new c(i.getShadowBlur(),0)),d=l.transform(this.getShadowOffset());t.shadowColor=i.getShadowColor().toCanvasStyle(t),t.shadowBlur=f.getLength(),t.shadowOffsetX=d.x,t.shadowOffsetY=d.y}},draw:function(t,e,n){var i=this._updateVersion=this._project._updateVersion;if(this._visible&&0!==this._opacity){var r=e.matrices,s=e.viewMatrix,a=this._matrix,o=r[r.length-1].appended(a);if(o.isInvertible()){s=s?s.appended(o):o,r.push(o),e.updateMatrix&&(o._updateVersion=i,this._globalMatrix=o);var h,u,l,c=this._blendMode,f=this._opacity,d="normal"===c,_=et.nativeModes[c],g=d&&1===f||e.dontStart||e.clip||(_||d&&f<1)&&this._canComposite(),v=e.pixelRatio||1;if(!g){var p=this.getStrokeBounds(s);if(!p.width||!p.height)return;l=e.offset,u=e.offset=p.getTopLeft().floor(),h=t,t=tt.getContext(p.getSize().ceil().add(1).multiply(v)),1!==v&&t.scale(v,v)}t.save();var m=n?n.appended(a):this._canScaleStroke&&!this.getStrokeScaling(!0)&&s,y=!g&&e.clipItem,w=!m||y;if(g?(t.globalAlpha=f,_&&(t.globalCompositeOperation=c)):w&&t.translate(-u.x,-u.y),w&&(g?a:s).applyToContext(t),y&&e.clipItem.draw(t,e.extend({clip:!0})),m){t.setTransform(v,0,0,v,0,0);var x=e.offset;x&&t.translate(-x.x,-x.y)}this._draw(t,e,s,m),t.restore(),r.pop(),e.clip&&!e.dontFinish&&t.clip(),g||(et.process(c,t,h,f,u.subtract(l).multiply(v)),tt.release(t),e.offset=l)}}},_isUpdated:function(t){var e=this._parent;if(e instanceof L)return e._isUpdated(t);var n=this._updateVersion===t;return!n&&e&&e._visible&&e._isUpdated(t)&&(this._updateVersion=t,n=!0),n},_drawSelection:function(t,e,n,i,r){var s=this._selection,a=1&s,o=2&s||a&&this._selectBounds,h=4&s;if(this._drawSelected||(a=!1),
-(a||o||h)&&this._isUpdated(r)){var u,l=this.getSelectedColor(!0)||(u=this.getLayer())&&u.getSelectedColor(!0),c=e.appended(this.getGlobalMatrix(!0)),f=n/2;if(t.strokeStyle=t.fillStyle=l?l.toCanvasStyle(t):"#009dec",a&&this._drawSelected(t,c,i),h){var d=this.getPosition(!0),_=d.x,g=d.y;t.beginPath(),t.arc(_,g,f,0,2*Math.PI,!0),t.stroke();for(var v=[[0,-1],[1,0],[0,1],[-1,0]],p=f,m=n+1,y=0;y<4;y++){var w=v[y],x=w[0],b=w[1];t.moveTo(_+x*p,g+b*p),t.lineTo(_+x*m,g+b*m),t.stroke()}}if(o){var C=c._transformCorners(this.getInternalBounds());t.beginPath();for(var y=0;y<8;y++)t[0===y?"moveTo":"lineTo"](C[y],C[++y]);t.closePath(),t.stroke();for(var y=0;y<8;y++)t.fillRect(C[y]-f,C[++y]-f,n,n)}}},_canComposite:function(){return!1}},r.each(["down","drag","up","move"],function(t){this["removeOn"+r.capitalize(t)]=function(){var e={};return e[t]=!0,this.removeOn(e)}},{removeOn:function(t){for(var e in t)if(t[e]){var n="mouse"+e,i=this._project,r=i._removeSets=i._removeSets||{};r[n]=r[n]||{},r[n][this._id]=this}return this}})),x=w.extend({_class:"Group",_selectBounds:!1,_selectChildren:!0,_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||this.addChildren(Array.isArray(t)?t:arguments)},_changed:function ft(t){ft.base.call(this,t),1026&t&&(this._clipItem=e)},_getClipItem:function(){var t=this._clipItem;if(t===e){t=null;for(var n=this._children,i=0,r=n.length;i<r;i++)if(n[i]._clipMask){t=n[i];break}this._clipItem=t}return t},isClipped:function(){return!!this._getClipItem()},setClipped:function(t){var e=this.getFirstChild();e&&e.setClipMask(t)},_getBounds:function dt(t,e){var n=this._getClipItem();return n?n._getCachedBounds(t&&t.appended(n._matrix),r.set({},e,{stroke:!1})):dt.base.call(this,t,e)},_hitTestChildren:function _t(t,e,n){var i=this._getClipItem();return(!i||i.contains(t))&&_t.base.call(this,t,e,n,i)},_draw:function(t,e){var n=e.clip,i=!n&&this._getClipItem();e=e.extend({clipItem:i,clip:!1}),n?(t.beginPath(),e.dontStart=e.dontFinish=!0):i&&i.draw(t,e.extend({clip:!0}));for(var r=this._children,s=0,a=r.length;s<a;s++){var o=r[s];o!==i&&o.draw(t,e)}}}),b=x.extend({_class:"Layer",initialize:function(){x.apply(this,arguments)},_getOwner:function(){return this._parent||null!=this._index&&this._project},isInserted:function gt(){return this._parent?gt.base.call(this):null!=this._index},activate:function(){this._project._activeLayer=this},_hitTestSelf:function(){}}),C=w.extend({_class:"Shape",_applyMatrix:!1,_canApplyMatrix:!1,_canScaleStroke:!0,_serializeFields:{type:null,size:null,radius:null},initialize:function(t){this._initialize(t)},_equals:function(t){return this._type===t._type&&this._size.equals(t._size)&&r.equals(this._radius,t._radius)},copyContent:function(t){this.setType(t._type),this.setSize(t._size),this.setRadius(t._radius)},getType:function(){return this._type},setType:function(t){this._type=t},getShape:"#getType",setShape:"#setType",getSize:function(){var t=this._size;return new _(t.width,t.height,this,"setSize")},setSize:function(){var t=d.read(arguments);if(this._size){if(!this._size.equals(t)){var e=this._type,n=t.width,i=t.height;if("rectangle"===e){var r=d.min(this._radius,t.divide(2));this._radius.set(r.width,r.height)}else"circle"===e?(n=i=(n+i)/2,this._radius=n/2):"ellipse"===e&&this._radius.set(n/2,i/2);this._size.set(n,i),this._changed(9)}}else this._size=t.clone()},getRadius:function(){var t=this._radius;return"circle"===this._type?t:new _(t.width,t.height,this,"setRadius")},setRadius:function(t){var e=this._type;if("circle"===e){if(t===this._radius)return;var n=2*t;this._radius=t,this._size.set(n,n)}else if(t=d.read(arguments),this._radius){if(this._radius.equals(t))return;if(this._radius.set(t.width,t.height),"rectangle"===e){var n=d.max(this._size,t.multiply(2));this._size.set(n.width,n.height)}else"ellipse"===e&&this._size.set(2*t.width,2*t.height)}else this._radius=t.clone();this._changed(9)},isEmpty:function(){return!1},toPath:function(t){var n=new(E[r.capitalize(this._type)])({center:new c,size:this._size,radius:this._radius,insert:!1});return n.copyAttributes(this),paper.settings.applyMatrix&&n.setApplyMatrix(!0),(t===e||t)&&n.insertAbove(this),n},toShape:"#clone",_draw:function(t,e,n,i){var r=this._style,s=r.hasFill(),a=r.hasStroke(),o=e.dontFinish||e.clip,h=!i;if(s||a||o){var u=this._type,l=this._radius,c="circle"===u;if(e.dontStart||t.beginPath(),h&&c)t.arc(0,0,l,0,2*Math.PI,!0);else{var f=c?l:l.width,d=c?l:l.height,_=this._size,g=_.width,v=_.height;if(h&&"rectangle"===u&&0===f&&0===d)t.rect(-g/2,-v/2,g,v);else{var p=g/2,m=v/2,y=.44771525016920644,w=f*y,x=d*y,b=[-p,-m+d,-p,-m+x,-p+w,-m,-p+f,-m,p-f,-m,p-w,-m,p,-m+x,p,-m+d,p,m-d,p,m-x,p-w,m,p-f,m,-p+f,m,-p+w,m,-p,m-x,-p,m-d];i&&i.transform(b,b,32),t.moveTo(b[0],b[1]),t.bezierCurveTo(b[2],b[3],b[4],b[5],b[6],b[7]),p!==f&&t.lineTo(b[8],b[9]),t.bezierCurveTo(b[10],b[11],b[12],b[13],b[14],b[15]),m!==d&&t.lineTo(b[16],b[17]),t.bezierCurveTo(b[18],b[19],b[20],b[21],b[22],b[23]),p!==f&&t.lineTo(b[24],b[25]),t.bezierCurveTo(b[26],b[27],b[28],b[29],b[30],b[31])}}t.closePath()}o||!s&&!a||(this._setStyles(t,e,n),s&&(t.fill(r.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),a&&t.stroke())},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_getBounds:function(t,e){var n=new g(this._size).setCenter(0,0),i=this._style,r=e.stroke&&i.hasStroke()&&i.getStrokeWidth();return t&&(n=t._transformBounds(n)),r?n.expand(E._getStrokePadding(r,this._getStrokeMatrix(t,e))):n}},new function(){function t(t,e,n){var i=t._radius;if(!i.isZero())for(var r=t._size.divide(2),s=0;s<4;s++){var a=new c(1&s?1:-1,s>1?1:-1),o=a.multiply(r),h=o.subtract(a.multiply(i)),u=new g(o,h);if((n?u.expand(n):u).contains(e))return h}}function e(t,e,n,i){var r=t.divide(e);return(!i||r.quadrant===i)&&r.subtract(r.normalize()).multiply(e).divide(n).length<=1}return{_contains:function n(e){if("rectangle"===this._type){var i=t(this,e);return i?e.subtract(i).divide(this._radius).getLength()<=1:n.base.call(this,e)}return e.divide(this.size).getLength()<=.5},_hitTestSelf:function i(n,r,s,a){var o=!1,h=this._style,u=r.stroke&&h.hasStroke(),l=r.fill&&h.hasFill();if(u||l){var c=this._type,f=this._radius,d=u?h.getStrokeWidth()/2:0,_=r._tolerancePadding.add(E._getStrokePadding(d,!h.getStrokeScaling()&&a));if("rectangle"===c){var v=_.multiply(2),p=t(this,n,v);if(p)o=e(n.subtract(p),f,_,p.getQuadrant());else{var m=new g(this._size).setCenter(0,0),y=m.expand(v),w=m.expand(v.negate());o=y._containsPoint(n)&&!w._containsPoint(n)}}else o=e(n,f,_)}return o?new P(u?"stroke":"fill",this):i.base.apply(this,arguments)}}},{statics:new function(){function t(t,e,n,i,s){var a=new C(r.getNamed(s));return a._type=t,a._size=n,a._radius=i,a.translate(e)}return{Circle:function(){var e=c.readNamed(arguments,"center"),n=r.readNamed(arguments,"radius");return t("circle",e,new d(2*n),n,arguments)},Rectangle:function(){var e=g.readNamed(arguments,"rectangle"),n=d.min(d.readNamed(arguments,"radius"),e.getSize(!0).divide(2));return t("rectangle",e.getCenter(!0),e.getSize(!0),n,arguments)},Ellipse:function(){var e=C._readEllipse(arguments),n=e.radius;return t("ellipse",e.center,n.multiply(2),n,arguments)},_readEllipse:function(t){var e,n;if(r.hasNamed(t,"radius"))e=c.readNamed(t,"center"),n=d.readNamed(t,"radius");else{var i=g.readNamed(t,"rectangle");e=i.getCenter(!0),n=i.getSize(!0).divide(2)}return{center:e,radius:n}}}}}),S=w.extend({_class:"Raster",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!1,handle:!1},_serializeFields:{crossOrigin:null,source:null},initialize:function(t,n){if(!this._initialize(t,n!==e&&c.read(arguments,1))){var r="string"==typeof t?i.getElementById(t):t;r?this.setImage(r):this.setSource(t)}this._size||(this._size=new d,this._loaded=!1)},_equals:function(t){return this.getSource()===t.getSource()},copyContent:function(t){var e=t._image,n=t._canvas;if(e)this._setImage(e);else if(n){var i=tt.getCanvas(t._size);i.getContext("2d").drawImage(n,0,0),this._setImage(i)}this._crossOrigin=t._crossOrigin},getSize:function(){var t=this._size;return new _(t?t.width:0,t?t.height:0,this,"setSize")},setSize:function(){var t=d.read(arguments);if(!t.equals(this._size))if(t.width>0&&t.height>0){var e=this.getElement();this._setImage(tt.getCanvas(t)),e&&this.getContext(!0).drawImage(e,0,0,t.width,t.height)}else this._canvas&&tt.release(this._canvas),this._size=t.clone()},getWidth:function(){return this._size?this._size.width:0},setWidth:function(t){this.setSize(t,this.getHeight())},getHeight:function(){return this._size?this._size.height:0},setHeight:function(t){this.setSize(this.getWidth(),t)},getLoaded:function(){return this._loaded},isEmpty:function(){var t=this._size;return!t||0===t.width&&0===t.height},getResolution:function(){var t=this._matrix,e=new c(0,0).transform(t),n=new c(1,0).transform(t).subtract(e),i=new c(0,1).transform(t).subtract(e);return new d(72/n.getLength(),72/i.getLength())},getPpi:"#getResolution",getImage:function(){return this._image},setImage:function(t){function e(t){var e=n.getView(),i=t&&t.type||"load";e&&n.responds(i)&&(paper=e._scope,n.emit(i,new G(t)))}var n=this;this._setImage(t),this._loaded?setTimeout(e,0):t&&U.add(t,{load:function(i){n._setImage(t),e(i)},error:e})},_setImage:function(t){this._canvas&&tt.release(this._canvas),t&&t.getContext?(this._image=null,this._canvas=t,this._loaded=!0):(this._image=t,this._canvas=null,this._loaded=!!(t&&t.src&&t.complete)),this._size=new d(t?t.naturalWidth||t.width:0,t?t.naturalHeight||t.height:0),this._context=null,this._changed(521)},getCanvas:function(){if(!this._canvas){var t=tt.getContext(this._size);try{this._image&&t.drawImage(this._image,0,0),this._canvas=t.canvas}catch(e){tt.release(t)}}return this._canvas},setCanvas:"#setImage",getContext:function(t){return this._context||(this._context=this.getCanvas().getContext("2d")),t&&(this._image=null,this._changed(513)),this._context},setContext:function(t){this._context=t},getSource:function(){var t=this._image;return t&&t.src||this.toDataURL()},setSource:function(t){var e=new n.Image,i=this._crossOrigin;i&&(e.crossOrigin=i),e.src=t,this.setImage(e)},getCrossOrigin:function(){var t=this._image;return t&&t.crossOrigin||this._crossOrigin||""},setCrossOrigin:function(t){this._crossOrigin=t;var e=this._image;e&&(e.crossOrigin=t)},getElement:function(){return this._canvas||this._loaded&&this._image}},{beans:!1,getSubCanvas:function(){var t=g.read(arguments),e=tt.getContext(t.getSize());return e.drawImage(this.getCanvas(),t.x,t.y,t.width,t.height,0,0,t.width,t.height),e.canvas},getSubRaster:function(){var t=g.read(arguments),e=new S(w.NO_INSERT);return e._setImage(this.getSubCanvas(t)),e.translate(t.getCenter().subtract(this.getSize().divide(2))),e._matrix.prepend(this._matrix),e.insertAbove(this),e},toDataURL:function(){var t=this._image,e=t&&t.src;if(/^data:/.test(e))return e;var n=this.getCanvas();return n?n.toDataURL.apply(n,arguments):null},drawImage:function(t){var e=c.read(arguments,1);this.getContext(!0).drawImage(t,e.x,e.y)},getAverageColor:function(t){var e,n;if(t?t instanceof O?(n=t,e=t.getBounds()):"object"==typeof t&&("width"in t?e=new g(t):"x"in t&&(e=new g(t.x-.5,t.y-.5,1,1))):e=this.getBounds(),!e)return null;var i=32,s=Math.min(e.width,i),a=Math.min(e.height,i),o=S._sampleContext;o?o.clearRect(0,0,i+1,i+1):o=S._sampleContext=tt.getContext(new d(i)),o.save();var h=(new p).scale(s/e.width,a/e.height).translate(-e.x,-e.y);h.applyToContext(o),n&&n.draw(o,new r({clip:!0,matrices:[h]})),this._matrix.applyToContext(o);var u=this.getElement(),l=this._size;u&&o.drawImage(u,-l.width/2,-l.height/2),o.restore();for(var c=o.getImageData(.5,.5,Math.ceil(s),Math.ceil(a)).data,f=[0,0,0],_=0,v=0,m=c.length;v<m;v+=4){var y=c[v+3];_+=y,y/=255,f[0]+=c[v]*y,f[1]+=c[v+1]*y,f[2]+=c[v+2]*y}for(var v=0;v<3;v++)f[v]/=_;return _?D.read(f):null},getPixel:function(){var t=c.read(arguments),e=this.getContext().getImageData(t.x,t.y,1,1).data;return new D("rgb",[e[0]/255,e[1]/255,e[2]/255],e[3]/255)},setPixel:function(){var t=c.read(arguments),e=D.read(arguments),n=e._convert("rgb"),i=e._alpha,r=this.getContext(!0),s=r.createImageData(1,1),a=s.data;a[0]=255*n[0],a[1]=255*n[1],a[2]=255*n[2],a[3]=null!=i?255*i:255,r.putImageData(s,t.x,t.y)},createImageData:function(){var t=d.read(arguments);return this.getContext().createImageData(t.width,t.height)},getImageData:function(){var t=g.read(arguments);return t.isEmpty()&&(t=new g(this._size)),this.getContext().getImageData(t.x,t.y,t.width,t.height)},setImageData:function(t){var e=c.read(arguments,1);this.getContext(!0).putImageData(t,e.x,e.y)},_getBounds:function(t,e){var n=new g(this._size).setCenter(0,0);return t?t._transformBounds(n):n},_hitTestSelf:function(t){if(this._contains(t)){var e=this;return new P("pixel",e,{offset:t.add(e._size.divide(2)).round(),color:{get:function(){return e.getPixel(this.offset)}}})}},_draw:function(t){var e=this.getElement();e&&(t.globalAlpha=this._opacity,t.drawImage(e,-this._size.width/2,-this._size.height/2))},_canComposite:function(){return!0}}),k=w.extend({_class:"SymbolItem",_applyMatrix:!1,_canApplyMatrix:!1,_boundsOptions:{stroke:!0},_serializeFields:{symbol:null},initialize:function(t,n){this._initialize(t,n!==e&&c.read(arguments,1))||this.setDefinition(t instanceof I?t:new I(t))},_equals:function(t){return this._definition===t._definition},copyContent:function(t){this.setDefinition(t._definition)},getDefinition:function(){return this._definition},setDefinition:function(t){this._definition=t,this._changed(9)},getSymbol:"#getDefinition",setSymbol:"#setDefinition",isEmpty:function(){return this._definition._item.isEmpty()},_getBounds:function(t,e){var n=this._definition._item;return n._getCachedBounds(n._matrix.prepended(t),e)},_hitTestSelf:function(t,e,n,i){var r=this._definition._item._hitTest(t,e,n);return r&&(r.item=this),r},_draw:function(t,e){this._definition._item.draw(t,e)}}),I=r.extend({_class:"SymbolDefinition",initialize:function(t,e){this._id=l.get(),this.project=paper.project,t&&this.setItem(t,e)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._class,this._item],t,!1,e)})},_changed:function(t){8&t&&w._clearBoundsCache(this),1&t&&this.project._changed(t)},getItem:function(){return this._item},setItem:function(t,e){t._symbol&&(t=t.clone()),this._item&&(this._item._symbol=null),this._item=t,t.remove(),t.setSelected(!1),e||t.setPosition(new c),t._symbol=this,this._changed(9)},getDefinition:"#getItem",setDefinition:"#setItem",place:function(t){return new k(this,t)},clone:function(){return new I(this._item.clone(!1))},equals:function(t){return t===this||t&&this._item.equals(t._item)||!1}}),P=r.extend({_class:"HitResult",initialize:function(t,e,n){this.type=t,this.item=e,n&&(n.enumerable=!0,this.inject(n))},statics:{getOptions:function(t){var e=t&&r.read(t);return r.set({type:null,tolerance:paper.settings.hitTolerance,fill:!e,stroke:!e,segments:!e,handles:!1,ends:!1,center:!1,bounds:!1,guides:!1,selected:!1},e)}}}),M=r.extend({_class:"Segment",beans:!0,_selection:0,initialize:function(t,n,i,r,s,a){var o,h,u,l,c=arguments.length;0===c||(1===c?t&&"point"in t?(o=t.point,h=t.handleIn,u=t.handleOut,l=t.selection):o=t:null==t||"object"==typeof t?(o=t,h=n,u=i,l=r):(o=t!==e?[t,n]:null,h=i!==e?[i,r]:null,u=s!==e?[s,a]:null)),new A(o,this,"_point"),new A(h,this,"_handleIn"),new A(u,this,"_handleOut"),l&&this.setSelection(l)},_serialize:function(t,e){var n=this._point,i=this._selection,s=i||this.hasHandles()?[n,this._handleIn,this._handleOut]:n;return i&&s.push(i),r.serialize(s,t,!0,e)},_changed:function(t){var e=this._path;if(e){var n,i=e._curves,r=this._index;i&&(t&&t!==this._point&&t!==this._handleIn||!(n=r>0?i[r-1]:e._closed?i[i.length-1]:null)||n._changed(),t&&t!==this._point&&t!==this._handleOut||!(n=i[r])||n._changed()),e._changed(25)}},getPoint:function(){return this._point},setPoint:function(){var t=c.read(arguments);this._point.set(t.x,t.y)},getHandleIn:function(){return this._handleIn},setHandleIn:function(){var t=c.read(arguments);this._handleIn.set(t.x,t.y)},getHandleOut:function(){return this._handleOut},setHandleOut:function(){var t=c.read(arguments);this._handleOut.set(t.x,t.y)},hasHandles:function(){return!this._handleIn.isZero()||!this._handleOut.isZero()},clearHandles:function(){this._handleIn.set(0,0),this._handleOut.set(0,0)},getSelection:function(){return this._selection},setSelection:function(t){var e=this._selection,n=this._path;this._selection=t=t||0,n&&t!==e&&(n._updateSelection(this,e,t),n._changed(129))},changeSelection:function(t,e){var n=this._selection;this.setSelection(e?n|t:n&~t)},isSelected:function(){return!!(7&this._selection)},setSelected:function(t){this.changeSelection(7,t)},getIndex:function(){return this._index!==e?this._index:null},getPath:function(){return this._path||null},getCurve:function(){var t=this._path,e=this._index;return t?(e>0&&!t._closed&&e===t._segments.length-1&&e--,t.getCurves()[e]||null):null},getLocation:function(){var t=this.getCurve();return t?new z(t,this===t._segment1?0:1):null},getNext:function(){var t=this._path&&this._path._segments;return t&&(t[this._index+1]||this._path._closed&&t[0])||null},smooth:function(t,n,i){var r=t||{},s=r.type,a=r.factor,o=this.getPrevious(),h=this.getNext(),u=(o||this)._point,l=this._point,f=(h||this)._point,d=u.getDistance(l),_=l.getDistance(f);if(s&&"catmull-rom"!==s){if("geometric"!==s)throw new Error("Smoothing method '"+s+"' not supported.");if(o&&h){var g=u.subtract(f),v=a===e?.4:a,p=v*d/(d+_);n||this.setHandleIn(g.multiply(p)),i||this.setHandleOut(g.multiply(p-v))}}else{var m=a===e?.5:a,y=Math.pow(d,m),w=y*y,x=Math.pow(_,m),b=x*x;if(!n&&o){var C=2*b+3*x*y+w,S=3*x*(x+y);this.setHandleIn(0!==S?new c((b*u._x+C*l._x-w*f._x)/S-l._x,(b*u._y+C*l._y-w*f._y)/S-l._y):new c)}if(!i&&h){var C=2*w+3*y*x+b,S=3*y*(y+x);this.setHandleOut(0!==S?new c((w*f._x+C*l._x-b*u._x)/S-l._x,(w*f._y+C*l._y-b*u._y)/S-l._y):new c)}}},getPrevious:function(){var t=this._path&&this._path._segments;return t&&(t[this._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._index},isLast:function(){var t=this._path;return t&&this._index===t._segments.length-1||!1},reverse:function(){var t=this._handleIn,e=this._handleOut,n=t._x,i=t._y;t.set(e._x,e._y),e.set(n,i)},reversed:function(){return new M(this._point,this._handleOut,this._handleIn)},remove:function(){return!!this._path&&!!this._path.removeSegment(this._index)},clone:function(){return new M(this._point,this._handleIn,this._handleOut)},equals:function(t){return t===this||t&&this._class===t._class&&this._point.equals(t._point)&&this._handleIn.equals(t._handleIn)&&this._handleOut.equals(t._handleOut)||!1},toString:function(){var t=["point: "+this._point];return this._handleIn.isZero()||t.push("handleIn: "+this._handleIn),this._handleOut.isZero()||t.push("handleOut: "+this._handleOut),"{ "+t.join(", ")+" }"},transform:function(t){this._transformCoordinates(t,new Array(6),!0),this._changed()},interpolate:function(t,e,n){var i=1-n,r=n,s=t._point,a=e._point,o=t._handleIn,h=e._handleIn,u=e._handleOut,l=t._handleOut;this._point.set(i*s._x+r*a._x,i*s._y+r*a._y,!0),this._handleIn.set(i*o._x+r*h._x,i*o._y+r*h._y,!0),this._handleOut.set(i*l._x+r*u._x,i*l._y+r*u._y,!0),this._changed()},_transformCoordinates:function(t,e,n){var i=this._point,r=n&&this._handleIn.isZero()?null:this._handleIn,s=n&&this._handleOut.isZero()?null:this._handleOut,a=i._x,o=i._y,h=2;return e[0]=a,e[1]=o,r&&(e[h++]=r._x+a,e[h++]=r._y+o),s&&(e[h++]=s._x+a,e[h++]=s._y+o),t&&(t._transformCoordinates(e,e,h/2),a=e[0],o=e[1],n?(i._x=a,i._y=o,h=2,r&&(r._x=e[h++]-a,r._y=e[h++]-o),s&&(s._x=e[h++]-a,s._y=e[h++]-o)):(r||(e[h++]=a,e[h++]=o),s||(e[h++]=a,e[h++]=o))),e}}),A=c.extend({initialize:function(t,n,i){var r,s,a;if(t)if((r=t[0])!==e)s=t[1];else{var o=t;(r=o.x)===e&&(o=c.read(arguments),r=o.x),s=o.y,a=o.selected}else r=s=0;this._x=r,this._y=s,this._owner=n,n[i]=this,a&&this.setSelected(!0)},set:function(t,e){return this._x=t,this._y=e,this._owner._changed(this),this},getX:function(){return this._x},setX:function(t){this._x=t,this._owner._changed(this)},getY:function(){return this._y},setY:function(t){this._y=t,this._owner._changed(this)},isZero:function(){return u.isZero(this._x)&&u.isZero(this._y)},isSelected:function(){return!!(this._owner._selection&this._getSelection())},setSelected:function(t){this._owner.changeSelection(this._getSelection(),t)},_getSelection:function(){var t=this._owner;return this===t._point?1:this===t._handleIn?2:this===t._handleOut?4:0}}),T=r.extend({_class:"Curve",initialize:function(t,e,n,i,r,s,a,o){var h,u,l,c,f,d,_=arguments.length;3===_?(this._path=t,h=e,u=n):0===_?(h=new M,u=new M):1===_?"segment1"in t?(h=new M(t.segment1),u=new M(t.segment2)):"point1"in t?(l=t.point1,f=t.handle1,d=t.handle2,c=t.point2):Array.isArray(t)&&(l=[t[0],t[1]],c=[t[6],t[7]],f=[t[2]-t[0],t[3]-t[1]],d=[t[4]-t[6],t[5]-t[7]]):2===_?(h=new M(t),u=new M(e)):4===_?(l=t,f=e,d=n,c=i):8===_&&(l=[t,e],c=[a,o],f=[n-t,i-e],d=[r-a,s-o]),this._segment1=h||new M(l,null,f),this._segment2=u||new M(c,d,null)},_serialize:function(t,e){return r.serialize(this.hasHandles()?[this.getPoint1(),this.getHandle1(),this.getHandle2(),this.getPoint2()]:[this.getPoint1(),this.getPoint2()],t,!0,e)},_changed:function(){this._length=this._bounds=e},clone:function(){return new T(this._segment1,this._segment2)},toString:function(){var t=["point1: "+this._segment1._point];return this._segment1._handleOut.isZero()||t.push("handle1: "+this._segment1._handleOut),this._segment2._handleIn.isZero()||t.push("handle2: "+this._segment2._handleIn),t.push("point2: "+this._segment2._point),"{ "+t.join(", ")+" }"},remove:function(){var t=!1;if(this._path){var e=this._segment2,n=e._handleOut;t=e.remove(),t&&this._segment1._handleOut.set(n.x,n.y)}return t},getPoint1:function(){return this._segment1._point},setPoint1:function(){var t=c.read(arguments);this._segment1._point.set(t.x,t.y)},getPoint2:function(){return this._segment2._point},setPoint2:function(){var t=c.read(arguments);this._segment2._point.set(t.x,t.y)},getHandle1:function(){return this._segment1._handleOut},setHandle1:function(){var t=c.read(arguments);this._segment1._handleOut.set(t.x,t.y)},getHandle2:function(){return this._segment2._handleIn},setHandle2:function(){var t=c.read(arguments);this._segment2._handleIn.set(t.x,t.y)},getSegment1:function(){return this._segment1},getSegment2:function(){return this._segment2},getPath:function(){return this._path},getIndex:function(){return this._segment1._index},getNext:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index+1]||this._path._closed&&t[0])||null},getPrevious:function(){var t=this._path&&this._path._curves;return t&&(t[this._segment1._index-1]||this._path._closed&&t[t.length-1])||null},isFirst:function(){return 0===this._segment1._index},isLast:function(){var t=this._path;return t&&this._segment1._index===t._curves.length-1||!1},isSelected:function(){return this.getPoint1().isSelected()&&this.getHandle2().isSelected()&&this.getHandle2().isSelected()&&this.getPoint2().isSelected()},setSelected:function(t){this.getPoint1().setSelected(t),this.getHandle1().setSelected(t),this.getHandle2().setSelected(t),this.getPoint2().setSelected(t)},getValues:function(t){return T.getValues(this._segment1,this._segment2,t)},getPoints:function(){for(var t=this.getValues(),e=[],n=0;n<8;n+=2)e.push(new c(t[n],t[n+1]));return e},getLength:function(){return null==this._length&&(this._length=T.getLength(this.getValues(),0,1)),this._length},getArea:function(){return T.getArea(this.getValues())},getLine:function(){return new m(this._segment1._point,this._segment2._point)},getPart:function(t,e){return new T(T.getPart(this.getValues(),t,e))},getPartLength:function(t,e){return T.getLength(this.getValues(),t,e)},getIntersections:function(t){return T._getIntersections(this.getValues(),t&&t!==this?t.getValues():null,this,t,[],{})},divideAt:function(t){return this.divideAtTime(t&&t.curve===this?t.time:t)},divideAtTime:function(t,e){var n=4e-7,i=1-n,r=null;if(t>=n&&t<=i){var s=T.subdivide(this.getValues(),t),a=s[0],o=s[1],h=e||this.hasHandles(),u=this._segment1,l=this._segment2,f=this._path;h&&(u._handleOut.set(a[2]-a[0],a[3]-a[1]),l._handleIn.set(o[4]-o[6],o[5]-o[7]));var d=a[6],_=a[7],g=new M(new c(d,_),h&&new c(a[4]-d,a[5]-_),h&&new c(o[2]-d,o[3]-_));f?(f.insert(u._index+1,g),r=this.getNext()):(this._segment2=g,this._changed(),r=new T(g,l))}return r},splitAt:function(t){return this._path?this._path.splitAt(t):null},splitAtTime:function(t){return this.splitAt(this.getLocationAtTime(t))},divide:function(t,n){return this.divideAtTime(t===e?.5:n?t:this.getTimeAt(t))},split:function(t,n){return this.splitAtTime(t===e?.5:n?t:this.getTimeAt(t))},reversed:function(){return new T(this._segment2.reversed(),this._segment1.reversed())},clearHandles:function(){this._segment1._handleOut.set(0,0),this._segment2._handleIn.set(0,0)},statics:{getValues:function(t,e,n){var i=t._point,r=t._handleOut,s=e._handleIn,a=e._point,o=[i._x,i._y,i._x+r._x,i._y+r._y,a._x+s._x,a._y+s._y,a._x,a._y];return n&&n._transformCoordinates(o,o,4),o},subdivide:function(t,n){var i=t[0],r=t[1],s=t[2],a=t[3],o=t[4],h=t[5],u=t[6],l=t[7];n===e&&(n=.5);var c=1-n,f=c*i+n*s,d=c*r+n*a,_=c*s+n*o,g=c*a+n*h,v=c*o+n*u,p=c*h+n*l,m=c*f+n*_,y=c*d+n*g,w=c*_+n*v,x=c*g+n*p,b=c*m+n*w,C=c*y+n*x;return[[i,r,f,d,m,y,b,C],[b,C,w,x,v,p,u,l]]},solveCubic:function(t,e,n,i,r,s){var a=t[e],o=t[e+2],h=t[e+4],l=t[e+6],c=0;if(!(a<n&&l<n&&o<n&&h<n||a>n&&l>n&&o>n&&h>n)){var f=3*(o-a),d=3*(h-o)-f,_=l-a-f-d;c=u.solveCubic(_,d,f,a-n,i,r,s)}return c},getTimeOf:function(t,e){var n=new c(t[0],t[1]),i=new c(t[6],t[7]),r=1e-12,s=e.isClose(n,r)?0:e.isClose(i,r)?1:null;if(null!==s)return s;for(var a=[e.x,e.y],o=[],h=2e-7,u=0;u<2;u++)for(var l=T.solveCubic(t,u,a[u],o,0,1),f=0;f<l;f++)if(s=o[f],e.isClose(T.getPoint(t,s),h))return s;return e.isClose(n,h)?0:e.isClose(i,h)?1:null},getNearestTime:function(t,e){function n(n){if(n>=0&&n<=1){var i=e.getDistance(T.getPoint(t,n),!0);if(i<d)return d=i,_=n,!0}}if(T.isStraight(t)){var i=t[0],r=t[1],s=t[6],a=t[7],o=s-i,h=a-r,u=o*o+h*h;if(0===u)return 0;var l=((e.x-i)*o+(e.y-r)*h)/u;return l<1e-12?0:l>.999999999999?1:T.getTimeOf(t,new c(i+l*o,r+l*h))}for(var f=100,d=1/0,_=0,g=0;g<=f;g++)n(g/f);for(var v=1/(2*f);v>4e-7;)n(_-v)||n(_+v)||(v/=2);return _},getPart:function(t,e,n){var i=e>n;if(i){var r=e;e=n,n=r}return e>0&&(t=T.subdivide(t,e)[1]),n<1&&(t=T.subdivide(t,(n-e)/(1-e))[0]),i?[t[6],t[7],t[4],t[5],t[2],t[3],t[0],t[1]]:t},isFlatEnough:function(t,e){var n=t[0],i=t[1],r=t[2],s=t[3],a=t[4],o=t[5],h=t[6],u=t[7],l=3*r-2*n-h,c=3*s-2*i-u,f=3*a-2*h-n,d=3*o-2*u-i;return Math.max(l*l,f*f)+Math.max(c*c,d*d)<=16*e*e},getArea:function(t){var e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7];return 3*((h-n)*(i+s)-(o-e)*(r+a)+r*(e-s)-i*(n-a)+h*(s+e/3)-o*(a+n/3))/20},getBounds:function(t){for(var e=t.slice(0,2),n=e.slice(),i=[0,0],r=0;r<2;r++)T._addBounds(t[r],t[r+2],t[r+4],t[r+6],r,0,e,n,i);return new g(e[0],e[1],n[0]-e[0],n[1]-e[1])},_addBounds:function(t,e,n,i,r,s,a,o,h){function l(t,e){var n=t-e,i=t+e;n<a[r]&&(a[r]=n),i>o[r]&&(o[r]=i)}s/=2;var c=a[r]-s,f=o[r]+s;if(t<c||e<c||n<c||i<c||t>f||e>f||n>f||i>f)if(e<t!=e<i&&n<t!=n<i)l(t,s),l(i,s);else{var d=3*(e-n)-t+i,_=2*(t+n)-4*e,g=e-t,v=u.solveQuadratic(d,_,g,h),p=4e-7,m=1-p;l(i,0);for(var y=0;y<v;y++){var w=h[y],x=1-w;p<w&&w<m&&l(x*x*x*t+3*x*x*w*e+3*x*w*w*n+w*w*w*i,s)}}}}},r.each(["getBounds","getStrokeBounds","getHandleBounds"],function(t){this[t]=function(){this._bounds||(this._bounds={});var e=this._bounds[t];return e||(e=this._bounds[t]=E[t]([this._segment1,this._segment2],!1,this._path)),e.clone()}},{}),r.each({isStraight:function(t,e,n){if(e.isZero()&&n.isZero())return!0;var i=t.getVector(),r=2e-7;if(i.isZero())return!1;if(t.getDistance(e)<r&&t.getDistance(n)<r){var s=i.dot(i),a=i.dot(e)/s,o=i.dot(n)/s;return a>=0&&a<=1&&o<=0&&o>=-1}return!1},isLinear:function(t,e,n){var i=t.getVector().divide(3);return e.equals(i)&&n.negate().equals(i)}},function(t,e){this[e]=function(){var e=this._segment1,n=this._segment2;return t(new m(e._point,n._point),e._handleOut,n._handleIn)},this.statics[e]=function(e){var n=e[0],i=e[1],r=e[6],s=e[7];return t(new m(n,i,r,s),new c(e[2]-n,e[3]-i),new c(e[4]-r,e[5]-s))}},{statics:{},hasHandles:function(){return!this._segment1._handleOut.isZero()||!this._segment2._handleIn.isZero()},isCollinear:function(t){return t&&this.isStraight()&&t.isStraight()&&this.getLine().isCollinear(t.getLine())},isHorizontal:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).y)<1e-7},isVertical:function(){return this.isStraight()&&Math.abs(this.getTangentAtTime(.5).x)<1e-7}}),{beans:!1,getLocationAt:function(t,e){return this.getLocationAtTime(e?t:this.getTimeAt(t))},getLocationAtTime:function(t){return null!=t&&t>=0&&t<=1?new z(this,t):null},getTimeAt:function(t,e){return T.getTimeAt(this.getValues(),t,e)},getParameterAt:"#getTimeAt",getOffsetAtTime:function(t){return this.getPartLength(0,t)},getLocationOf:function(){return this.getLocationAtTime(this.getTimeOf(c.read(arguments)))},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getTimeOf:function(){return T.getTimeOf(this.getValues(),c.read(arguments))},getParameterOf:"#getTimeOf",getNearestLocation:function(){var t=c.read(arguments),e=this.getValues(),n=T.getNearestTime(e,t),i=T.getPoint(e,n);return new z(this,n,i,null,t.getDistance(i))},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t}},new function(){var t=["getPoint","getTangent","getNormal","getWeightedTangent","getWeightedNormal","getCurvature"];return r.each(t,function(t){this[t+"At"]=function(e,n){var i=this.getValues();return T[t](i,n?e:T.getTimeAt(i,e))},this[t+"AtTime"]=function(e){return T[t](this.getValues(),e)}},{statics:{_evaluateMethods:t}})},new function(){function t(t){var e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],h=t[7],u=9*(i-s)+3*(o-e),l=6*(e+s)-12*i,c=3*(i-e),f=9*(r-a)+3*(h-n),d=6*(n+a)-12*r,_=3*(r-n);return function(t){var e=(u*t+l)*t+c,n=(f*t+d)*t+_;return Math.sqrt(e*e+n*n)}}function n(t,e){return Math.max(2,Math.min(16,Math.ceil(32*Math.abs(e-t))))}function i(t,e,n,i){if(null==e||e<0||e>1)return null;var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],f=t[6],d=t[7],_=u.isZero;_(a-r)&&_(o-s)&&(a=r,o=s),_(h-f)&&_(l-d)&&(h=f,l=d);var g,v,p=3*(a-r),m=3*(h-a)-p,y=f-r-p-m,w=3*(o-s),x=3*(l-o)-w,b=d-s-w-x;if(0===n)g=0===e?r:1===e?f:((y*e+m)*e+p)*e+r,v=0===e?s:1===e?d:((b*e+x)*e+w)*e+s;else{var C=4e-7,S=1-C;if(e<C?(g=p,v=w):e>S?(g=3*(f-h),v=3*(d-l)):(g=(3*y*e+2*m)*e+p,v=(3*b*e+2*x)*e+w),i){0===g&&0===v&&(e<C||e>S)&&(g=h-a,v=l-o);var k=Math.sqrt(g*g+v*v);k&&(g/=k,v/=k)}if(3===n){var I=6*y*e+2*m,P=6*b*e+2*x,M=Math.pow(g*g+v*v,1.5);g=0!==M?(g*P-v*I)/M:0,v=0}}return 2===n?new c(v,(-g)):new c(g,v)}return{statics:{getLength:function(i,r,s,a){if(r===e&&(r=0),s===e&&(s=1),T.isStraight(i)){var o=i;s<1&&(o=T.subdivide(o,s)[0],r/=s),r>0&&(o=T.subdivide(o,r)[1]);var h=o[6]-o[0],l=o[7]-o[1];return Math.sqrt(h*h+l*l)}return u.integrate(a||t(i),r,s,n(r,s))},getTimeAt:function(i,r,s){function a(t){return p+=u.integrate(d,s,t,n(s,t)),s=t,p-r}if(s===e&&(s=r<0?1:0),0===r)return s;var o=Math.abs,h=1e-12,l=r>0,c=l?s:0,f=l?1:s,d=t(i),_=T.getLength(i,c,f,d),g=o(r)-_;if(o(g)<h)return l?f:c;if(g>h)return null;var v=r/_,p=0;return u.findRoot(a,d,s+v,c,f,32,1e-12)},getPoint:function(t,e){return i(t,e,0,!1)},getTangent:function(t,e){return i(t,e,1,!0)},getWeightedTangent:function(t,e){return i(t,e,1,!1)},getNormal:function(t,e){return i(t,e,2,!0)},getWeightedNormal:function(t,e){return i(t,e,2,!1)},getCurvature:function(t,e){return i(t,e,3,!1).x}}}},new function(){function t(t,e,n,i,r,s,a,o,h,u,l){var c=!l&&e.excludeStart,f=!l&&e.excludeEnd,d=4e-7,_=1-d;if(null==r&&(r=T.getTimeOf(n,s)),null!==r&&r>=(c?d:0)&&r<=(f?_:1)&&(null==h&&(h=T.getTimeOf(a,u)),null!==h&&h>=(f?d:0)&&h<=(c?_:1))){var g=e.renormalize;
-if(g){var v=g(r,h);r=v[0],h=v[1]}var p=new z(i,r,s||T.getPoint(n,r),l),m=new z(o,h,u||T.getPoint(a,h),l),y=p.getPath()===m.getPath()&&p.getIndex()>m.getIndex(),w=y?m:p,x=e.include;p._intersection=m,m._intersection=p,x&&!x(w)||z.insert(t,w,!0)}}function e(r,s,a,o,h,u,l,c,f,d,_,g,v){if(++g>=48||++v>4096)return v;var p,y,w=s[0],x=s[1],b=s[6],C=s[7],S=m.getSignedDistance,k=S(w,x,b,C,s[2],s[3]),I=S(w,x,b,C,s[4],s[5]),P=k*I>0?.75:4/9,M=P*Math.min(0,k,I),A=P*Math.max(0,k,I),z=S(w,x,b,C,r[0],r[1]),O=S(w,x,b,C,r[2],r[3]),E=S(w,x,b,C,r[4],r[5]),L=S(w,x,b,C,r[6],r[7]),N=n(z,O,E,L),B=N[0],j=N[1];if(0===k&&0===I&&0===z&&0===O&&0===E&&0===L||null==(p=i(B,j,M,A))||null==(y=i(B.reverse(),j.reverse(),M,A)))return v;var F=l+(c-l)*p,D=l+(c-l)*y;if(Math.max(d-f,D-F)<1e-9){var R=(F+D)/2,q=(f+d)/2;r=a.getValues(),s=o.getValues(),t(h,u,_?s:r,_?o:a,_?q:R,null,_?r:s,_?a:o,_?R:q,null)}else if(r=T.getPart(r,p,y),y-p>.8)if(D-F>d-f){var V=T.subdivide(r,.5),R=(F+D)/2;v=e(s,V[0],o,a,h,u,f,d,F,R,!_,g,v),v=e(s,V[1],o,a,h,u,f,d,R,D,!_,g,v)}else{var V=T.subdivide(s,.5),q=(f+d)/2;v=e(V[0],r,o,a,h,u,f,q,F,D,!_,g,v),v=e(V[1],r,o,a,h,u,q,d,F,D,!_,g,v)}else v=e(s,r,o,a,h,u,f,d,F,D,!_,g,v);return v}function n(t,e,n,i){var r,s=[0,t],a=[1/3,e],o=[2/3,n],h=[1,i],u=e-(2*t+i)/3,l=n-(t+2*i)/3;if(u*l<0)r=[[s,a,h],[s,o,h]];else{var c=u/l;r=[c>=2?[s,a,h]:c<=.5?[s,o,h]:[s,a,o,h],[s,h]]}return(u||l)<0?r.reverse():r}function i(t,e,n,i){return t[0][1]<n?r(t,!0,n):e[0][1]>i?r(e,!1,i):t[0][0]}function r(t,e,n){for(var i=t[0][0],r=t[0][1],s=1,a=t.length;s<a;s++){var o=t[s][0],h=t[s][1];if(e?h>=n:h<=n)return h===n?o:i+(n-r)*(o-i)/(h-r);i=o,r=h}return null}function s(e,n,i,r,s,a){for(var o=T.isStraight(e),h=o?n:e,l=o?e:n,c=l[0],f=l[1],d=l[6],_=l[7],g=d-c,v=_-f,p=Math.atan2(-v,g),m=Math.sin(p),y=Math.cos(p),w=[],x=0;x<8;x+=2){var b=h[x]-c,C=h[x+1]-f;w.push(b*y-C*m,b*m+C*y)}for(var S=[],k=T.solveCubic(w,1,0,S,0,1),x=0;x<k;x++){var I=S[x],P=T.getPoint(h,I),M=T.getTimeOf(l,P);if(null!==M){var A=T.getPoint(l,M),z=o?M:I,O=o?I:M;(!a.excludeEnd||O>u.CURVETIME_EPSILON)&&t(s,a,e,i,z,o?A:P,n,r,O,o?P:A)}}}function a(e,n,i,r,s,a){var o=m.intersect(e[0],e[1],e[6],e[7],n[0],n[1],n[6],n[7]);o&&t(s,a,e,i,null,o,n,r,null,o)}return{statics:{_getIntersections:function(n,i,r,o,h,u){if(!i)return T._getSelfIntersection(n,r,h,u);var l=2e-7,f=n[0],d=n[1],_=n[6],g=n[7],v=i[0],p=i[1],m=i[6],y=i[7],w=(3*n[2]+f)/4,x=(3*n[3]+d)/4,b=(3*n[4]+_)/4,C=(3*n[5]+g)/4,S=(3*i[2]+v)/4,k=(3*i[3]+p)/4,I=(3*i[4]+m)/4,P=(3*i[5]+y)/4,M=Math.min,A=Math.max;if(!(A(f,w,b,_)+l>M(v,S,I,m)&&M(f,w,b,_)-l<A(v,S,I,m)&&A(d,x,C,g)+l>M(p,k,P,y)&&M(d,x,C,g)-l<A(p,k,P,y)))return h;var z=T.getOverlaps(n,i);if(z){for(var O=0;O<2;O++){var E=z[O];t(h,u,n,r,E[0],null,i,o,E[1],null,!0)}return h}var L=T.isStraight(n),N=T.isStraight(i),B=L&&N,j=h.length;if((B?a:L||N?s:e)(n,i,r,o,h,u,0,1,0,1,0,0,0),B&&h.length>j)return h;var F=new c(f,d),D=new c(_,g),R=new c(v,p),q=new c(m,y);return F.isClose(R,l)&&t(h,u,n,r,0,F,i,o,0,R),!u.excludeStart&&F.isClose(q,l)&&t(h,u,n,r,0,F,i,o,1,q),!u.excludeEnd&&D.isClose(R,l)&&t(h,u,n,r,1,D,i,o,0,R),D.isClose(q,l)&&t(h,u,n,r,1,D,i,o,1,q),h},_getSelfIntersection:function(t,e,n,i){var r=t[0],s=t[1],a=t[2],o=t[3],h=t[4],l=t[5],f=t[6],d=t[7],_=new m(r,s,f,d,(!1)),g=_.getSide(new c(a,o),!0),v=_.getSide(new c(h,l),!0);if(g===v){var p=(r-h)*(o-d)+(a-f)*(l-s);if(p*g>0)return n}var y=f-3*h+3*a-r,w=h-2*a+r,x=a-r,b=d-3*l+3*o-s,C=l-2*o+s,S=o-s,k=b*x-y*S,I=b*w-y*C,P=C*x-w*S;if(k*k-4*I*P<0){var M,A=[],z=u.solveCubic(y*y+b*b,3*(y*w+b*C),2*(w*w+C*C)+y*x+b*S,w*x+C*S,A,0,1);if(z>0){for(var O=0,E=0;O<z;O++){var L=Math.abs(e.getCurvatureAtTime(A[O]));L>E&&(E=L,M=A[O])}var N=T.subdivide(t,M);i.excludeEnd=!0,i.renormalize=function(t,e){return[t*M,e*(1-M)+M]},T._getIntersections(N[0],N[1],e,e,n,i)}}return n},getOverlaps:function(t,e){function n(t){var e=t[6]-t[0],n=t[7]-t[1];return e*e+n*n}var i=Math.abs,r=4e-7,s=2e-7,a=T.isStraight(t),o=T.isStraight(e),h=a&&o,u=n(t)<n(e),l=u?e:t,f=u?t:e,d=new m(l[0],l[1],l[6],l[7]);if(d.getDistance(new c(f[0],f[1]))<s&&d.getDistance(new c(f[6],f[7]))<s)!h&&d.getDistance(new c(l[2],l[3]))<s&&d.getDistance(new c(l[4],l[5]))<s&&d.getDistance(new c(f[2],f[3]))<s&&d.getDistance(new c(f[4],f[5]))<s&&(a=o=h=!0);else if(h)return null;if(a^o)return null;for(var _=[t,e],g=[],v=0,p=0;v<2&&g.length<2;v+=0===p?0:1,p=1^p){var y=T.getTimeOf(_[1^v],new c(_[v][0===p?0:6],_[v][0===p?1:7]));if(null!=y){var w=0===v?[p,y]:[y,p];(0===g.length||i(w[0]-g[0][0])>r&&i(w[1]-g[0][1])>r)&&g.push(w)}if(1===v&&0===g.length)break}if(2!==g.length)g=null;else if(!h){var x=T.getPart(t,g[0][0],g[1][0]),b=T.getPart(e,g[0][1],g[1][1]);(i(b[2]-x[2])>s||i(b[3]-x[3])>s||i(b[4]-x[4])>s||i(b[5]-x[5])>s)&&(g=null)}return g}}}}),z=r.extend({_class:"CurveLocation",beans:!0,initialize:function(t,e,n,i,r){if(e>.9999996){var s=t.getNext();s&&(e=0,t=s)}this._setCurve(t),this._time=e,this._point=n||t.getPointAtTime(e),this._overlap=i,this._distance=r,this._intersection=this._next=this._previous=null},_setCurve:function(t){var e=t._path;this._path=e,this._version=e?e._version:0,this._curve=t,this._segment=null,this._segment1=t._segment1,this._segment2=t._segment2},_setSegment:function(t){this._setCurve(t.getCurve()),this._segment=t,this._time=t===this._segment1?0:1,this._point=t._point.clone()},getSegment:function(){var t=this.getCurve(),e=this._segment;if(!e){var n=this.getTime();0===n?e=t._segment1:1===n?e=t._segment2:null!=n&&(e=t.getPartLength(0,n)<t.getPartLength(n,1)?t._segment1:t._segment2),this._segment=e}return e},getCurve:function(){function t(t){var e=t&&t.getCurve();if(e&&null!=(n._time=e.getTimeOf(n._point)))return n._setCurve(e),n._segment=t,e}var e=this._path,n=this;return e&&e._version!==this._version&&(this._time=this._curve=this._offset=null),this._curve||t(this._segment)||t(this._segment1)||t(this._segment2.getPrevious())},getPath:function(){var t=this.getCurve();return t&&t._path},getIndex:function(){var t=this.getCurve();return t&&t.getIndex()},getTime:function(){var t=this.getCurve(),e=this._time;return t&&null==e?this._time=t.getTimeOf(this._point):e},getParameter:"#getTime",getPoint:function(){return this._point},getOffset:function(){var t=this._offset;if(null==t){t=0;var e=this.getPath(),n=this.getIndex();if(e&&null!=n)for(var i=e.getCurves(),r=0;r<n;r++)t+=i[r].getLength();this._offset=t+=this.getCurveOffset()}return t},getCurveOffset:function(){var t=this.getCurve(),e=this.getTime();return null!=e&&t&&t.getPartLength(0,e)},getIntersection:function(){return this._intersection},getDistance:function(){return this._distance},divide:function(){var t=this.getCurve(),e=null;return t&&(e=t.divideAtTime(this.getTime()),e&&this._setSegment(e._segment1)),e},split:function(){var t=this.getCurve();return t?t.splitAtTime(this.getTime()):null},equals:function(t,e){var n=this===t,i=2e-7;if(!n&&t instanceof z&&this.getPath()===t.getPath()&&this.getPoint().isClose(t.getPoint(),i)){var r=this.getCurve(),s=t.getCurve(),a=Math.abs,o=a((r.isLast()&&s.isFirst()?-1:r.getIndex())+this.getTime()-((s.isLast()&&r.isFirst()?-1:s.getIndex())+t.getTime()));n=(o<4e-7||(o=a(this.getOffset()-t.getOffset()))<i||a(this.getPath().getLength()-o)<i)&&(e||!this._intersection&&!t._intersection||this._intersection&&this._intersection.equals(t._intersection,!0))}return n},toString:function(){var t=[],e=this.getPoint(),n=h.instance;e&&t.push("point: "+e);var i=this.getIndex();null!=i&&t.push("index: "+i);var r=this.getTime();return null!=r&&t.push("time: "+n.number(r)),null!=this._distance&&t.push("distance: "+n.number(this._distance)),"{ "+t.join(", ")+" }"},isTouching:function(){var t=this._intersection;if(t&&this.getTangent().isCollinear(t.getTangent())){var e=this.getCurve(),n=t.getCurve();return!(e.isStraight()&&n.isStraight()&&e.getLine().intersect(n.getLine()))}return!1},isCrossing:function(){function t(t,e,n){return e<n?t>e&&t<n:t>e||t<n}var e=this._intersection;if(!e)return!1;var n=this.getTime(),i=e.getTime(),r=4e-7,s=1-r,a=n>r&&n<s,o=i>r&&i<s;if(a&&o)return!this.isTouching();var h=this.getCurve(),u=n<=r?h.getPrevious():h,l=e.getCurve(),c=i<=r?l.getPrevious():l;if(n>=s&&(h=h.getNext()),i>=s&&(l=l.getNext()),!(u&&h&&c&&l))return!1;var f=[];a||f.push(u.getLength(),h.getLength()),o||f.push(c.getLength(),l.getLength());var d=this.getPoint(),_=Math.min.apply(Math,f)/64,g=a?h.getTangentAtTime(n):h.getPointAt(_).subtract(d),v=a?g.negate():u.getPointAt(-_).subtract(d),p=o?l.getTangentAtTime(i):l.getPointAt(_).subtract(d),m=o?p.negate():c.getPointAt(-_).subtract(d),y=v.getAngle(),w=g.getAngle(),x=m.getAngle(),b=p.getAngle();return!!(a?t(y,x,b)^t(w,x,b)&&t(y,b,x)^t(w,b,x):t(x,y,w)^t(b,y,w)&&t(x,w,y)^t(b,w,y))},hasOverlap:function(){return!!this._overlap}},r.each(T._evaluateMethods,function(t){var e=t+"At";this[t]=function(){var t=this.getCurve(),n=this.getTime();return null!=n&&t&&t[e](n,!0)}},{preserve:!0}),new function(){function t(t,e,n){function i(n,i){for(var s=n+i;s>=-1&&s<=r;s+=i){var a=t[(s%r+r)%r];if(!e.getPoint().isClose(a.getPoint(),2e-7))break;if(e.equals(a))return a}return null}for(var r=t.length,s=0,a=r-1;s<=a;){var o,h=s+a>>>1,u=t[h];if(n&&(o=e.equals(u)?u:i(h,-1)||i(h,1)))return e._overlap&&(o._overlap=o._intersection._overlap=!0),o;var l=e.getPath(),c=u.getPath(),f=l===c?e.getIndex()+e.getTime()-(u.getIndex()+u.getTime()):l._id-c._id;f<0?a=h-1:s=h+1}return t.splice(s,0,e),e}return{statics:{insert:t,expand:function(e){for(var n=e.slice(),i=e.length-1;i>=0;i--)t(n,e[i]._intersection,!1);return n}}}}),O=w.extend({_class:"PathItem",_selectBounds:!1,_canScaleStroke:!0,initialize:function(){},statics:{create:function(t){var e=(t&&t.match(/m/gi)||[]).length>1||/z\s*\S+/i.test(t)?L:E;return new e(t)}},_asPathItem:function(){return this},setPathData:function(t){function e(t,e){var n=+i[t];return o&&(n+=h[e]),n}function n(t){return new c(e(t,"x"),e(t+1,"y"))}var i,r,s,a=t&&t.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/gi),o=!1,h=new c,u=new c;this.clear();for(var l=0,f=a&&a.length;l<f;l++){var _=a[l],g=_[0],v=g.toLowerCase();i=_.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);var p=i&&i.length;switch(o=g===v,"z"!==r||/[mz]/.test(v)||this.moveTo(h=u),v){case"m":case"l":for(var m="m"===v,y=0;y<p;y+=2)this[0===y&&m?"moveTo":"lineTo"](h=n(y));s=h,m&&(u=h);break;case"h":case"v":for(var w="h"===v?"x":"y",y=0;y<p;y++)h[w]=e(y,w),this.lineTo(h);s=h;break;case"c":for(var y=0;y<p;y+=6)this.cubicCurveTo(n(y),s=n(y+2),h=n(y+4));break;case"s":for(var y=0;y<p;y+=4)this.cubicCurveTo(/[cs]/.test(r)?h.multiply(2).subtract(s):h,s=n(y),h=n(y+2)),r=v;break;case"q":for(var y=0;y<p;y+=4)this.quadraticCurveTo(s=n(y),h=n(y+2));break;case"t":for(var y=0;y<p;y+=2)this.quadraticCurveTo(s=/[qt]/.test(r)?h.multiply(2).subtract(s):h,h=n(y)),r=v;break;case"a":for(var y=0;y<p;y+=7)this.arcTo(h=n(y+5),new d((+i[y]),(+i[y+1])),+i[y+2],+i[y+4],+i[y+3]);break;case"z":this.closePath(1e-12)}r=v}},_canComposite:function(){return!(this.hasFill()&&this.hasStroke())},_contains:function(t){var e=t.isInside(this.getBounds({internal:!0,handle:!0}))&&this._getWinding(t);return!!("evenodd"===this.getFillRule()?1&e:e)},getIntersections:function(t,e,n,i){var r=this===t||!t,s=this._matrix._orNullIfIdentity(),a=r?s:(n||t._matrix)._orNullIfIdentity();if(!r&&!this.getBounds(s).touches(t.getBounds(a)))return[];for(var o,t,h=this.getCurves(),u=r?h:t.getCurves(),l=h.length,c=r?l:u.length,f=[],d=[],_=0;_<c;_++)f[_]=u[_].getValues(a);for(var _=0;_<l;_++){var g=h[_],v=r?f[_]:g.getValues(s),p=g.getPath();p!==t&&(t=p,o=[],d.push(o)),r&&T._getSelfIntersection(v,g,o,{include:e,excludeStart:1===l&&g.getPoint1().equals(g.getPoint2())});for(var m=r?_+1:0;m<c;m++){if(i&&o.length)return o;var y=u[m];T._getIntersections(v,f[m],g,y,o,{include:e,excludeStart:r&&g.getPrevious()===y,excludeEnd:r&&g.getNext()===y})}}o=[];for(var _=0,w=d.length;_<w;_++)o.push.apply(o,d[_]);return o},getCrossings:function(t){return this.getIntersections(t,function(t){return t._overlap||t.isCrossing()})},getNearestLocation:function(){for(var t=c.read(arguments),e=this.getCurves(),n=1/0,i=null,r=0,s=e.length;r<s;r++){var a=e[r].getNearestLocation(t);a._distance<n&&(n=a._distance,i=a)}return i},getNearestPoint:function(){var t=this.getNearestLocation.apply(this,arguments);return t?t.getPoint():t},interpolate:function(t,e,n){var i=!this._children,r=i?"_segments":"_children",s=t[r],a=e[r],o=this[r];if(!s||!a||s.length!==a.length)throw new Error("Invalid operands in interpolate() call: "+t+", "+e);var h=o.length,u=a.length;if(h<u)for(var l=i?M:E,c=h;c<u;c++)this.add(new l);else h>u&&this[i?"removeSegments":"removeChildren"](u,h);for(var c=0;c<u;c++)o[c].interpolate(s[c],a[c],n);i&&(this.setClosed(t._closed),this._changed(9))}}),E=O.extend({_class:"Path",_serializeFields:{segments:[],closed:!1},initialize:function(t){this._closed=!1,this._segments=[],this._version=0;var n=Array.isArray(t)?"object"==typeof t[0]?t:arguments:!t||t.size!==e||t.x===e&&t.point===e?null:arguments;n&&n.length>0?this.setSegments(n):(this._curves=e,this._segmentSelection=0,n||"string"!=typeof t||(this.setPathData(t),t=null)),this._initialize(!n&&t)},_equals:function(t){return this._closed===t._closed&&r.equals(this._segments,t._segments)},copyContent:function(t){this.setSegments(t._segments),this._closed=t._closed;var n=t._clockwise;n!==e&&(this._clockwise=n)},_changed:function vt(t){if(vt.base.call(this,t),8&t){if(this._length=this._area=this._clockwise=this._monoCurves=e,16&t)this._version++;else if(this._curves)for(var n=0,i=this._curves.length;n<i;n++)this._curves[n]._changed()}else 32&t&&(this._bounds=e)},getStyle:function(){var t=this._parent;return(t instanceof L?t:this)._style},getSegments:function(){return this._segments},setSegments:function(t){var n=this.isFullySelected();this._segments.length=0,this._segmentSelection=0,this._curves=e,t&&t.length>0&&this._add(M.readAll(t)),n&&this.setFullySelected(!0)},getFirstSegment:function(){return this._segments[0]},getLastSegment:function(){return this._segments[this._segments.length-1]},getCurves:function(){var t=this._curves,e=this._segments;if(!t){var n=this._countCurves();t=this._curves=new Array(n);for(var i=0;i<n;i++)t[i]=new T(this,e[i],e[i+1]||e[0])}return t},getFirstCurve:function(){return this.getCurves()[0]},getLastCurve:function(){var t=this.getCurves();return t[t.length-1]},isClosed:function(){return this._closed},setClosed:function(t){if(this._closed!=(t=!!t)){if(this._closed=t,this._curves){var e=this._curves.length=this._countCurves();t&&(this._curves[e-1]=new T(this,this._segments[e-1],this._segments[0]))}this._changed(25)}}},{beans:!0,getPathData:function(t,e){function n(e,n){e._transformCoordinates(t,g),i=g[0],r=g[1],v?(p.push("M"+_.pair(i,r)),v=!1):(o=g[2],u=g[3],o===i&&u===r&&l===s&&c===a?n||p.push("l"+_.pair(i-s,r-a)):p.push("c"+_.pair(l-s,c-a)+" "+_.pair(o-s,u-a)+" "+_.pair(i-s,r-a))),s=i,a=r,l=g[4],c=g[5]}var i,r,s,a,o,u,l,c,f=this._segments,d=f.length,_=new h(e),g=new Array(6),v=!0,p=[];if(0===d)return"";for(var m=0;m<d;m++)n(f[m]);return this._closed&&d>0&&(n(f[0],!0),p.push("z")),p.join("")},isEmpty:function(){return 0===this._segments.length},_transformContent:function(t){for(var e=this._segments,n=new Array(6),i=0,r=e.length;i<r;i++)e[i]._transformCoordinates(t,n,!0);return!0},_add:function(t,e){for(var n=this._segments,i=this._curves,r=t.length,s=null==e,e=s?n.length:e,a=0;a<r;a++){var o=t[a];o._path&&(o=t[a]=o.clone()),o._path=this,o._index=e+a,o._selection&&this._updateSelection(o,0,o._selection)}if(s)n.push.apply(n,t);else{n.splice.apply(n,[e,0].concat(t));for(var a=e+r,h=n.length;a<h;a++)n[a]._index=a}if(i){var u=this._countCurves(),l=e>0&&e+r-1===u?e-1:e,c=l,f=Math.min(l+r,u);t._curves&&(i.splice.apply(i,[l,0].concat(t._curves)),c+=t._curves.length);for(var a=c;a<f;a++)i.splice(a,0,new T(this,null,null));this._adjustCurves(l,f)}return this._changed(25),t},_adjustCurves:function(t,e){for(var n,i=this._segments,r=this._curves,s=t;s<e;s++)n=r[s],n._path=this,n._segment1=i[s],n._segment2=i[s+1]||i[0],n._changed();(n=r[this._closed&&0===t?i.length-1:t-1])&&(n._segment2=i[t]||i[0],n._changed()),(n=r[e])&&(n._segment1=i[e],n._changed())},_countCurves:function(){var t=this._segments.length;return!this._closed&&t>0?t-1:t},add:function(t){return arguments.length>1&&"number"!=typeof t?this._add(M.readAll(arguments)):this._add([M.read(arguments)])[0]},insert:function(t,e){return arguments.length>2&&"number"!=typeof e?this._add(M.readAll(arguments,1),t):this._add([M.read(arguments,1)],t)[0]},addSegment:function(){return this._add([M.read(arguments)])[0]},insertSegment:function(t){return this._add([M.read(arguments,1)],t)[0]},addSegments:function(t){return this._add(M.readAll(t))},insertSegments:function(t,e){return this._add(M.readAll(e),t)},removeSegment:function(t){return this.removeSegments(t,t+1)[0]||null},removeSegments:function(t,e,n){t=t||0,e=r.pick(e,this._segments.length);var i=this._segments,s=this._curves,a=i.length,o=i.splice(t,e-t),h=o.length;if(!h)return o;for(var u=0;u<h;u++){var l=o[u];l._selection&&this._updateSelection(l,l._selection,0),l._index=l._path=null}for(var u=t,c=i.length;u<c;u++)i[u]._index=u;if(s){for(var f=t>0&&e===a+(this._closed?1:0)?t-1:t,s=s.splice(f,h),u=s.length-1;u>=0;u--)s[u]._path=null;n&&(o._curves=s.slice(1)),this._adjustCurves(f,f)}return this._changed(25),o},clear:"#removeSegments",hasHandles:function(){for(var t=this._segments,e=0,n=t.length;e<n;e++)if(t[e].hasHandles())return!0;return!1},clearHandles:function(){for(var t=this._segments,e=0,n=t.length;e<n;e++)t[e].clearHandles()},getLength:function(){if(null==this._length){for(var t=this.getCurves(),e=0,n=0,i=t.length;n<i;n++)e+=t[n].getLength();this._length=e}return this._length},getArea:function(t){var n=t===e,i=this._area;if(!n||null==i){var r=this._segments,s=r.length,a=n?this._closed:t,o=s-1;i=0;for(var h=0,u=a?s:o;h<u;h++)i+=T.getArea(T.getValues(r[h],r[h<o?h+1:0]));n&&(this._area=i)}return i},isClockwise:function(){return this._clockwise!==e?this._clockwise:this.getArea()>=0},setClockwise:function(t){this.isClockwise()!=(t=!!t)&&this.reverse(),this._clockwise=t},isFullySelected:function(){var t=this._segments.length;return this.isSelected()&&t>0&&this._segmentSelection===7*t},setFullySelected:function(t){t&&this._selectSegments(!0),this.setSelected(t)},setSelection:function pt(t){1&t||this._selectSegments(!1),pt.base.call(this,t)},_selectSegments:function(t){var e=this._segments,n=e.length,i=t?7:0;this._segmentSelection=i*n;for(var r=0;r<n;r++)e[r]._selection=i},_updateSelection:function(t,e,n){t._selection=n;var i=this._segmentSelection+=n-e;i>0&&this.setSelected(!0)},splitAt:function(t){var e="number"==typeof t?this.getLocationAt(t):t,n=e&&e.index,i=e&&e.time,r=4e-7,s=1-r;i>=s&&(n++,i=0);var a=this.getCurves();if(n>=0&&n<a.length){i>=r&&a[n++].divideAtTime(i);var o,h=this.removeSegments(n,this._segments.length,!0);return this._closed?(this.setClosed(!1),o=this):(o=new E(w.NO_INSERT),o.insertAbove(this,!0),o.copyAttributes(this)),o._add(h,0),this.addSegment(h[0]),o}return null},split:function(t,n){var i,r=n===e?t:(i=this.getCurves()[t])&&i.getLocationAtTime(n);return null!=r?this.splitAt(r):null},join:function(t,e){var n=e||0;if(t&&t!==this){var i=t._segments,r=this.getLastSegment(),s=t.getLastSegment();if(!s)return this;r&&r._point.isClose(s._point,n)&&t.reverse();var a=t.getFirstSegment();if(r&&r._point.isClose(a._point,n))r.setHandleOut(a._handleOut),this._add(i.slice(1));else{var o=this.getFirstSegment();o&&o._point.isClose(a._point,n)&&t.reverse(),s=t.getLastSegment(),o&&o._point.isClose(s._point,n)?(o.setHandleIn(s._handleIn),this._add(i.slice(0,i.length-1),0)):this._add(i.slice())}t._closed&&this._add([i[0]]),t.remove()}var h=this.getFirstSegment(),u=this.getLastSegment();return h!==u&&h._point.isClose(u._point,n)&&(h.setHandleIn(u._handleIn),u.remove(),this.setClosed(!0)),this},reduce:function(t){for(var e=this.getCurves(),n=t&&t.simplify,i=n?2e-7:0,r=e.length-1;r>=0;r--){var s=e[r];!s.hasHandles()&&(s.getLength()<i||n&&s.isCollinear(s.getNext()))&&s.remove()}return this},reverse:function(){this._segments.reverse();for(var t=0,n=this._segments.length;t<n;t++){var i=this._segments[t],r=i._handleIn;i._handleIn=i._handleOut,i._handleOut=r,i._index=t}this._curves=null,this._clockwise!==e&&(this._clockwise=!this._clockwise),this._changed(9)},flatten:function(t){for(var e=new N(this,t||.25,256,(!0)),n=e.parts,i=n.length,r=[],s=0;s<i;s++)r.push(new M(n[s].curve.slice(0,2)));!this._closed&&i>0&&r.push(new M(n[i-1].curve.slice(6))),this.setSegments(r)},simplify:function(t){var e=new B(this).fit(t||2.5);return e&&this.setSegments(e),!!e},smooth:function(t){function n(t,e){var n=t&&t.index;if(null!=n){var r=t.path;if(r&&r!==i)throw new Error(t._class+" "+n+" of "+r+" is not part of "+i);e&&t instanceof T&&n++}else n="number"==typeof t?t:e;return Math.min(n<0&&h?n%o:n<0?n+o:n,o-1)}var i=this,r=t||{},s=r.type||"asymmetric",a=this._segments,o=a.length,h=this._closed,u=h&&r.from===e&&r.to===e,l=n(r.from,0),c=n(r.to,o-1);if(l>c)if(h)l-=o;else{var f=l;l=c,c=f}if(/^(?:asymmetric|continuous)$/.test(s)){var d="asymmetric"===s,_=Math.min,g=c-l+1,v=g-1,p=u?_(g,4):1,m=p,y=p,w=[];if(h||(m=_(1,l),y=_(1,o-c-1)),v+=m+y,v<=1)return;for(var x=0,b=l-m;x<=v;x++,b++)w[x]=a[(b<0?b+o:b)%o]._point;for(var C=w[0]._x+2*w[1]._x,S=w[0]._y+2*w[1]._y,k=2,I=v-1,P=[C],M=[S],A=[k],z=[],O=[],x=1;x<v;x++){var E=x<I,L=E?1:d?1:2,N=E?4:d?2:7,B=E?4:d?3:8,j=E?2:d?0:1,F=L/k;k=A[x]=N-F,C=P[x]=B*w[x]._x+j*w[x+1]._x-F*C,S=M[x]=B*w[x]._y+j*w[x+1]._y-F*S}z[I]=P[I]/A[I],O[I]=M[I]/A[I];for(var x=v-2;x>=0;x--)z[x]=(P[x]-z[x+1])/A[x],O[x]=(M[x]-O[x+1])/A[x];z[v]=(3*w[v]._x-z[I])/2,O[v]=(3*w[v]._y-O[I])/2;for(var x=m,D=v-y,b=l;x<=D;x++,b++){var R=a[b<0?b+o:b],q=R._point,V=z[x]-q._x,H=O[x]-q._y;(u||x<D)&&R.setHandleOut(V,H),(u||x>m)&&R.setHandleIn(-V,-H)}}else for(var x=l;x<=c;x++)a[x<0?x+o:x].smooth(r,!u&&x===l,!u&&x===c)},toShape:function(t){function n(t,e){var n=c[t],i=n.getNext(),r=c[e],s=r.getNext();return n._handleOut.isZero()&&i._handleIn.isZero()&&r._handleOut.isZero()&&s._handleIn.isZero()&&i._point.subtract(n._point).isCollinear(s._point.subtract(r._point))}function i(t){var e=c[t],n=e.getPrevious(),i=e.getNext();return n._handleOut.isZero()&&e._handleIn.isZero()&&e._handleOut.isZero()&&i._handleIn.isZero()&&e._point.subtract(n._point).isOrthogonal(i._point.subtract(e._point))}function r(t){var e=c[t],n=e.getNext(),i=e._handleOut,r=n._handleIn,s=.5522847498307936;if(i.isOrthogonal(r)){var a=e._point,o=n._point,h=new m(a,i,(!0)).intersect(new m(o,r,(!0)),!0);return h&&u.isZero(i.getLength()/h.subtract(a).getLength()-s)&&u.isZero(r.getLength()/h.subtract(o).getLength()-s)}return!1}function s(t,e){return c[t]._point.getDistance(c[e]._point)}if(!this._closed)return null;var a,o,h,l,c=this._segments;if(!this.hasHandles()&&4===c.length&&n(0,2)&&n(1,3)&&i(1)?(a=C.Rectangle,o=new d(s(0,3),s(0,1)),l=c[1]._point.add(c[2]._point).divide(2)):8===c.length&&r(0)&&r(2)&&r(4)&&r(6)&&n(1,5)&&n(3,7)?(a=C.Rectangle,o=new d(s(1,6),s(0,3)),h=o.subtract(new d(s(0,7),s(1,2))).divide(2),l=c[3]._point.add(c[4]._point).divide(2)):4===c.length&&r(0)&&r(1)&&r(2)&&r(3)&&(u.isZero(s(0,2)-s(1,3))?(a=C.Circle,h=s(0,2)/2):(a=C.Ellipse,h=new d(s(2,0)/2,s(3,1)/2)),l=c[1]._point),a){var f=this.getPosition(!0),_=new a({center:f,size:o,radius:h,insert:!1});return _.copyAttributes(this,!0),_._matrix.prepend(this._matrix),_.rotate(l.subtract(f).getAngle()+90),(t===e||t)&&_.insertAbove(this),_}return null},toPath:"#clone",_hitTestSelf:function(t,e,n,i){function r(e,n){return t.subtract(e).divide(n).length<=1}function s(t,n,i){if(!e.selected||n.isSelected()){var s=t._point;if(n!==s&&(n=n.add(s)),r(n,x))return new P(i,g,{segment:t,point:n})}}function a(t,n){return(n||e.segments)&&s(t,t._point,"segment")||!n&&e.handles&&(s(t,t._handleIn,"handle-in")||s(t,t._handleOut,"handle-out"))}function o(t){f.add(t)}function h(e){if(("round"!==u||"round"!==l)&&(f=new E({internal:!0,closed:!0}),y||e._index>0&&e._index<m-1?"round"!==u&&(e._handleIn.isZero()||e._handleOut.isZero())&&E._addBevelJoin(e,u,k,c,null,i,o,!0):"round"!==l&&E._addSquareCap(e,l,k,null,i,o,!0),!f.isEmpty())){var n;return f.contains(t)||(n=f.getNearestLocation(t))&&r(n.getPoint(),w)}return r(e._point,x)}var u,l,c,f,d,_,g=this,v=this.getStyle(),p=this._segments,m=p.length,y=this._closed,w=e._tolerancePadding,x=w,b=e.stroke&&v.hasStroke(),C=e.fill&&v.hasFill(),S=e.curves,k=b?v.getStrokeWidth()/2:C&&e.tolerance>0||S?0:null;if(null!==k&&(k>0?(u=v.getStrokeJoin(),l=v.getStrokeCap(),c=k*v.getMiterLimit(),x=x.add(E._getStrokePadding(k,i))):u=l="round"),!e.ends||e.segments||y){if(e.segments||e.handles)for(var I=0;I<m;I++)if(_=a(p[I]))return _}else if(_=a(p[0],!0)||a(p[m-1],!0))return _;if(null!==k){if(d=this.getNearestLocation(t)){var M=d.getTime();0===M||1===M&&m>1?h(d.getSegment())||(d=null):r(d.getPoint(),x)||(d=null)}if(!d&&"miter"===u&&m>1)for(var I=0;I<m;I++){var A=p[I];if(t.getDistance(A._point)<=c&&h(A)){d=A.getLocation();break}}}return!d&&C&&this._contains(t)||d&&!b&&!S?new P("fill",this):d?new P(b?"stroke":"curve",this,{location:d,point:d.getPoint()}):null}},r.each(T._evaluateMethods,function(t){this[t+"At"]=function(e){var n=this.getLocationAt(e);return n&&n[t]()}},{beans:!1,getLocationOf:function(){for(var t=c.read(arguments),e=this.getCurves(),n=0,i=e.length;n<i;n++){var r=e[n].getLocationOf(t);if(r)return r}return null},getOffsetOf:function(){var t=this.getLocationOf.apply(this,arguments);return t?t.getOffset():null},getLocationAt:function(t){for(var e=this.getCurves(),n=0,i=0,r=e.length;i<r;i++){var s=n,a=e[i];if(n+=a.getLength(),n>t)return a.getLocationAt(t-s)}return e.length>0&&t<=this.getLength()?new z(e[e.length-1],1):null}}),new function(){function t(t,e,n,i){function r(e){var n=h[e],i=h[e+1];s==n&&a==i||(t.beginPath(),t.moveTo(s,a),t.lineTo(n,i),t.stroke(),t.beginPath(),t.arc(n,i,o,0,2*Math.PI,!0),t.fill())}for(var s,a,o=i/2,h=new Array(6),u=0,l=e.length;u<l;u++){var c=e[u],f=c._selection;if(c._transformCoordinates(n,h),s=h[0],a=h[1],2&f&&r(2),4&f&&r(4),t.fillRect(s-o,a-o,i,i),!(1&f)){var d=t.fillStyle;t.fillStyle="#ffffff",t.fillRect(s-o+1,a-o+1,i-2,i-2),t.fillStyle=d}}}function e(t,e,n){function i(e){if(n)e._transformCoordinates(n,_),r=_[0],s=_[1];else{var i=e._point;r=i._x,s=i._y}if(g)t.moveTo(r,s),g=!1;else{if(n)h=_[2],u=_[3];else{var f=e._handleIn;h=r+f._x,u=s+f._y}h===r&&u===s&&l===a&&c===o?t.lineTo(r,s):t.bezierCurveTo(l,c,h,u,r,s)}if(a=r,o=s,n)l=_[4],c=_[5];else{var f=e._handleOut;l=a+f._x,c=o+f._y}}for(var r,s,a,o,h,u,l,c,f=e._segments,d=f.length,_=new Array(6),g=!0,v=0;v<d;v++)i(f[v]);e._closed&&d>0&&i(f[0])}return{_draw:function(t,n,i,r){function s(t){return c[(t%f+f)%f]}var a=n.dontStart,o=n.dontFinish||n.clip,h=this.getStyle(),u=h.hasFill(),l=h.hasStroke(),c=h.getDashArray(),f=!paper.support.nativeDash&&l&&c&&c.length;if(a||t.beginPath(),(u||l&&!f||o)&&(e(t,this,r),this._closed&&t.closePath()),!o&&(u||l)&&(this._setStyles(t,n,i),u&&(t.fill(h.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),l)){if(f){a||t.beginPath();var d,_=new N(this,.25,32,(!1),r),g=_.length,v=-h.getDashOffset(),p=0;for(v%=g;v>0;)v-=s(p--)+s(p--);for(;v<g;)d=v+s(p++),(v>0||d>0)&&_.drawPart(t,Math.max(v,0),Math.max(d,0)),v=d+s(p++)}t.stroke()}},_drawSelected:function(n,i){n.beginPath(),e(n,this,i),n.stroke(),t(n,this._segments,i,paper.settings.handleSize)}}},new function(){function t(t){var e=t._segments;if(0===e.length)throw new Error("Use a moveTo() command first");return e[e.length-1]}return{moveTo:function(){var t=this._segments;1===t.length&&this.removeSegment(0),t.length||this._add([new M(c.read(arguments))])},moveBy:function(){throw new Error("moveBy() is unsupported on Path items.")},lineTo:function(){this._add([new M(c.read(arguments))])},cubicCurveTo:function(){var e=c.read(arguments),n=c.read(arguments),i=c.read(arguments),r=t(this);r.setHandleOut(e.subtract(r._point)),this._add([new M(i,n.subtract(i))])},quadraticCurveTo:function(){var e=c.read(arguments),n=c.read(arguments),i=t(this)._point;this.cubicCurveTo(e.add(i.subtract(e).multiply(1/3)),e.add(n.subtract(e).multiply(1/3)),n)},curveTo:function(){var e=c.read(arguments),n=c.read(arguments),i=r.pick(r.read(arguments),.5),s=1-i,a=t(this)._point,o=e.subtract(a.multiply(s*s)).subtract(n.multiply(i*i)).divide(2*i*s);if(o.isNaN())throw new Error("Cannot put a curve through points with parameter = "+i);this.quadraticCurveTo(o,n)},arcTo:function(){var e,n,i,s,a,o=t(this),h=o._point,l=c.read(arguments),f=r.peek(arguments),_=r.pick(f,!0);if("boolean"==typeof _)var g=h.add(l).divide(2),e=g.add(g.subtract(h).rotate(_?-90:90));else if(r.remain(arguments)<=2)e=l,l=c.read(arguments);else{var v=d.read(arguments),y=u.isZero;if(y(v.width)||y(v.height))return this.lineTo(l);var w=r.read(arguments),_=!!r.read(arguments),x=!!r.read(arguments),g=h.add(l).divide(2),b=h.subtract(g).rotate(-w),C=b.x,S=b.y,k=Math.abs,I=k(v.width),P=k(v.height),A=I*I,T=P*P,z=C*C,O=S*S,E=Math.sqrt(z/A+O/T);if(E>1&&(I*=E,P*=E,A=I*I,T=P*P),E=(A*T-A*O-T*z)/(A*O+T*z),k(E)<1e-12&&(E=0),E<0)throw new Error("Cannot create an arc with the given arguments");n=new c(I*S/P,-P*C/I).multiply((x===_?-1:1)*Math.sqrt(E)).rotate(w).add(g),a=(new p).translate(n).rotate(w).scale(I,P),s=a._inverseTransform(h),i=s.getDirectedAngle(a._inverseTransform(l)),!_&&i>0?i-=360:_&&i<0&&(i+=360)}if(e){var L=new m(h.add(e).divide(2),e.subtract(h).rotate(90),(!0)),N=new m(e.add(l).divide(2),l.subtract(e).rotate(90),(!0)),B=new m(h,l),j=B.getSide(e);if(n=L.intersect(N,!0),!n){if(!j)return this.lineTo(l);throw new Error("Cannot create an arc with the given arguments")}s=h.subtract(n),i=s.getDirectedAngle(l.subtract(n));var F=B.getSide(n);0===F?i=j*Math.abs(i):j===F&&(i+=i<0?360:-360)}for(var D=Math.abs(i),R=D>=360?4:Math.ceil(D/90),q=i/R,V=q*Math.PI/360,H=4/3*Math.sin(V)/(1+Math.cos(V)),U=[],Z=0;Z<=R;Z++){var b=l,W=null;if(Z<R&&(W=s.rotate(90).multiply(H),a?(b=a._transformPoint(s),W=a._transformPoint(s.add(W)).subtract(b)):b=n.add(s)),0===Z)o.setHandleOut(W);else{var G=s.rotate(-90).multiply(H);a&&(G=a._transformPoint(s.add(G)).subtract(b)),U.push(new M(b,G,W))}s=s.rotate(q)}this._add(U)},lineBy:function(){var e=c.read(arguments),n=t(this)._point;this.lineTo(n.add(e))},curveBy:function(){var e=c.read(arguments),n=c.read(arguments),i=r.read(arguments),s=t(this)._point;this.curveTo(s.add(e),s.add(n),i)},cubicCurveBy:function(){var e=c.read(arguments),n=c.read(arguments),i=c.read(arguments),r=t(this)._point;this.cubicCurveTo(r.add(e),r.add(n),r.add(i))},quadraticCurveBy:function(){var e=c.read(arguments),n=c.read(arguments),i=t(this)._point;this.quadraticCurveTo(i.add(e),i.add(n))},arcBy:function(){var e=t(this)._point,n=e.add(c.read(arguments)),i=r.pick(r.peek(arguments),!0);"boolean"==typeof i?this.arcTo(n,i):this.arcTo(n,e.add(c.read(arguments)))},closePath:function(t){this.setClosed(!0),this.join(this,t)}}},{_getBounds:function(t,e){var n=e.handle?"getHandleBounds":e.stroke?"getStrokeBounds":"getBounds";return E[n](this._segments,this._closed,this,t,e)},statics:{getBounds:function(t,e,n,i,r,s){function a(t){t._transformCoordinates(i,h);for(var e=0;e<2;e++)T._addBounds(u[e],u[e+4],h[e+2],h[e],e,s?s[e]:0,l,c,f);var n=u;u=h,h=n}var o=t[0];if(!o)return new g;for(var h=new Array(6),u=o._transformCoordinates(i,new Array(6)),l=u.slice(0,2),c=l.slice(),f=new Array(2),d=1,_=t.length;d<_;d++)a(t[d]);return e&&a(o),new g(l[0],l[1],c[0]-l[0],c[1]-l[1])},getStrokeBounds:function(t,e,n,i,r){function s(t){v=v.include(t)}function a(t){v=v.unite(x.setCenter(t._point.transform(i)))}function o(t,e){var n=t._handleIn,r=t._handleOut;"round"===e||!n.isZero()&&!r.isZero()&&n.isCollinear(r)?a(t):E._addBevelJoin(t,e,p,w,i,f,s)}function h(t,e){"round"===e?a(t):E._addSquareCap(t,e,p,i,f,s)}var u=n.getStyle(),l=u.hasStroke(),c=u.getStrokeWidth(),f=l&&n._getStrokeMatrix(i,r),_=l&&E._getStrokePadding(c,f),v=E.getBounds(t,e,n,i,r,_);if(!l)return v;for(var p=c/2,m=u.getStrokeJoin(),y=u.getStrokeCap(),w=p*u.getMiterLimit(),x=new g(new d(_)),b=t.length-(e?0:1),C=1;C<b;C++)o(t[C],m);return e?o(t[0],m):b>0&&(h(t[0],y),h(t[t.length-1],y)),v},_getStrokePadding:function(t,e){
-if(!e)return[t,t];var n=new c(t,0).transform(e),i=new c(0,t).transform(e),r=n.getAngleInRadians(),s=n.getLength(),a=i.getLength(),o=Math.sin(r),h=Math.cos(r),u=Math.tan(r),l=Math.atan2(a*u,s),f=Math.atan2(a,u*s);return[Math.abs(s*Math.cos(l)*h+a*Math.sin(l)*o),Math.abs(a*Math.sin(f)*h+s*Math.cos(f)*o)]},_addBevelJoin:function(t,e,n,i,r,s,a,o){var h=t.getCurve(),u=h.getPrevious(),l=h.getPointAtTime(0),f=u.getNormalAtTime(1),d=h.getNormalAtTime(0),_=f.getDirectedAngle(d)<0?-n:n;if(f.setLength(_),d.setLength(_),r&&r._transformPoint(l,l),s&&(s._transformPoint(f,f),s._transformPoint(d,d)),o&&(a(l),a(l.add(f))),"miter"===e){var g=new m(l.add(f),new c((-f.y),f.x),(!0)).intersect(new m(l.add(d),new c((-d.y),d.x),(!0)),!0);if(g&&l.getDistance(g)<=i&&(a(g),!o))return}o||a(l.add(f)),a(l.add(d))},_addSquareCap:function(t,e,n,i,r,s,a){var o=t._point,h=t.getLocation(),u=h.getNormal().multiply(n);i&&i._transformPoint(o,o),r&&r._transformPoint(u,u),a&&(s(o.subtract(u)),s(o.add(u))),"square"===e&&(o=o.add(u.rotate(0===h.getTime()?-90:90))),s(o.add(u)),s(o.subtract(u))},getHandleBounds:function(t,e,n,i,r){var s,a,o=n.getStyle(),h=r.stroke&&o.hasStroke();if(h){var u=n._getStrokeMatrix(i,r),l=o.getStrokeWidth()/2,c=l;"miter"===o.getStrokeJoin()&&(c=l*o.getMiterLimit()),"square"===o.getStrokeCap()&&(c=Math.max(c,l*Math.sqrt(2))),s=E._getStrokePadding(l,u),a=E._getStrokePadding(c,u)}for(var f=new Array(6),d=1/0,_=-d,v=d,p=_,m=0,y=t.length;m<y;m++){var w=t[m];w._transformCoordinates(i,f);for(var x=0;x<6;x+=2){var b=0===x?a:s,C=b?b[0]:0,S=b?b[1]:0,k=f[x],I=f[x+1],P=k-C,M=k+C,A=I-S,T=I+S;P<d&&(d=P),M>_&&(_=M),A<v&&(v=A),T>p&&(p=T)}}return new g(d,v,_-d,p-v)}}});E.inject({statics:new function(){function t(t,e,n){var i=r.getNamed(n),s=new E(i&&i.insert===!1&&w.NO_INSERT);return s._add(t),s._closed=e,s.set(i)}function e(e,n,r){for(var s=new Array(4),a=0;a<4;a++){var o=i[a];s[a]=new M(o._point.multiply(n).add(e),o._handleIn.multiply(n),o._handleOut.multiply(n))}return t(s,!0,r)}var n=.5522847498307936,i=[new M([-1,0],[0,n],[0,-n]),new M([0,-1],[-n,0],[n,0]),new M([1,0],[0,-n],[0,n]),new M([0,1],[n,0],[-n,0])];return{Line:function(){return t([new M(c.readNamed(arguments,"from")),new M(c.readNamed(arguments,"to"))],!1,arguments)},Circle:function(){var t=c.readNamed(arguments,"center"),n=r.readNamed(arguments,"radius");return e(t,new d(n),arguments)},Rectangle:function(){var e,i=g.readNamed(arguments,"rectangle"),r=d.readNamed(arguments,"radius",0,{readNull:!0}),s=i.getBottomLeft(!0),a=i.getTopLeft(!0),o=i.getTopRight(!0),h=i.getBottomRight(!0);if(!r||r.isZero())e=[new M(s),new M(a),new M(o),new M(h)];else{r=d.min(r,i.getSize(!0).divide(2));var u=r.width,l=r.height,c=u*n,f=l*n;e=[new M(s.add(u,0),null,[-c,0]),new M(s.subtract(0,l),[0,f]),new M(a.add(0,l),null,[0,-f]),new M(a.add(u,0),[-c,0],null),new M(o.subtract(u,0),null,[c,0]),new M(o.add(0,l),[0,-f],null),new M(h.subtract(0,l),null,[0,f]),new M(h.subtract(u,0),[c,0])]}return t(e,!0,arguments)},RoundRectangle:"#Rectangle",Ellipse:function(){var t=C._readEllipse(arguments);return e(t.center,t.radius,arguments)},Oval:"#Ellipse",Arc:function(){var t=c.readNamed(arguments,"from"),e=c.readNamed(arguments,"through"),n=c.readNamed(arguments,"to"),i=r.getNamed(arguments),s=new E(i&&i.insert===!1&&w.NO_INSERT);return s.moveTo(t),s.arcTo(e,n),s.set(i)},RegularPolygon:function(){for(var e=c.readNamed(arguments,"center"),n=r.readNamed(arguments,"sides"),i=r.readNamed(arguments,"radius"),s=360/n,a=n%3===0,o=new c(0,a?-i:i),h=a?-1:.5,u=new Array(n),l=0;l<n;l++)u[l]=new M(e.add(o.rotate((l+h)*s)));return t(u,!0,arguments)},Star:function(){for(var e=c.readNamed(arguments,"center"),n=2*r.readNamed(arguments,"points"),i=r.readNamed(arguments,"radius1"),s=r.readNamed(arguments,"radius2"),a=360/n,o=new c(0,(-1)),h=new Array(n),u=0;u<n;u++)h[u]=new M(e.add(o.rotate(a*u).multiply(u%2?s:i)));return t(h,!0,arguments)}}}});var L=O.extend({_class:"CompoundPath",_serializeFields:{children:[]},initialize:function(t){this._children=[],this._namedChildren={},this._initialize(t)||("string"==typeof t?this.setPathData(t):this.addChildren(Array.isArray(t)?t:arguments))},insertChildren:function mt(t,n,i){for(var r=n.length-1;r>=0;r--){var s=n[r];s instanceof L&&(n=n.slice(),n.splice.apply(n,[r,1].concat(s.removeChildren())),s.remove())}n=mt.base.call(this,t,n,i,E);for(var r=0,a=!i&&n&&n.length;r<a;r++){var s=n[r];s._clockwise===e&&s.setClockwise(0===s._index)}return n},reduce:function yt(t){for(var e=this._children,n=e.length-1;n>=0;n--){var i=e[n].reduce(t);i.isEmpty()&&i.remove()}if(0===e.length){var i=new E(w.NO_INSERT);return i.copyAttributes(this),i.insertAbove(this),this.remove(),i}return yt.base.call(this)},isClockwise:function(){var t=this.getFirstChild();return t&&t.isClockwise()},setClockwise:function(t){this.isClockwise()^!!t&&this.reverse()},getFirstSegment:function(){var t=this.getFirstChild();return t&&t.getFirstSegment()},getLastSegment:function(){var t=this.getLastChild();return t&&t.getLastSegment()},getCurves:function(){for(var t=this._children,e=[],n=0,i=t.length;n<i;n++)e.push.apply(e,t[n].getCurves());return e},getFirstCurve:function(){var t=this.getFirstChild();return t&&t.getFirstCurve()},getLastCurve:function(){var t=this.getLastChild();return t&&t.getFirstCurve()},getArea:function(){for(var t=this._children,e=0,n=0,i=t.length;n<i;n++)e+=t[n].getArea();return e}},{beans:!0,getPathData:function(t,e){for(var n=this._children,i=[],r=0,s=n.length;r<s;r++){var a=n[r],o=a._matrix;i.push(a.getPathData(t&&!o.isIdentity()?t.appended(o):t,e))}return i.join(" ")}},{_hitTestChildren:function wt(t,e,n){return wt.base.call(this,t,e["class"]===E||"path"===e.type?e:r.set({},e,{fill:!1}),n)},_draw:function(t,e,n,i){var r=this._children;if(0!==r.length){e=e.extend({dontStart:!0,dontFinish:!0}),t.beginPath();for(var s=0,a=r.length;s<a;s++)r[s].draw(t,e,i);if(!e.clip){this._setStyles(t,e,n);var o=this._style;o.hasFill()&&(t.fill(o.getFillRule()),t.shadowColor="rgba(0,0,0,0)"),o.hasStroke()&&t.stroke()}}},_drawSelected:function(t,e,n){for(var i=this._children,r=0,s=i.length;r<s;r++){var a=i[r],o=a._matrix;n[a._id]||a._drawSelected(t,o.isIdentity()?e:e.appended(o))}}},new function(){function t(t,e){var n=t._children;if(e&&0===n.length)throw new Error("Use a moveTo() command first");return n[n.length-1]}return r.each(["lineTo","cubicCurveTo","quadraticCurveTo","curveTo","arcTo","lineBy","cubicCurveBy","quadraticCurveBy","curveBy","arcBy"],function(e){this[e]=function(){var n=t(this,!0);n[e].apply(n,arguments)}},{moveTo:function(){var e=t(this),n=e&&e.isEmpty()?e:new E(w.NO_INSERT);n!==e&&this.addChild(n),n.moveTo.apply(n,arguments)},moveBy:function(){var e=t(this,!0),n=e&&e.getLastSegment(),i=c.read(arguments);this.moveTo(n?i.add(n._point):i)},closePath:function(e){t(this,!0).closePath(e)}})},r.each(["reverse","flatten","simplify","smooth"],function(t){this[t]=function(e){for(var n,i=this._children,r=0,s=i.length;r<s;r++)n=i[r][t](e)||n;return n}},{}));O.inject(new function(){function t(t,e){var n=t.clone(!1).reduce({simplify:!0}).transform(null,!0,!0);return e?n.resolveCrossings():n}function e(t,e,n,i,r){var s=new t(w.NO_INSERT);return s.addChildren(e,!0),n&&(s=s.reduce({simplify:!0})),s.insertAbove(r&&i.isSibling(r)&&i.getIndex()<r.getIndex()?r:i),s.copyAttributes(i,!0),s}function n(n,r,s){function o(t){for(var e=0,n=t.length;e<n;e++){var i=t[e];g.push.apply(g,i._segments),v.push.apply(v,i._getMonoCurves()),i._overlapsOnly=i._validOverlapsOnly=!0}}var u=f[s];if(u[s]=!0,!n._children&&!n._closed)return i(n,r,u);var c=t(n,!0),d=r&&n!==r&&t(r,!0);d&&(u.subtract||u.exclude)^(d.isClockwise()^c.isClockwise())&&d.reverse();var _=a(z.expand(c.getCrossings(d))),g=[],v=[];o(c._children||[c]),d&&o(d._children||[d]);for(var p=0,m=_.length;p<m;p++)h(_[p]._segment,c,d,v,u);for(var p=0,m=g.length;p<m;p++){var y=g[p],w=y._intersection;if(null==y._winding&&h(y,c,d,v,u),!w||!w._overlap){var x=y._path;x._overlapsOnly=!1,u[y._winding]&&(x._validOverlapsOnly=!1)}}return e(L,l(g,u),!0,n,r)}function i(n,i,r){function s(t){if(o.contains(t.getPointAt(t.getLength()/2))^u)return l.unshift(t),!0}if(!i||!i._children&&!i._closed||!r.subtract&&!r.intersect)return null;for(var a=t(n,!1),o=t(i,!1),h=a.getCrossings(o),u=r.subtract,l=[],c=h.length-1;c>=0;c--){var f=h[c].split();f&&(s(f)&&f.getFirstSegment().setHandleIn(0,0),a.getLastSegment().setHandleOut(0,0))}return s(a),e(x,l,!1,n,i)}function s(t,e){for(var n=t;n;){if(n===e)return;n=n._previous}for(;t._next&&t._next!==e;)t=t._next;if(!t._next){for(;e._previous;)e=e._previous;t._next=e,e._previous=t}}function a(t,e){for(var n,i,r=e&&[],a=4e-7,o=1-a,h=!1,u=[],l=t.length-1;l>=0;l--){var c=t[l];if(e){if(!e(c))continue;r.unshift(c)}var f,d=c._curve,_=c._time,g=_;if(d!==n?h=!d.hasHandles():i>=a&&i<=o&&(_/=i),_<a)f=d._segment1;else if(_>o)f=d._segment2;else{var v=d.divideAtTime(_,!0);h&&u.push(d,v),f=v._segment1}c._setSegment(f);var p=f._intersection,m=c._intersection;if(p){s(p,m);for(var y=p;y;)s(y._intersection,p),y=y._next}else f._intersection=m;n=d,i=g}for(var l=0,w=u.length;l<w;l++)u[l].clearHandles();return r||t}function o(t,e,n){var i=2e-7,r=t.x,s=t.y,a=0,h=0,u=e.length,l=[],f=Math.abs;if(n){for(var d=-(1/0),_=1/0,g=s-i,v=s+i,p=0;p<u;p++)for(var m=e[p].values,y=T.solveCubic(m,0,r,l,0,1),w=y-1;w>=0;w--){var x=T.getPoint(m,l[w]).y;x<g&&x>d?d=x:x>v&&x<_&&(_=x)}d=(d+s)/2,_=(_+s)/2,d>-(1/0)&&(a=o(new c(r,d),e).winding),_<1/0&&(h=o(new c(r,_),e).winding)}else{for(var b,C,S=r-i,k=r+i,I=0,P=0,M=!1,p=0;p<u;p++){var A=e[p],z=A.winding,m=A.values,O=m[1],E=m[7];if(A.last&&(b=A.last.winding,C=A.last.values[6],M=!1),s>=O&&s<=E||s>=E&&s<=O)if(z){var L=s===O?m[0]:s===E?m[6]:1===T.solveCubic(m,1,s,l,0,1)?T.getPoint(m,l[0]).x:null;null!=L&&(L>=S&&L<=k?M=!0:s===O&&z===b||s===O&&(r-L)*(r-C)<0||(L<S?a+=z:L>k&&(h+=z))),b=z,C=m[6]}else(r-m[0])*(r-m[6])<=0&&(M=!0);M&&(p>=u-1||e[p+1].last)&&(I+=1,P-=1)}0===a&&0===h&&(a=I,h=P)}return{winding:Math.max(f(a),f(h)),contour:!a^!h}}function h(t,e,n,i,r){var s,a=[],h=t,u=0;do{var l=t.getCurve(),c=l.getLength();a.push({segment:t,curve:l,length:c}),u+=c,t=t.getNext()}while(t&&!t._intersection&&t!==h);for(var c=u/2,f=0,d=a.length;f<d;f++){var _=a[f],g=_.length;if(c<=g){var l=_.curve,v=l._path,p=v._parent,m=l.getTimeAt(c),y=l.getPointAtTime(m),w=Math.abs(l.getTangentAtTime(m).y)<1e-7;p instanceof L&&(v=p),s=r.subtract&&n&&(v===e&&n._getWinding(y,w)||v===n&&!e._getWinding(y,w))?{winding:0}:o(y,i,w);break}c-=g}for(var f=a.length-1;f>=0;f--){var x=a[f].segment;x._winding=s.winding,x._contour=s.contour}}function l(t,e){function n(t,n){return!(!t||t._visited||!(!e||e[t._winding]||!n&&e.unite&&t._contour))}function i(t){return t===a||t===o}function s(t,r){if(!t._next)return t;for(;t;){var s=t._segment,a=s.getNext(),o=a&&a._intersection;if(s!==r&&(i(s)||i(a)||!s._visited&&!a._visited&&(!e||n(s)&&(n(a)||o&&n(o._segment)))))return t;t=t._next}return null}for(var a,o,h=[],l=0,c=t.length;l<c;l++){var f,d=null,_=!1,g=t[l],v=g._intersection;if(!g._visited&&g._path._overlapsOnly){var p=g._path,m=v._segment._path,y=p._segments,x=m._segments;if(r.equals(y,x)){(e.unite||e.intersect)&&p.getArea()&&h.push(p.clone(!1));for(var b=0,C=y.length;b<C;b++)y[b]._visited=x[b]._visited=!0}}if(n(g,!0)&&(g._path._validOverlapsOnly||!v||!v._overlap)){for(a=o=null;;){v=v&&s(v,g)||v;var S=v&&v._segment;if(i(g)?_=!0:S&&(i(S)?(_=!0,g=S):n(S,n(g,!0))&&(e&&(e.intersect||e.subtract)&&(g._visited=!0),g=S)),_||g._visited){g._visited=!0;break}if(g._path._validOverlapsOnly&&!n(g))break;d||(d=new E(w.NO_INSERT),a=g,o=S);var k=g.getNext();d.add(new M(g._point,f,k&&g._handleOut)),g._visited=!0,g=k||g._path.getFirstSegment(),f=k&&k._handleIn,v=g._intersection}if(_)d.firstSegment.setHandleIn(f),d.setClosed(!0);else if(d){var I=d.getArea(!0);Math.abs(I)>=2e-7&&console.error("Boolean operation resulted in open path","segments =",d._segments.length,"length =",d.getLength(),"area=",I),d=null}d&&(d._segments.length>8||!u.isZero(d.getArea()))&&(h.push(d),d=null)}}return h}var f={unite:{1:!0},intersect:{2:!0},subtract:{1:!0},exclude:{1:!0}};return{_getWinding:function(t,e){return o(t,this._getMonoCurves(),e).winding},unite:function(t){return n(this,t,"unite")},intersect:function(t){return n(this,t,"intersect")},subtract:function(t){return n(this,t,"subtract")},exclude:function(t){return n(this,t,"exclude")},divide:function(t){return e(x,[this.subtract(t),this.intersect(t)],!0,this,t)},resolveCrossings:function(){function t(t){var e=t&&t._intersection;return e&&e._overlap}var e=this._children,n=e||[this],i=!1,s=!1,o=this.getIntersections(null,function(t){return t._overlap&&(i=!0)||t.isCrossing()&&(s=!0)});if(o=z.expand(o),i)for(var h=a(o,function(t){return t._overlap}),u=h.length-1;u>=0;u--){var c=h[u]._segment,f=c.getPrevious(),d=c.getNext();if(c._path&&t(f)&&t(d)){c.remove(),f._handleOut.set(0,0),d._handleIn.set(0,0);var _=f.getCurve();_.isStraight()&&0===_.getLength()&&f.remove()}}s&&(a(o,i&&function(t){var e=t.getCurve(),n=t._intersection._curve,i=t._segment;return!!(e&&n&&e._path&&n._path)||void(i&&(i._intersection=null))}),n=l(r.each(n,function(t){this.push.apply(this,t._segments)},[])));var g,v=n.length;if(v>1){n=n.slice().sort(function(t,e){return e.getBounds().getArea()-t.getBounds().getArea()});for(var p=n[0],m=[p],y={},x="nonzero"===this.getFillRule(),b=x&&r.each(n,function(t){this.push(t.isClockwise()?1:-1)},[]),u=1;u<v;u++){for(var C=n[u],S=C.getInteriorPoint(),k=!1,I=null,P=!1,M=u-1;M>=0&&!I;M--)if(n[M].contains(S)){if(x&&!k&&(b[u]+=b[M],b[u]&&b[M])){P=y[u]=!0;break}k=!0,I=!y[M]&&n[M]}P||(C.setClockwise(I?!I.isClockwise():p.isClockwise()),m.push(C))}n=m,v=m.length}return v>1&&e?(n!==e&&this.setChildren(n,!0),g=this):1!==v||e||(n[0]!==this&&this.setSegments(n[0].removeSegments()),g=this),g||(g=new L(w.NO_INSERT),g.addChildren(n,!0),g=g.reduce(),g.copyAttributes(this),this.replaceWith(g)),g}}}),E.inject({_getMonoCurves:function(){function t(t){var e=t[1],r=t[7],s=Math.abs((e-r)/(t[0]-t[6]))<2e-7?0:e>r?-1:1,a={values:t,winding:s};i.push(a),s&&(n=a)}function e(e){if(0!==T.getLength(e)){var n=e[1],i=e[3],r=e[5],s=e[7];if(T.isStraight(e)||n>=i==i>=r&&i>=r==r>=s)t(e);else{var a=3*(i-r)-n+s,o=2*(n+r)-4*i,h=i-n,l=4e-7,c=1-l,f=[],d=u.solveQuadratic(a,o,h,f,l,c);if(d<1)t(e);else{f.sort();var _=f[0],g=T.subdivide(e,_);t(g[0]),d>1&&(_=(f[1]-_)/(1-_),g=T.subdivide(g[1],_),t(g[0])),t(g[1])}}}}var n,i=this._monoCurves;if(!i){i=this._monoCurves=[];for(var r=this.getCurves(),s=this._segments,a=0,o=r.length;a<o;a++)e(r[a].getValues());if(!this._closed&&s.length>1){var h=s[s.length-1]._point,l=s[0]._point,c=h._x,f=h._y,d=l._x,_=l._y;e([c,f,c,f,d,_,d,_])}i.length>0&&(i[0].last=n)}return i},getInteriorPoint:function(){var t=this.getBounds(),e=t.getCenter(!0);if(!this.contains(e)){for(var n=this._getMonoCurves(),i=[],r=e.y,s=[],a=0,o=n.length;a<o;a++){var h=n[a].values;if(1===n[a].winding&&r>h[1]&&r<=h[7]||r>=h[7]&&r<h[1])for(var u=T.solveCubic(h,1,r,i,0,1),l=u-1;l>=0;l--)s.push(T.getPoint(h,i[l]).x)}s.sort(function(t,e){return t-e}),e.x=(s[0]+s[1])/2}return e}}),L.inject({_getMonoCurves:function(){for(var t=this._children,e=[],n=0,i=t.length;n<i;n++)e.push.apply(e,t[n]._getMonoCurves());return e}});var N=r.extend({_class:"PathIterator",initialize:function(t,e,n,i,r){function s(t,e){var n=T.getValues(t,e,r);h.push(n),a(n,t._index,0,1)}function a(t,n,r,s){if(!(s-r>c)||i&&T.isStraight(t)||T.isFlatEnough(t,e||.25)){var o=t[6]-t[0],h=t[7]-t[1],f=Math.sqrt(o*o+h*h);f>0&&(l+=f,u.push({offset:l,curve:t,index:n,time:s}))}else{var d=T.subdivide(t,.5),_=(r+s)/2;a(d[0],n,r,_),a(d[1],n,_,s)}}for(var o,h=[],u=[],l=0,c=1/(n||32),f=t._segments,d=f[0],_=1,g=f.length;_<g;_++)o=f[_],s(d,o),d=o;t._closed&&s(o,f[0]),this.curves=h,this.parts=u,this.length=l,this.index=0},_get:function(t){for(var e,n=this.index;e=n,!(0===n||this.parts[--n].offset<t););for(var i=this.parts.length;e<i;e++){var r=this.parts[e];if(r.offset>=t){this.index=e;var s=this.parts[e-1],a=s&&s.index===r.index?s.time:0,o=s?s.offset:0;return{index:r.index,time:a+(r.time-a)*(t-o)/(r.offset-o)}}}var r=this.parts[this.parts.length-1];return{index:r.index,time:1}},drawPart:function(t,e,n){for(var i=this._get(e),r=this._get(n),s=i.index,a=r.index;s<=a;s++){var o=T.getPart(this.curves[s],s===i.index?i.time:0,s===r.index?r.time:1);s===i.index&&t.moveTo(o[0],o[1]),t.bezierCurveTo.apply(t,o.slice(2))}}},r.each(T._evaluateMethods,function(t){this[t+"At"]=function(e){var n=this._get(e);return T[t](this.curves[n.index],n.time)}},{})),B=r.extend({initialize:function(t){for(var e,n=this.points=[],i=t._segments,r=t._closed,s=0,a=i.length;s<a;s++){var o=i[s].point;e&&e.equals(o)||n.push(e=o.clone())}r&&(n.unshift(n[n.length-1]),n.push(n[1])),this.closed=r},fit:function(t){var e=this.points,n=e.length,i=null;return n>0&&(i=[new M(e[0])],n>1&&(this.fitCubic(i,t,0,n-1,e[1].subtract(e[0]),e[n-2].subtract(e[n-1])),this.closed&&(i.shift(),i.pop()))),i},fitCubic:function(t,e,n,i,r,s){var a=this.points;if(i-n===1){var o=a[n],h=a[i],u=o.getDistance(h)/3;return void this.addCurve(t,[o,o.add(r.normalize(u)),h.add(s.normalize(u)),h])}for(var l,c=this.chordLengthParameterize(n,i),f=Math.max(e,e*e),d=!0,_=0;_<=4;_++){var g=this.generateBezier(n,i,c,r,s),v=this.findMaxError(n,i,g,c);if(v.error<e&&d)return void this.addCurve(t,g);if(l=v.index,v.error>=f)break;d=this.reparameterize(n,i,c,g),f=v.error}var p=a[l-1].subtract(a[l+1]);this.fitCubic(t,e,n,l,r,p),this.fitCubic(t,e,l,i,p.negate(),s)},addCurve:function(t,e){var n=t[t.length-1];n.setHandleOut(e[1].subtract(e[0])),t.push(new M(e[3],e[2].subtract(e[3])))},generateBezier:function(t,e,n,i,r){for(var s=1e-12,a=Math.abs,o=this.points,h=o[t],u=o[e],l=[[0,0],[0,0]],c=[0,0],f=0,d=e-t+1;f<d;f++){var _=n[f],g=1-_,v=3*_*g,p=g*g*g,m=v*g,y=v*_,w=_*_*_,x=i.normalize(m),b=r.normalize(y),C=o[t+f].subtract(h.multiply(p+m)).subtract(u.multiply(y+w));l[0][0]+=x.dot(x),l[0][1]+=x.dot(b),l[1][0]=l[0][1],l[1][1]+=b.dot(b),c[0]+=x.dot(C),c[1]+=b.dot(C)}var S,k,I=l[0][0]*l[1][1]-l[1][0]*l[0][1];if(a(I)>s){var P=l[0][0]*c[1]-l[1][0]*c[0],M=c[0]*l[1][1]-c[1]*l[0][1];S=M/I,k=P/I}else{var A=l[0][0]+l[0][1],T=l[1][0]+l[1][1];S=k=a(A)>s?c[0]/A:a(T)>s?c[1]/T:0}var z,O,E=u.getDistance(h),L=s*E;if(S<L||k<L)S=k=E/3;else{var N=u.subtract(h);z=i.normalize(S),O=r.normalize(k),z.dot(N)-O.dot(N)>E*E&&(S=k=E/3,z=O=null)}return[h,h.add(z||i.normalize(S)),u.add(O||r.normalize(k)),u]},reparameterize:function(t,e,n,i){for(var r=t;r<=e;r++)n[r-t]=this.findRoot(i,this.points[r],n[r-t]);for(var r=1,s=n.length;r<s;r++)if(n[r]<=n[r-1])return!1;return!0},findRoot:function(t,e,n){for(var i=[],r=[],s=0;s<=2;s++)i[s]=t[s+1].subtract(t[s]).multiply(3);for(var s=0;s<=1;s++)r[s]=i[s+1].subtract(i[s]).multiply(2);var a=this.evaluate(3,t,n),o=this.evaluate(2,i,n),h=this.evaluate(1,r,n),u=a.subtract(e),l=o.dot(o)+u.dot(h);return Math.abs(l)<1e-6?n:n-u.dot(o)/l},evaluate:function(t,e,n){for(var i=e.slice(),r=1;r<=t;r++)for(var s=0;s<=t-r;s++)i[s]=i[s].multiply(1-n).add(i[s+1].multiply(n));return i[0]},chordLengthParameterize:function(t,e){for(var n=[0],i=t+1;i<=e;i++)n[i-t]=n[i-t-1]+this.points[i].getDistance(this.points[i-1]);for(var i=1,r=e-t;i<=r;i++)n[i]/=n[r];return n},findMaxError:function(t,e,n,i){for(var r=Math.floor((e-t+1)/2),s=0,a=t+1;a<e;a++){var o=this.evaluate(3,n,i[a-t]),h=o.subtract(this.points[a]),u=h.x*h.x+h.y*h.y;u>=s&&(s=u,r=a)}return{error:s,index:r}}}),j=w.extend({_class:"TextItem",_applyMatrix:!1,_canApplyMatrix:!1,_serializeFields:{content:null},_boundsOptions:{stroke:!1,handle:!1},initialize:function(t){this._content="",this._lines=[];var n=t&&r.isPlainObject(t)&&t.x===e&&t.y===e;this._initialize(n&&t,!n&&c.read(arguments))},_equals:function(t){return this._content===t._content},copyContent:function(t){this.setContent(t._content)},getContent:function(){return this._content},setContent:function(t){this._content=""+t,this._lines=this._content.split(/\r\n|\n|\r/gm),this._changed(265)},isEmpty:function(){return!this._content},getCharacterStyle:"#getStyle",setCharacterStyle:"#setStyle",getParagraphStyle:"#getStyle",setParagraphStyle:"#setStyle"}),F=j.extend({_class:"PointText",initialize:function(){j.apply(this,arguments)},getPoint:function(){var t=this._matrix.getTranslation();return new f(t.x,t.y,this,"setPoint")},setPoint:function(){var t=c.read(arguments);this.translate(t.subtract(this._matrix.getTranslation()))},_draw:function(t,e,n){if(this._content){this._setStyles(t,e,n);var i=this._lines,r=this._style,s=r.hasFill(),a=r.hasStroke(),o=r.getLeading(),h=t.shadowColor;t.font=r.getFontStyle(),t.textAlign=r.getJustification();for(var u=0,l=i.length;u<l;u++){t.shadowColor=h;var c=i[u];s&&(t.fillText(c,0,0),t.shadowColor="rgba(0,0,0,0)"),a&&t.strokeText(c,0,0),t.translate(0,o)}}},_getBounds:function(t,e){var n=this._style,i=this._lines,r=i.length,s=n.getJustification(),a=n.getLeading(),o=this.getView().getTextWidth(n.getFontStyle(),i),h=0;"left"!==s&&(h-=o/("center"===s?2:1));var u=new g(h,r?-.75*a:0,o,r*a);return t?t._transformBounds(u,u):u}}),D=r.extend(new function(){function t(t){var i,r=t.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/);if(r){i=[0,0,0];for(var s=0;s<3;s++){var o=r[s+1];i[s]=parseInt(1==o.length?o+o:o,16)/255}}else if(r=t.match(/^rgba?\((.*)\)$/)){i=r[1].split(",");for(var s=0,h=i.length;s<h;s++){var o=+i[s];i[s]=s<3?o/255:o}}else if(n){var u=a[t];if(!u){e||(e=tt.getContext(1,1),e.globalCompositeOperation="copy"),e.fillStyle="rgba(0,0,0,0)",e.fillStyle=t,e.fillRect(0,0,1,1);var l=e.getImageData(0,0,1,1).data;u=a[t]=[l[0]/255,l[1]/255,l[2]/255]}i=u.slice()}else i=[0,0,0];return i}var e,i={gray:["gray"],rgb:["red","green","blue"],hsb:["hue","saturation","brightness"],hsl:["hue","saturation","lightness"],gradient:["gradient","origin","destination","highlight"]},s={},a={},o=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]],u={"rgb-hsb":function(t,e,n){var i=Math.max(t,e,n),r=Math.min(t,e,n),s=i-r,a=0===s?0:60*(i==t?(e-n)/s+(e<n?6:0):i==e?(n-t)/s+2:(t-e)/s+4);return[a,0===i?0:s/i,i]},"hsb-rgb":function(t,e,n){t=(t/60%6+6)%6;var i=Math.floor(t),r=t-i,i=o[i],s=[n,n*(1-e),n*(1-e*r),n*(1-e*(1-r))];return[s[i[0]],s[i[1]],s[i[2]]]},"rgb-hsl":function(t,e,n){var i=Math.max(t,e,n),r=Math.min(t,e,n),s=i-r,a=0===s,o=a?0:60*(i==t?(e-n)/s+(e<n?6:0):i==e?(n-t)/s+2:(t-e)/s+4),h=(i+r)/2,u=a?0:h<.5?s/(i+r):s/(2-i-r);return[o,u,h]},"hsl-rgb":function(t,e,n){if(t=(t/360%1+1)%1,0===e)return[n,n,n];for(var i=[t+1/3,t,t-1/3],r=n<.5?n*(1+e):n+e-n*e,s=2*n-r,a=[],o=0;o<3;o++){var h=i[o];h<0&&(h+=1),h>1&&(h-=1),a[o]=6*h<1?s+6*(r-s)*h:2*h<1?r:3*h<2?s+(r-s)*(2/3-h)*6:s}return a},"rgb-gray":function(t,e,n){return[.2989*t+.587*e+.114*n]},"gray-rgb":function(t){return[t,t,t]},"gray-hsb":function(t){return[0,0,t]},"gray-hsl":function(t){return[0,0,t]},"gradient-rgb":function(){return[]},"rgb-gradient":function(){return[]}};return r.each(i,function(t,e){s[e]=[],r.each(t,function(t,n){var a=r.capitalize(t),o=/^(hue|saturation)$/.test(t),h=s[e][n]="gradient"===t?function(t){var e=this._components[0];return t=R.read(Array.isArray(t)?t:arguments,0,{readNull:!0}),e!==t&&(e&&e._removeOwner(this),t&&t._addOwner(this)),t}:"gradient"===e?function(){return c.read(arguments,0,{readNull:"highlight"===t,clone:!0})}:function(t){return null==t||isNaN(t)?0:t};this["get"+a]=function(){return this._type===e||o&&/^hs[bl]$/.test(this._type)?this._components[n]:this._convert(e)[n]},this["set"+a]=function(t){this._type===e||o&&/^hs[bl]$/.test(this._type)||(this._components=this._convert(e),this._properties=i[e],this._type=e),this._components[n]=h.call(this,t),this._changed()}},this)},{_class:"Color",_readIndex:!0,initialize:function l(e){var n,r,a,o,h=Array.prototype.slice,u=arguments,c=this.__read,f=0;Array.isArray(e)&&(u=e,e=u[0]);var d=null!=e&&typeof e;if("string"===d&&e in i&&(n=e,e=u[1],Array.isArray(e)?(r=e,a=u[2]):(c&&(f=1),u=h.call(u,1),d=typeof e)),!r){if(o="number"===d?u:"object"===d&&null!=e.length?e:null){n||(n=o.length>=3?"rgb":"gray");var _=i[n].length;a=o[_],c&&(f+=o===arguments?_+(null!=a?1:0):1),o.length>_&&(o=h.call(o,0,_))}else if("string"===d)n="rgb",r=t(e),4===r.length&&(a=r[3],r.length--);else if("object"===d)if(e.constructor===l){if(n=e._type,r=e._components.slice(),a=e._alpha,"gradient"===n)for(var g=1,v=r.length;g<v;g++){var p=r[g];p&&(r[g]=p.clone())}}else if(e.constructor===R)n="gradient",o=u;else{n="hue"in e?"lightness"in e?"hsl":"hsb":"gradient"in e||"stops"in e||"radial"in e?"gradient":"gray"in e?"gray":"rgb";var m=i[n],y=s[n];this._components=r=[];for(var g=0,v=m.length;g<v;g++){var w=e[m[g]];null==w&&0===g&&"gradient"===n&&"stops"in e&&(w={stops:e.stops,radial:e.radial}),w=y[g].call(this,w),null!=w&&(r[g]=w)}a=e.alpha}c&&n&&(f=1)}if(this._type=n||"rgb",!r){this._components=r=[];for(var y=s[this._type],g=0,v=y.length;g<v;g++){var w=y[g].call(this,o&&o[g]);null!=w&&(r[g]=w)}}this._components=r,this._properties=i[this._type],this._alpha=a,c&&(this.__read=f)},_set:"#initialize",_serialize:function(t,e){var n=this.getComponents();return r.serialize(/^(gray|rgb)$/.test(this._type)?n:[this._type].concat(n),t,!0,e)},_changed:function(){this._canvasStyle=null,this._owner&&this._owner._changed(65)},_convert:function(t){var e;return this._type===t?this._components.slice():(e=u[this._type+"-"+t])?e.apply(this,this._components):u["rgb-"+t].apply(this,u[this._type+"-rgb"].apply(this,this._components))},convert:function(t){return new D(t,this._convert(t),this._alpha)},getType:function(){return this._type},setType:function(t){this._components=this._convert(t),this._properties=i[t],this._type=t},getComponents:function(){var t=this._components.slice();return null!=this._alpha&&t.push(this._alpha),t},getAlpha:function(){return null!=this._alpha?this._alpha:1},setAlpha:function(t){this._alpha=null==t?null:Math.min(Math.max(t,0),1),this._changed()},hasAlpha:function(){return null!=this._alpha},equals:function(t){var e=r.isPlainValue(t,!0)?D.read(arguments):t;return e===this||e&&this._class===e._class&&this._type===e._type&&this._alpha===e._alpha&&r.equals(this._components,e._components)||!1},toString:function(){for(var t=this._properties,e=[],n="gradient"===this._type,i=h.instance,r=0,s=t.length;r<s;r++){var a=this._components[r];null!=a&&e.push(t[r]+": "+(n?a:i.number(a)))}return null!=this._alpha&&e.push("alpha: "+i.number(this._alpha)),"{ "+e.join(", ")+" }"},toCSS:function(t){function e(t){return Math.round(255*(t<0?0:t>1?1:t))}var n=this._convert("rgb"),i=t||null==this._alpha?1:this._alpha;return n=[e(n[0]),e(n[1]),e(n[2])],i<1&&n.push(i<0?0:i),t?"#"+((1<<24)+(n[0]<<16)+(n[1]<<8)+n[2]).toString(16).slice(1):(4==n.length?"rgba(":"rgb(")+n.join(",")+")"},toCanvasStyle:function(t){if(this._canvasStyle)return this._canvasStyle;if("gradient"!==this._type)return this._canvasStyle=this.toCSS();var e,n=this._components,i=n[0],r=i._stops,s=n[1],a=n[2];if(i._radial){var o=a.getDistance(s),h=n[3];if(h){var u=h.subtract(s);u.getLength()>o&&(h=s.add(u.normalize(o-.1)))}var l=h||s;e=t.createRadialGradient(l.x,l.y,0,s.x,s.y,o)}else e=t.createLinearGradient(s.x,s.y,a.x,a.y);for(var c=0,f=r.length;c<f;c++){var d=r[c];e.addColorStop(d._offset||c/(f-1),d._color.toCanvasStyle())}return this._canvasStyle=e},transform:function(t){if("gradient"===this._type){for(var e=this._components,n=1,i=e.length;n<i;n++){var r=e[n];t._transformPoint(r,r,!0)}this._changed()}},statics:{_types:i,random:function(){var t=Math.random;return new D(t(),t(),t())}}})},new function(){var t={add:function(t,e){return t+e},subtract:function(t,e){return t-e},multiply:function(t,e){return t*e},divide:function(t,e){return t/e}};return r.each(t,function(t,e){this[e]=function(e){e=D.read(arguments);for(var n=this._type,i=this._components,r=e._convert(n),s=0,a=i.length;s<a;s++)r[s]=t(i[s],r[s]);return new D(n,r,null!=this._alpha?t(this._alpha,e.getAlpha()):null)}},{})}),R=r.extend({_class:"Gradient",initialize:function(t,e){this._id=l.get(),t&&this._set(t)&&(t=e=null),this._stops||this.setStops(t||["white","black"]),null==this._radial&&this.setRadial("string"==typeof e&&"radial"===e||e||!1)},_serialize:function(t,e){return e.add(this,function(){return r.serialize([this._stops,this._radial],t,!0,e)})},_changed:function(){for(var t=0,e=this._owners&&this._owners.length;t<e;t++)this._owners[t]._changed()},_addOwner:function(t){this._owners||(this._owners=[]),this._owners.push(t)},_removeOwner:function(t){var n=this._owners?this._owners.indexOf(t):-1;n!=-1&&(this._owners.splice(n,1),0===this._owners.length&&(this._owners=e))},clone:function(){for(var t=[],e=0,n=this._stops.length;e<n;e++)t[e]=this._stops[e].clone();return new R(t,this._radial)},getStops:function(){return this._stops},setStops:function(t){if(t.length<2)throw new Error("Gradient stop list needs to contain at least two stops.");var n=this._stops;if(n)for(var i=0,r=n.length;i<r;i++)n[i]._owner=e;n=this._stops=q.readAll(t,0,{clone:!0});for(var i=0,r=n.length;i<r;i++)n[i]._owner=this;this._changed()},getRadial:function(){return this._radial},setRadial:function(t){this._radial=t,this._changed()},equals:function(t){if(t===this)return!0;if(t&&this._class===t._class){var e=this._stops,n=t._stops,i=e.length;if(i===n.length){for(var r=0;r<i;r++)if(!e[r].equals(n[r]))return!1;return!0}}return!1}}),q=r.extend({_class:"GradientStop",initialize:function(t,n){var i=t,r=n;"object"==typeof t&&n===e&&(Array.isArray(t)&&"number"!=typeof t[0]?(i=t[0],r=t[1]):("color"in t||"offset"in t||"rampPoint"in t)&&(i=t.color,r=t.offset||t.rampPoint||0)),this.setColor(i),this.setOffset(r)},clone:function(){return new q(this._color.clone(),this._offset)},_serialize:function(t,e){var n=this._color,i=this._offset;return r.serialize(null==i?[n]:[n,i],t,!0,e)},_changed:function(){this._owner&&this._owner._changed(65)},getOffset:function(){return this._offset},setOffset:function(t){this._offset=t,this._changed()},getRampPoint:"#getOffset",setRampPoint:"#setOffset",getColor:function(){return this._color},setColor:function(){var t=D.read(arguments,0,{clone:!0});t&&(t._owner=this),this._color=t,this._changed()},equals:function(t){return t===this||t&&this._class===t._class&&this._color.equals(t._color)&&this._offset==t._offset||!1}}),V=r.extend(new function(){var t={fillColor:null,fillRule:"nonzero",strokeColor:null,strokeWidth:1,strokeCap:"butt",strokeJoin:"miter",strokeScaling:!0,miterLimit:10,dashOffset:0,dashArray:[],shadowColor:null,shadowBlur:0,shadowOffset:new c,selectedColor:null},n=r.set({},t,{fontFamily:"sans-serif",fontWeight:"normal",fontSize:12,leading:null,justification:"left"}),i=r.set({},n,{fillColor:new D}),s={strokeWidth:97,strokeCap:97,strokeJoin:97,strokeScaling:105,miterLimit:97,fontFamily:9,fontWeight:9,fontSize:9,font:9,leading:9,justification:9},a={beans:!0},o={_class:"Style",beans:!0,initialize:function(e,r,s){this._values={},this._owner=r,this._project=r&&r._project||s||paper.project,this._defaults=!r||r instanceof x?n:r instanceof j?i:t,e&&this.set(e)}};return r.each(n,function(t,n){var i=/Color$/.test(n),h="shadowOffset"===n,u=r.capitalize(n),l=s[n],f="set"+u,d="get"+u;o[f]=function(t){var r=this._owner,s=r&&r._children;if(s&&s.length>0&&!(r instanceof L))for(var a=0,o=s.length;a<o;a++)s[a]._style[f](t);else if(n in this._defaults){var h=this._values[n];h!==t&&(i&&(h&&h._owner!==e&&(h._owner=e),t&&t.constructor===D&&(t._owner&&(t=t.clone()),t._owner=r)),this._values[n]=t,r&&r._changed(l||65))}},o[d]=function(t){var s,a=this._owner,o=a&&a._children;if(n in this._defaults&&(!o||0===o.length||t||a instanceof L)){var s=this._values[n];if(s===e)s=this._defaults[n],s&&s.clone&&(s=s.clone());else{var u=i?D:h?c:null;!u||s&&s.constructor===u||(this._values[n]=s=u.read([s],0,{readNull:!0,clone:!0}),s&&i&&(s._owner=a))}}else if(o)for(var l=0,f=o.length;l<f;l++){var _=o[l]._style[d]();if(0===l)s=_;else if(!r.equals(s,_))return e}return s},a[d]=function(t){return this._style[d](t)},a[f]=function(t){this._style[f](t)}}),r.each({Font:"FontFamily",WindingRule:"FillRule"},function(t,e){var n="get"+e,i="set"+e;o[n]=a[n]="#get"+t,o[i]=a[i]="#set"+t}),w.inject(a),o},{set:function(t){var e=t instanceof V,n=e?t._values:t;if(n)for(var i in n)if(i in this._defaults){
-var r=n[i];this[i]=r&&e&&r.clone?r.clone():r}},equals:function(t){return t===this||t&&this._class===t._class&&r.equals(this._values,t._values)||!1},hasFill:function(){var t=this.getFillColor();return!!t&&t.alpha>0},hasStroke:function(){var t=this.getStrokeColor();return!!t&&t.alpha>0&&this.getStrokeWidth()>0},hasShadow:function(){var t=this.getShadowColor();return!!t&&t.alpha>0&&(this.getShadowBlur()>0||!this.getShadowOffset().isZero())},getView:function(){return this._project._view},getFontStyle:function(){var t=this.getFontSize();return this.getFontWeight()+" "+t+(/[a-z]/i.test(t+"")?" ":"px ")+this.getFontFamily()},getFont:"#getFontFamily",setFont:"#setFontFamily",getLeading:function xt(){var t=xt.base.call(this),e=this.getFontSize();return/pt|em|%|px/.test(e)&&(e=this.getView().getPixelSize(e)),null!=t?t:1.2*e}}),H=new function(){function t(t,e,n,i){for(var r=["","webkit","moz","Moz","ms","o"],s=e[0].toUpperCase()+e.substring(1),a=0;a<6;a++){var o=r[a],h=o?o+s:e;if(h in t){if(!n)return t[h];t[h]=i;break}}}return{getStyles:function(t){var e=t&&9!==t.nodeType?t.ownerDocument:t,n=e&&e.defaultView;return n&&n.getComputedStyle(t,"")},getBounds:function(t,e){var n,i=t.ownerDocument,r=i.body,s=i.documentElement;try{n=t.getBoundingClientRect()}catch(a){n={left:0,top:0,width:0,height:0}}var o=n.left-(s.clientLeft||r.clientLeft||0),h=n.top-(s.clientTop||r.clientTop||0);if(!e){var u=i.defaultView;o+=u.pageXOffset||s.scrollLeft||r.scrollLeft,h+=u.pageYOffset||s.scrollTop||r.scrollTop}return new g(o,h,n.width,n.height)},getViewportBounds:function(t){var e=t.ownerDocument,n=e.defaultView,i=e.documentElement;return new g(0,0,n.innerWidth||i.clientWidth,n.innerHeight||i.clientHeight)},getOffset:function(t,e){return H.getBounds(t,e).getPoint()},getSize:function(t){return H.getBounds(t,!0).getSize()},isInvisible:function(t){return H.getSize(t).equals(new d(0,0))},isInView:function(t){return!H.isInvisible(t)&&H.getViewportBounds(t).intersects(H.getBounds(t,!0))},isInserted:function(t){return i.body.contains(t)},getPrefixed:function(e,n){return e&&t(e,n)},setPrefixed:function(e,n,i){if("object"==typeof n)for(var r in n)t(e,r,!0,n[r]);else t(e,n,!0,i)}}},U={add:function(t,e){if(t)for(var n in e)for(var i=e[n],r=n.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.addEventListener(r[s],i,!1)},remove:function(t,e){if(t)for(var n in e)for(var i=e[n],r=n.split(/[\s,]+/g),s=0,a=r.length;s<a;s++)t.removeEventListener(r[s],i,!1)},getPoint:function(t){var e=t.targetTouches?t.targetTouches.length?t.targetTouches[0]:t.changedTouches[0]:t;return new c(e.pageX||e.clientX+i.documentElement.scrollLeft,e.pageY||e.clientY+i.documentElement.scrollTop)},getTarget:function(t){return t.target||t.srcElement},getRelatedTarget:function(t){return t.relatedTarget||t.toElement},getOffset:function(t,e){return U.getPoint(t).subtract(H.getOffset(e||U.getTarget(t)))}};U.requestAnimationFrame=new function(){function t(){var e=s;s=[];for(var n=0,a=e.length;n<a;n++)e[n]();r=i&&s.length,r&&i(t)}var e,i=H.getPrefixed(n,"requestAnimationFrame"),r=!1,s=[];return function(n){s.push(n),i?r||(i(t),r=!0):e||(e=setInterval(t,1e3/60))}};var Z=r.extend(s,{_class:"View",initialize:function bt(t,e){function r(t){return e[t]||parseInt(e.getAttribute(t),10)}function s(){var t=H.getSize(e);return t.isNaN()||t.isZero()?new d(r("width"),r("height")):t}var o;if(n&&e){this._id=e.getAttribute("id"),null==this._id&&e.setAttribute("id",this._id="view-"+bt._id++),U.add(e,this._viewEvents);var h="none";if(H.setPrefixed(e.style,{userDrag:h,userSelect:h,touchCallout:h,contentZooming:h,tapHighlightColor:"rgba(0,0,0,0)"}),a.hasAttribute(e,"resize")){var u=this;U.add(n,this._windowEvents={resize:function(){u.setViewSize(s())}})}if(o=s(),a.hasAttribute(e,"stats")&&"undefined"!=typeof Stats){this._stats=new Stats;var l=this._stats.domElement,c=l.style,f=H.getOffset(e);c.position="absolute",c.left=f.x+"px",c.top=f.y+"px",i.body.appendChild(l)}}else o=new d(e),e=null;this._project=t,this._scope=t._scope,this._element=e,this._pixelRatio||(this._pixelRatio=n&&n.devicePixelRatio||1),this._setElementSize(o.width,o.height),this._viewSize=o,bt._views.push(this),bt._viewsById[this._id]=this,(this._matrix=new p)._owner=this,this._zoom=1,bt._focused||(bt._focused=this),this._frameItems={},this._frameItemCount=0,this._itemEvents={"native":{},virtual:{}},this._autoUpdate=!paper.agent.node,this._needsUpdate=!1},remove:function(){if(!this._project)return!1;Z._focused===this&&(Z._focused=null),Z._views.splice(Z._views.indexOf(this),1),delete Z._viewsById[this._id];var t=this._project;return t._view===this&&(t._view=null),U.remove(this._element,this._viewEvents),U.remove(n,this._windowEvents),this._element=this._project=null,this.off("frame"),this._animate=!1,this._frameItems={},!0},_events:r.each(w._itemHandlers.concat(["onResize","onKeyDown","onKeyUp"]),function(t){this[t]={}},{onFrame:{install:function(){this.play()},uninstall:function(){this.pause()}}}),_animate:!1,_time:0,_count:0,getAutoUpdate:function(){return this._autoUpdate},setAutoUpdate:function(t){this._autoUpdate=t,t&&this.requestUpdate()},update:function(){},draw:function(){this.update()},requestUpdate:function(){if(!this._requested){var t=this;U.requestAnimationFrame(function(){if(t._requested=!1,t._animate){t.requestUpdate();var e=t._element;H.getPrefixed(i,"hidden")&&"true"!==a.getAttribute(e,"keepalive")||!H.isInView(e)||t._handleFrame()}t._autoUpdate&&t.update()}),this._requested=!0}},play:function(){this._animate=!0,this.requestUpdate()},pause:function(){this._animate=!1},_handleFrame:function(){paper=this._scope;var t=Date.now()/1e3,e=this._last?t-this._last:0;this._last=t,this.emit("frame",new r({delta:e,time:this._time+=e,count:this._count++})),this._stats&&this._stats.update()},_animateItem:function(t,e){var n=this._frameItems;e?(n[t._id]={item:t,time:0,count:0},1===++this._frameItemCount&&this.on("frame",this._handleFrameItems)):(delete n[t._id],0===--this._frameItemCount&&this.off("frame",this._handleFrameItems))},_handleFrameItems:function(t){for(var e in this._frameItems){var n=this._frameItems[e];n.item.emit("frame",new r(t,{time:n.time+=t.delta,count:n.count++}))}},_changed:function(){this._project._changed(2049),this._bounds=null},getElement:function(){return this._element},getPixelRatio:function(){return this._pixelRatio},getResolution:function(){return 72*this._pixelRatio},getViewSize:function(){var t=this._viewSize;return new _(t.width,t.height,this,"setViewSize")},setViewSize:function(){var t=d.read(arguments),e=t.width,n=t.height,i=t.subtract(this._viewSize);i.isZero()||(this._setElementSize(e,n),this._viewSize.set(e,n),this.emit("resize",{size:t,delta:i}),this._changed(),this._autoUpdate&&this.requestUpdate())},_setElementSize:function(t,e){var n=this._element;n&&(n.width!==t&&(n.width=t),n.height!==e&&(n.height=e))},getBounds:function(){return this._bounds||(this._bounds=this._matrix.inverted()._transformBounds(new g(new c,this._viewSize))),this._bounds},getSize:function(){return this.getBounds().getSize()},getCenter:function(){return this.getBounds().getCenter()},setCenter:function(){var t=c.read(arguments);this.translate(this.getCenter().subtract(t))},getZoom:function(){return this._zoom},setZoom:function(t){this.transform((new p).scale(t/this._zoom,this.getCenter())),this._zoom=t},getMatrix:function(){return this._matrix},setMatrix:function(){var t=this._matrix;t.initialize.apply(t,arguments)},isVisible:function(){return H.isInView(this._element)},isInserted:function(){return H.isInserted(this._element)},getPixelSize:function(t){var e,n=this._element;if(n){var r=n.parentNode,s=i.createElement("div");s.style.fontSize=t,r.appendChild(s),e=parseFloat(H.getStyles(s).fontSize),r.removeChild(s)}else e=parseFloat(e);return e},getTextWidth:function(t,e){return 0}},r.each(["rotate","scale","shear","skew"],function(t){var e="rotate"===t;this[t]=function(){var n=(e?r:c).read(arguments),i=c.read(arguments,0,{readNull:!0});return this.transform((new p)[t](n,i||this.getCenter(!0)))}},{translate:function(){var t=new p;return this.transform(t.translate.apply(t,arguments))},transform:function(t){this._matrix.append(t)},scrollBy:function(){this.translate(c.read(arguments).negate())}}),{projectToView:function(){return this._matrix._transformPoint(c.read(arguments))},viewToProject:function(){return this._matrix._inverseTransform(c.read(arguments))},getEventPoint:function(t){return this.viewToProject(U.getOffset(t,this._element))}},{statics:{_views:[],_viewsById:{},_id:0,create:function(t,e){i&&"string"==typeof e&&(e=i.getElementById(e));var r=n?W:Z;return new r(t,e)}}},new function(){function t(t){var e=U.getTarget(t);return e.getAttribute&&Z._viewsById[e.getAttribute("id")]}function e(){var t=Z._focused;if(!t||!t.isVisible())for(var e=0,n=Z._views.length;e<n;e++)if((t=Z._views[e]).isVisible()){Z._focused=h=t;break}}function r(t,e,n){t._handleMouseEvent("mousemove",e,n)}function s(t,e,n,i,r,s,a){function o(t,n){if(t.responds(n)){if(h||(h=new X(n,i,r,e||t,s?r.subtract(s):null)),t.emit(n,h)&&(I=!0,h.prevented&&(P=!0),h.stopped))return u=!0}else{var a=M[n];if(a)return o(t,a)}}for(var h,u=!1;t&&t!==a&&!o(t,n);)t=t._parent;return u}function a(t,e,n,i,r,a){return t._project.removeOn(n),P=I=!1,b&&s(b,null,n,i,r,a)||e&&e!==b&&!e.isDescendant(b)&&s(e,null,M[n]||n,i,r,a,b)||s(t,b||e||t,n,i,r,a)}if(n){var o,h,u,l,c,f=!1,d=!1,_=n.navigator;_.pointerEnabled||_.msPointerEnabled?(u="pointerdown MSPointerDown",l="pointermove MSPointerMove",c="pointerup pointercancel MSPointerUp MSPointerCancel"):(u="touchstart",l="touchmove",c="touchend touchcancel","ontouchstart"in n&&_.userAgent.match(/mobile|tablet|ip(ad|hone|od)|android|silk/i)||(u+=" mousedown",l+=" mousemove",c+=" mouseup"));var g={},v={mouseout:function(t){var e=Z._focused,n=U.getRelatedTarget(t);if(e&&(!n||"HTML"===n.nodeName)){var i=U.getOffset(t,e._element),s=i.x,a=Math.abs,o=a(s),h=1<<25,u=o-h;i.x=a(u)<o?u*(s<0?-1:1):s,r(e,t,e.viewToProject(i))}},scroll:e};g[u]=function(e){var n=Z._focused=t(e);f||(f=!0,n._handleMouseEvent("mousedown",e))},v[l]=function(n){var i=Z._focused;if(!d){var s=t(n);s?i!==s&&(i&&r(i,n),o||(o=i),i=Z._focused=h=s):h&&h===i&&(o&&!o.isInserted()&&(o=null),i=Z._focused=o,o=null,e())}i&&r(i,n)},v[u]=function(){d=!0},v[c]=function(t){var e=Z._focused;e&&f&&e._handleMouseEvent("mouseup",t),d=f=!1},U.add(i,v),U.add(n,{load:e});var p,m,y,w,x,b,C,S,k,I=!1,P=!1,M={doubleclick:"click",mousedrag:"mousemove"},A=!1,T={mousedown:{mousedown:1,mousedrag:1,click:1,doubleclick:1},mouseup:{mouseup:1,mousedrag:1,click:1,doubleclick:1},mousemove:{mousedrag:1,mousemove:1,mouseenter:1,mouseleave:1}};return{_viewEvents:g,_handleMouseEvent:function(t,e,n){function i(t){return r.virtual[t]||l.responds(t)||u&&u.responds(t)}var r=this._itemEvents,o=r["native"][t],h="mousemove"===t,u=this._scope.tool,l=this;h&&f&&i("mousedrag")&&(t="mousedrag"),n||(n=this.getEventPoint(e));var c=this.getBounds().contains(n),d=o&&c&&l._project.hitTest(n,{tolerance:0,fill:!0,stroke:!0}),_=d&&d.item||null,g=!1,v={};v[t.substr(5)]=!0,o&&_!==x&&(x&&s(x,null,"mouseleave",e,n),_&&s(_,null,"mouseenter",e,n),x=_),A^c&&(s(this,null,c?"mouseenter":"mouseleave",e,n),p=c?this:null,g=!0),!c&&!v.drag||n.equals(y)||(a(this,_,h?t:"mousemove",e,n,y),g=!0),A=c,(v.down&&c||v.up&&m)&&(a(this,_,t,e,n,m),v.down?(k=_===C&&Date.now()-S<300,w=C=_,b=!P&&_,m=n):v.up&&(P||_!==w||(S=Date.now(),a(this,_,k?"doubleclick":"click",e,n,m),k=!1),w=b=null),A=!1,g=!0),y=n,g&&u&&(I=u._handleMouseEvent(t,e,n,v)||I),(I&&!v.move||v.down&&i("mouseup"))&&e.preventDefault()},_handleKeyEvent:function(t,e,n,i){function r(r){r.responds(t)&&(paper=a,r.emit(t,s=s||new $(t,e,n,i)))}var s,a=this._scope,o=a.tool;this.isVisible()&&(r(this),o&&o.responds(t)&&r(o))},_countItemEvent:function(t,e){var n=this._itemEvents,i=n["native"],r=n.virtual;for(var s in T)i[s]=(i[s]||0)+(T[s][t]||0)*e;r[t]=(r[t]||0)+e},statics:{updateFocus:e}}}}),W=Z.extend({_class:"CanvasView",initialize:function(t,e){if(!(e instanceof n.HTMLCanvasElement)){var i=d.read(arguments,1);if(i.isZero())throw new Error("Cannot create CanvasView with the provided argument: "+[].slice.call(arguments,1));e=tt.getCanvas(i)}var r=this._context=e.getContext("2d");if(r.save(),this._pixelRatio=1,!/^off|false$/.test(a.getAttribute(e,"hidpi"))){var s=n.devicePixelRatio||1,o=H.getPrefixed(r,"backingStorePixelRatio")||1;this._pixelRatio=s/o}Z.call(this,t,e),this._needsUpdate=!0},remove:function Ct(){return this._context.restore(),Ct.base.call(this)},_setElementSize:function St(t,e){var n=this._pixelRatio;if(St.base.call(this,t*n,e*n),1!==n){var i=this._element,r=this._context;if(!a.hasAttribute(i,"resize")){var s=i.style;s.width=t+"px",s.height=e+"px"}r.restore(),r.save(),r.scale(n,n)}},getPixelSize:function kt(t){var e,n=paper.agent;if(n&&n.firefox)e=kt.base.call(this,t);else{var i=this._context,r=i.font;i.font=t+" serif",e=parseFloat(i.font),i.font=r}return e},getTextWidth:function(t,e){var n=this._context,i=n.font,r=0;n.font=t;for(var s=0,a=e.length;s<a;s++)r=Math.max(r,n.measureText(e[s]).width);return n.font=i,r},update:function(){if(!this._needsUpdate)return!1;var t=this._project,e=this._context,n=this._viewSize;return e.clearRect(0,0,n.width+1,n.height+1),t&&t.draw(e,this._matrix,this._pixelRatio),this._needsUpdate=!1,!0}}),G=r.extend({_class:"Event",initialize:function(t){this.event=t,this.type=t&&t.type},prevented:!1,stopped:!1,preventDefault:function(){this.prevented=!0,this.event.preventDefault()},stopPropagation:function(){this.stopped=!0,this.event.stopPropagation()},stop:function(){this.stopPropagation(),this.preventDefault()},getTimeStamp:function(){return this.event.timeStamp},getModifiers:function(){return J.modifiers}}),$=G.extend({_class:"KeyEvent",initialize:function(t,e,n,i){this.type=t,this.event=e,this.key=n,this.character=i},toString:function(){return"{ type: '"+this.type+"', key: '"+this.key+"', character: '"+this.character+"', modifiers: "+this.getModifiers()+" }"}}),J=new function(){function t(t){var e=t.key||t.keyIdentifier;return e=/^U\+/.test(e)?String.fromCharCode(parseInt(e.substr(2),16)):/^Arrow[A-Z]/.test(e)?e.substr(5):"Unidentified"===e?String.fromCharCode(t.keyCode):e,o[e]||(e.length>1?r.hyphenate(e):e.toLowerCase())}function e(t,n,i,a){var o,h=Z._focused;if(u[n]=t,t?l[n]=i:delete l[n],n.length>1&&(o=r.camelize(n))in c){c[o]=t;var f=paper&&paper.agent;if("meta"===o&&f&&f.mac)if(t)s={};else{for(var d in s)d in l&&e(!1,d,s[d],a);s=null}}else t&&s&&(s[n]=i);h&&h._handleKeyEvent(t?"keydown":"keyup",a,n,i)}var s,a,o={"\t":"tab"," ":"space","\b":"backspace","\x7f":"delete",Spacebar:"space",Del:"delete",Win:"meta",Esc:"escape"},h={tab:"\t",space:" ",enter:"\r"},u={},l={},c=new r({shift:!1,control:!1,alt:!1,meta:!1,capsLock:!1,space:!1}).inject({option:{get:function(){return this.alt}},command:{get:function(){var t=paper&&paper.agent;return t&&t.mac?this.meta:this.control}}});return U.add(i,{keydown:function(n){var i=t(n),r=paper&&paper.agent;i.length>1||r&&r.chrome&&(n.altKey||r.mac&&n.metaKey||!r.mac&&n.ctrlKey)?e(!0,i,h[i]||(i.length>1?"":i),n):a=i},keypress:function(n){if(a){var i=t(n),r=n.charCode,s=r>=32?String.fromCharCode(r):i.length>1?"":i;i!==a&&(i=s.toLowerCase()),e(!0,i,s,n),a=null}},keyup:function(n){var i=t(n);i in l&&e(!1,i,l[i],n)}}),U.add(n,{blur:function(t){for(var n in l)e(!1,n,l[n],t)}}),{modifiers:c,isDown:function(t){return!!u[t]}}},X=G.extend({_class:"MouseEvent",initialize:function(t,e,n,i,r){this.type=t,this.event=e,this.point=n,this.target=i,this.delta=r},toString:function(){return"{ type: '"+this.type+"', point: "+this.point+", target: "+this.target+(this.delta?", delta: "+this.delta:"")+", modifiers: "+this.getModifiers()+" }"}}),Y=G.extend({_class:"ToolEvent",_item:null,initialize:function(t,e,n){this.tool=t,this.type=e,this.event=n},_choosePoint:function(t,e){return t?t:e?e.clone():null},getPoint:function(){return this._choosePoint(this._point,this.tool._point)},setPoint:function(t){this._point=t},getLastPoint:function(){return this._choosePoint(this._lastPoint,this.tool._lastPoint)},setLastPoint:function(t){this._lastPoint=t},getDownPoint:function(){return this._choosePoint(this._downPoint,this.tool._downPoint)},setDownPoint:function(t){this._downPoint=t},getMiddlePoint:function(){return!this._middlePoint&&this.tool._lastPoint?this.tool._point.add(this.tool._lastPoint).divide(2):this._middlePoint},setMiddlePoint:function(t){this._middlePoint=t},getDelta:function(){return!this._delta&&this.tool._lastPoint?this.tool._point.subtract(this.tool._lastPoint):this._delta},setDelta:function(t){this._delta=t},getCount:function(){return this.tool[/^mouse(down|up)$/.test(this.type)?"_downCount":"_moveCount"]},setCount:function(t){this.tool[/^mouse(down|up)$/.test(this.type)?"downCount":"count"]=t},getItem:function(){if(!this._item){var t=this.tool._scope.project.hitTest(this.getPoint());if(t){for(var e=t.item,n=e._parent;/^(Group|CompoundPath)$/.test(n._class);)e=n,n=n._parent;this._item=e}}return this._item},setItem:function(t){this._item=t},toString:function(){return"{ type: "+this.type+", point: "+this.getPoint()+", count: "+this.getCount()+", modifiers: "+this.getModifiers()+" }"}}),K=o.extend({_class:"Tool",_list:"tools",_reference:"tool",_events:["onMouseDown","onMouseUp","onMouseDrag","onMouseMove","onActivate","onDeactivate","onEditOptions","onKeyDown","onKeyUp"],initialize:function(t){o.call(this),this._moveCount=-1,this._downCount=-1,this._set(t)},getMinDistance:function(){return this._minDistance},setMinDistance:function(t){this._minDistance=t,null!=t&&null!=this._maxDistance&&t>this._maxDistance&&(this._maxDistance=t)},getMaxDistance:function(){return this._maxDistance},setMaxDistance:function(t){this._maxDistance=t,null!=this._minDistance&&null!=t&&t<this._minDistance&&(this._minDistance=t)},getFixedDistance:function(){return this._minDistance==this._maxDistance?this._minDistance:null},setFixedDistance:function(t){this._minDistance=this._maxDistance=t},_handleMouseEvent:function(t,e,n,i){function r(t,e){var r=n,s=a?c._point:c._downPoint||r;if(a){if(c._moveCount&&r.equals(s))return!1;if(s&&(null!=t||null!=e)){var o=r.subtract(s),h=o.getLength();if(h<(t||0))return!1;e&&(r=s.add(o.normalize(Math.min(h,e))))}c._moveCount++}return c._point=r,c._lastPoint=s||r,i.down&&(c._moveCount=-1,c._downPoint=r,c._downCount++),!0}function s(){o&&(l=c.emit(t,new Y(c,t,e))||l)}paper=this._scope,i.drag&&!this.responds(t)&&(t="mousemove");var a=i.move||i.drag,o=this.responds(t),h=this.minDistance,u=this.maxDistance,l=!1,c=this;if(i.down)r(),s();else if(i.up)r(null,u),s();else if(o)for(;r(h,u);)s();return l}}),Q={request:function(t){var e=new n.XMLHttpRequest;return e.open((t.method||"get").toUpperCase(),t.url,r.pick(t.async,!0)),t.mimeType&&e.overrideMimeType(t.mimeType),e.onload=function(){var n=e.status;0===n||200===n?t.onLoad&&t.onLoad.call(e,e.responseText):e.onerror()},e.onerror=function(){var n=e.status,i='Could not load "'+t.url+'" (Status: '+n+")";if(!t.onError)throw new Error(i);t.onError(i,n)},e.send(null)}},tt={canvases:[],getCanvas:function(t,e){if(!n)return null;var r,s=!0;"object"==typeof t&&(e=t.height,t=t.width),this.canvases.length?r=this.canvases.pop():(r=i.createElement("canvas"),s=!1);var a=r.getContext("2d");if(!a)throw new Error("Canvas "+r+" is unable toprovide a 2D context.");return r.width===t&&r.height===e?s&&a.clearRect(0,0,t+1,e+1):(r.width=t,r.height=e),a.save(),r},getContext:function(t,e){var n=this.getCanvas(t,e);return n?n.getContext("2d"):null},release:function(t){var e=t&&t.canvas?t.canvas:t;e&&e.getContext&&(e.getContext("2d").restore(),this.canvases.push(e))}},et=new function(){function t(t,e,n){return.2989*t+.587*e+.114*n}function e(e,n,i,r){var s=r-t(e,n,i);d=e+s,_=n+s,g=i+s;var r=t(d,_,g),a=v(d,_,g),o=p(d,_,g);if(a<0){var h=r-a;d=r+(d-r)*r/h,_=r+(_-r)*r/h,g=r+(g-r)*r/h}if(o>255){var u=255-r,l=o-r;d=r+(d-r)*u/l,_=r+(_-r)*u/l,g=r+(g-r)*u/l}}function n(t,e,n){return p(t,e,n)-v(t,e,n)}function i(t,e,n,i){var r,s=[t,e,n],a=p(t,e,n),o=v(t,e,n);o=o===t?0:o===e?1:2,a=a===t?0:a===e?1:2,r=0===v(o,a)?1===p(o,a)?2:1:0,s[a]>s[o]?(s[r]=(s[r]-s[o])*i/(s[a]-s[o]),s[a]=i):s[r]=s[a]=0,s[o]=0,d=s[0],_=s[1],g=s[2]}var s,a,o,h,u,l,c,f,d,_,g,v=Math.min,p=Math.max,m=Math.abs,y={multiply:function(){d=u*s/255,_=l*a/255,g=c*o/255},screen:function(){d=u+s-u*s/255,_=l+a-l*a/255,g=c+o-c*o/255},overlay:function(){d=u<128?2*u*s/255:255-2*(255-u)*(255-s)/255,_=l<128?2*l*a/255:255-2*(255-l)*(255-a)/255,g=c<128?2*c*o/255:255-2*(255-c)*(255-o)/255},"soft-light":function(){var t=s*u/255;d=t+u*(255-(255-u)*(255-s)/255-t)/255,t=a*l/255,_=t+l*(255-(255-l)*(255-a)/255-t)/255,t=o*c/255,g=t+c*(255-(255-c)*(255-o)/255-t)/255},"hard-light":function(){d=s<128?2*s*u/255:255-2*(255-s)*(255-u)/255,_=a<128?2*a*l/255:255-2*(255-a)*(255-l)/255,g=o<128?2*o*c/255:255-2*(255-o)*(255-c)/255},"color-dodge":function(){d=0===u?0:255===s?255:v(255,255*u/(255-s)),_=0===l?0:255===a?255:v(255,255*l/(255-a)),g=0===c?0:255===o?255:v(255,255*c/(255-o))},"color-burn":function(){d=255===u?255:0===s?0:p(0,255-255*(255-u)/s),_=255===l?255:0===a?0:p(0,255-255*(255-l)/a),g=255===c?255:0===o?0:p(0,255-255*(255-c)/o)},darken:function(){d=u<s?u:s,_=l<a?l:a,g=c<o?c:o},lighten:function(){d=u>s?u:s,_=l>a?l:a,g=c>o?c:o},difference:function(){d=u-s,d<0&&(d=-d),_=l-a,_<0&&(_=-_),g=c-o,g<0&&(g=-g)},exclusion:function(){d=u+s*(255-u-u)/255,_=l+a*(255-l-l)/255,g=c+o*(255-c-c)/255},hue:function(){i(s,a,o,n(u,l,c)),e(d,_,g,t(u,l,c))},saturation:function(){i(u,l,c,n(s,a,o)),e(d,_,g,t(u,l,c))},luminosity:function(){e(u,l,c,t(s,a,o))},color:function(){e(s,a,o,t(u,l,c))},add:function(){d=v(u+s,255),_=v(l+a,255),g=v(c+o,255)},subtract:function(){d=p(u-s,0),_=p(l-a,0),g=p(c-o,0)},average:function(){d=(u+s)/2,_=(l+a)/2,g=(c+o)/2},negation:function(){d=255-m(255-s-u),_=255-m(255-a-l),g=255-m(255-o-c)}},w=this.nativeModes=r.each(["source-over","source-in","source-out","source-atop","destination-over","destination-in","destination-out","destination-atop","lighter","darker","copy","xor"],function(t){this[t]=!0},{}),x=tt.getContext(1,1);x&&(r.each(y,function(t,e){var n="darken"===e,i=!1;x.save();try{x.fillStyle=n?"#300":"#a00",x.fillRect(0,0,1,1),x.globalCompositeOperation=e,x.globalCompositeOperation===e&&(x.fillStyle=n?"#a00":"#300",x.fillRect(0,0,1,1),i=x.getImageData(0,0,1,1).data[0]!==n?170:51)}catch(r){}x.restore(),w[e]=i}),tt.release(x)),this.process=function(t,e,n,i,r){var v=e.canvas,p="normal"===t;if(p||w[t])n.save(),n.setTransform(1,0,0,1,0,0),n.globalAlpha=i,p||(n.globalCompositeOperation=t),n.drawImage(v,r.x,r.y),n.restore();else{var m=y[t];if(!m)return;for(var x=n.getImageData(r.x,r.y,v.width,v.height),b=x.data,C=e.getImageData(0,0,v.width,v.height).data,S=0,k=b.length;S<k;S+=4){s=C[S],u=b[S],a=C[S+1],l=b[S+1],o=C[S+2],c=b[S+2],h=C[S+3],f=b[S+3],m();var I=h*i/255,P=1-I;b[S]=I*d+P*u,b[S+1]=I*_+P*l,b[S+2]=I*g+P*c,b[S+3]=h*i+P*f}n.putImageData(x,r.x,r.y)}}},nt=new function(){function t(t,e,s){return n(i.createElementNS(r,t),e,s)}function e(t,e){var n=o[e],i=n?t.getAttributeNS(n,e):t.getAttribute(e);return"null"===i?null:i}function n(t,e,n){for(var i in e){var r=e[i],s=o[i];"number"==typeof r&&n&&(r=n.number(r)),s?t.setAttributeNS(s,i,r):t.setAttribute(i,r)}return t}var r="http://www.w3.org/2000/svg",s="http://www.w3.org/2000/xmlns",a="http://www.w3.org/1999/xlink",o={href:a,xlink:s,xmlns:s+"/","xmlns:xlink":s+"/"};return{svg:r,xmlns:s,xlink:a,create:t,get:e,set:n}},it=r.each({fillColor:["fill","color"],fillRule:["fill-rule","string"],strokeColor:["stroke","color"],strokeWidth:["stroke-width","number"],strokeCap:["stroke-linecap","string"],strokeJoin:["stroke-linejoin","string"],strokeScaling:["vector-effect","lookup",{"true":"none","false":"non-scaling-stroke"},function(t,e){return!e&&(t instanceof O||t instanceof C||t instanceof j)}],miterLimit:["stroke-miterlimit","number"],dashArray:["stroke-dasharray","array"],dashOffset:["stroke-dashoffset","number"],fontFamily:["font-family","string"],fontWeight:["font-weight","string"],fontSize:["font-size","number"],justification:["text-anchor","lookup",{left:"start",center:"middle",right:"end"}],opacity:["opacity","number"],blendMode:["mix-blend-mode","style"]},function(t,e){var n=r.capitalize(e),i=t[2];this[e]={type:t[1],property:e,attribute:t[0],toSVG:i,fromSVG:i&&r.each(i,function(t,e){this[t]=e},{}),exportFilter:t[3],get:"get"+n,set:"set"+n}},{});return new function(){function t(t,e,n){var i=new r,s=t.getTranslation();if(e){t=t._shiftless();var a=t._inverseTransform(s);i[n?"cx":"x"]=a.x,i[n?"cy":"y"]=a.y,s=null}if(!t.isIdentity()){var o=t.decompose();if(o){var h=[],l=o.rotation,c=o.scaling,f=o.skewing;s&&!s.isZero()&&h.push("translate("+S.point(s)+")"),l&&h.push("rotate("+S.number(l)+")"),u.isZero(c.x-1)&&u.isZero(c.y-1)||h.push("scale("+S.point(c)+")"),f&&f.x&&h.push("skewX("+S.number(f.x)+")"),f&&f.y&&h.push("skewY("+S.number(f.y)+")"),i.transform=h.join(" ")}else i.transform="matrix("+t.getValues().join(",")+")"}return i}function e(e,n){for(var i=t(e._matrix),r=e._children,s=nt.create("g",i,S),a=0,o=r.length;a<o;a++){var h=r[a],u=b(h,n);if(u)if(h.isClipMask()){var l=nt.create("clipPath");l.appendChild(u),m(h,l,"clip"),nt.set(s,{"clip-path":"url(#"+l.id+")"})}else s.appendChild(u)}return s}function i(e,n){var i=t(e._matrix,!0),r=e.getSize(),s=e.getImage();return i.x-=r.width/2,i.y-=r.height/2,i.width=r.width,i.height=r.height,i.href=n.embedImages===!1&&s&&s.src||e.toDataURL(),nt.create("image",i,S)}function s(e,n){var i=n.matchShapes;if(i){var r=e.toShape(!1);if(r)return a(r,n)}var s,o=e._segments,h=o.length,u=t(e._matrix);if(i&&h>=2&&!e.hasHandles())if(h>2){s=e._closed?"polygon":"polyline";for(var l=[],c=0;c<h;c++)l.push(S.point(o[c]._point));u.points=l.join(" ")}else{s="line";var f=o[0]._point,d=o[1]._point;u.set({x1:f.x,y1:f.y,x2:d.x,y2:d.y})}else s="path",u.d=e.getPathData(null,n.precision);return nt.create(s,u,S)}function a(e){var n=e._type,i=e._radius,r=t(e._matrix,!0,"rectangle"!==n);if("rectangle"===n){n="rect";var s=e._size,a=s.width,o=s.height;r.x-=a/2,r.y-=o/2,r.width=a,r.height=o,i.isZero()&&(i=null)}return i&&("circle"===n?r.r=i:(r.rx=i.width,r.ry=i.height)),nt.create(n,r,S)}function o(e,n){var i=t(e._matrix),r=e.getPathData(null,n.precision);return r&&(i.d=r),nt.create("path",i,S)}function c(e,n){var i=t(e._matrix,!0),r=e._definition,s=v(r,"symbol"),a=r._item,o=a.getBounds();return s||(s=nt.create("symbol",{viewBox:S.rectangle(o)}),s.appendChild(b(a,n)),m(r,s,"symbol")),i.href="#"+s.id,i.x+=o.x,i.y+=o.y,i.width=o.width,i.height=o.height,i.overflow="visible",nt.create("use",i,S)}function f(t){var e=v(t,"color");if(!e){var n,i=t.getGradient(),r=i._radial,s=t.getOrigin(),a=t.getDestination();if(r){n={cx:s.x,cy:s.y,r:s.getDistance(a)};var o=t.getHighlight();o&&(n.fx=o.x,n.fy=o.y)}else n={x1:s.x,y1:s.y,x2:a.x,y2:a.y};n.gradientUnits="userSpaceOnUse",e=nt.create((r?"radial":"linear")+"Gradient",n,S);for(var h=i._stops,u=0,l=h.length;u<l;u++){var c=h[u],f=c._color,d=f.getAlpha();n={offset:c._offset||u/(l-1)},f&&(n["stop-color"]=f.toCSS(!0)),d<1&&(n["stop-opacity"]=d),e.appendChild(nt.create("stop",n,S))}m(t,e,"color")}return"url(#"+e.id+")"}function d(e){var n=nt.create("text",t(e._matrix,!0),S);return n.textContent=e._content,n}function _(t,e,n){var i={},s=!n&&t.getParent(),a=[];return null!=t._name&&(i.id=t._name),r.each(it,function(e){var n=e.get,o=e.type,h=t[n]();if(e.exportFilter?e.exportFilter(t,h):!s||!r.equals(s[n](),h)){if("color"===o&&null!=h){var u=h.getAlpha();u<1&&(i[e.attribute+"-opacity"]=u)}"style"===o?a.push(e.attribute+": "+h):i[e.attribute]=null==h?"none":"color"===o?h.gradient?f(h,t):h.toCSS(!0):"array"===o?h.join(","):"lookup"===o?e.toSVG[h]:h}}),a.length&&(i.style=a.join(";")),1===i.opacity&&delete i.opacity,t._visible||(i.visibility="hidden"),nt.set(e,i,S)}function v(t,e){k||(k={ids:{},svgs:{}});var n=t._id||t.__id||(t.__id=l.get("svg"));return t&&k.svgs[e+"-"+n]}function m(t,e,n){k||v();var i=k.ids[n]=(k.ids[n]||0)+1;e.id=n+"-"+i,k.svgs[n+"-"+(t._id||t.__id)]=e}function x(t,e){var i=t,r=null;if(k){i="svg"===t.nodeName.toLowerCase()&&t;for(var s in k.svgs)r||(i||(i=nt.create("svg"),i.appendChild(t)),r=i.insertBefore(nt.create("defs"),i.firstChild)),r.appendChild(k.svgs[s]);k=null}return e.asString?(new n.XMLSerializer).serializeToString(i):i}function b(t,e,n){var i=I[t._class],r=i&&i(t,e);if(r){var s=e.onExport;s&&(r=s(t,r,e)||r);var a=JSON.stringify(t._data);a&&"{}"!==a&&"null"!==a&&r.setAttribute("data-paper-data",a)}return r&&_(t,r,n)}function C(t){return t||(t={}),S=new h(t.precision),t}var S,k,I={Group:e,Layer:e,Raster:i,Path:s,Shape:a,CompoundPath:o,SymbolItem:c,PointText:d};w.inject({exportSVG:function(t){return t=C(t),x(b(this,t,!0),t)}}),y.inject({exportSVG:function(e){e=C(e);var n=this._children,i=this.getView(),s=r.pick(e.bounds,"view"),a=e.matrix||"view"===s&&i._matrix,o=a&&p.read([a]),h="view"===s?new g([0,0],i.getViewSize()):"content"===s?w._getBounds(n,o,{stroke:!0}):g.read([s],0,{readNull:!0}),u={version:"1.1",xmlns:nt.svg,"xmlns:xlink":nt.xlink};h&&(u.width=h.width,u.height=h.height,(h.x||h.y)&&(u.viewBox=S.rectangle(h)));var l=nt.create("svg",u,S),c=l;o&&!o.isIdentity()&&(c=l.appendChild(nt.create("g",t(o),S)));for(var f=0,d=n.length;f<d;f++)c.appendChild(b(n[f],e,!0));return x(l,e)}})},new function(){function t(t,e,n,i,r){var s=nt.get(t,e),a=null==s?i?null:n?"":0:n?s:parseFloat(s);return/%\s*$/.test(s)?a/100*(r?1:A[/x|^width/.test(e)?"width":"height"]):a}function s(e,n,i,r,s){return n=t(e,n||"x",!1,r,s),i=t(e,i||"y",!1,r,s),!r||null!=n&&null!=i?new c(n,i):null}function a(e,n,i,r,s){return n=t(e,n||"width",!1,r,s),i=t(e,i||"height",!1,r,s),!r||null!=n&&null!=i?new d(n,i):null}function o(t,e,n){return"none"===t?null:"number"===e?parseFloat(t):"array"===e?t?t.split(/[\s,]+/g).map(parseFloat):[]:"color"===e?k(t)||t:"lookup"===e?n[t]:t}function h(t,e,n,i){var r=t.childNodes,s="clippath"===e,a="defs"===e,o=new x,h=o._project,u=h._currentStyle,l=[];if(s||a||(o=b(o,t,i),h._currentStyle=o._style.clone()),i)for(var c=t.querySelectorAll("defs"),f=0,d=c.length;f<d;f++)P(c[f],n,!1);for(var f=0,d=r.length;f<d;f++){var _,g=r[f];1!==g.nodeType||/^defs$/i.test(g.nodeName)||!(_=P(g,n,!1))||_ instanceof I||l.push(_)}return o.addChildren(l),s&&(o=b(o.reduce(),t,i)),h._currentStyle=u,(s||a)&&(o.remove(),o=null),o}function u(t,e){for(var n=t.getAttribute("points").match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),i=[],r=0,s=n.length;r<s;r+=2)i.push(new c(parseFloat(n[r]),parseFloat(n[r+1])));var a=new E(i);return"polygon"===e&&a.closePath(),a}function l(t){return O.create(t.getAttribute("d"))}function f(e,n){var i,r=(t(e,"href",!0)||"").substring(1),a="radialgradient"===n;if(r)i=T[r].getGradient(),i._radial^a&&(i=i.clone(),i._radial=a);else{for(var o=e.childNodes,h=[],u=0,l=o.length;u<l;u++){var c=o[u];1===c.nodeType&&h.push(b(new q,c))}i=new R(h,a)}var f,d,_,g="userSpaceOnUse"!==t(e,"gradientUnits",!0);a?(f=s(e,"cx","cy",!1,g),d=f.add(t(e,"r",!1,!1,g),0),_=s(e,"fx","fy",!0,g)):(f=s(e,"x1","y1",!1,g),d=s(e,"x2","y2",!1,g));var v=b(new D(i,f,d,_),e);return v._scaleToBounds=g,null}function _(t,e,n,i){if(t.transform){for(var r=(i.getAttribute(n)||"").split(/\)\s*/g),s=new p,a=0,o=r.length;a<o;a++){var h=r[a];if(!h)break;for(var u=h.split(/\(\s*/),l=u[0],c=u[1].split(/[\s,]+/g),f=0,d=c.length;f<d;f++)c[f]=parseFloat(c[f]);switch(l){case"matrix":s.append(new p(c[0],c[1],c[2],c[3],c[4],c[5]));break;case"rotate":s.rotate(c[0],c[1],c[2]);break;case"translate":s.translate(c[0],c[1]);break;case"scale":s.scale(c);break;case"skewX":s.skew(c[0],0);break;case"skewY":s.skew(0,c[0])}}t.transform(s)}}function v(t,e,n){var i="fill-opacity"===n?"getFillColor":"getStrokeColor",r=t[i]&&t[i]();r&&r.setAlpha(parseFloat(e))}function m(t,n,i){var s=t.attributes[n],a=s&&s.value;if(!a){var o=r.camelize(n);a=t.style[o],a||i.node[o]===i.parent[o]||(a=i.node[o])}return a?"none"===a?null:a:e}function b(t,n,i){var s=n.parentNode,a={node:H.getStyles(n)||{},parent:!i&&!/^defs$/i.test(s.tagName)&&H.getStyles(s)||{}};return r.each(L,function(i,r){var s=m(n,r,a);t=s!==e&&i(t,s,r,n,a)||t;
-}),t}function k(t){var e=t&&t.match(/\((?:["'#]*)([^"')]+)/),i=e&&T[e[1].replace(n.location.href.split("#")[0]+"#","")];return i&&i._scaleToBounds&&(i=i.clone(),i._scaleToBounds=!0),i}function P(t,e,n){var s,o,h,u=t.nodeName.toLowerCase(),l="#document"!==u,c=i.body;n&&l&&(A=a(t,null,null,!0)||paper.getView().getSize(),s=nt.create("svg",{style:"stroke-width: 1px; stroke-miterlimit: 10"}),o=t.parentNode,h=t.nextSibling,s.appendChild(t),c.appendChild(s));var f=paper.settings,d=f.applyMatrix,_=f.insertItems;f.applyMatrix=!1,f.insertItems=!1;var g=z[u],v=g&&g(t,u,e,n)||null;if(f.insertItems=_,f.applyMatrix=d,v){!l||v instanceof x||(v=b(v,t,n));var p=e.onImport,m=l&&t.getAttribute("data-paper-data");p&&(v=p(t,v,e)||v),e.expandShapes&&v instanceof C&&(v.remove(),v=v.toPath()),m&&(v._data=JSON.parse(m))}return s&&(c.removeChild(s),o&&(h?o.insertBefore(t,h):o.appendChild(t))),n&&(T={},v&&r.pick(e.applyMatrix,d)&&v.matrix.apply(!0,!0)),v}function M(t,r,s){function a(i){try{var a="object"==typeof i?i:(new n.DOMParser).parseFromString(i,"image/svg+xml");if(!a.nodeName)throw a=null,new Error("Unsupported SVG source: "+t);paper=h,u=P(a,r,!0),r&&r.insert===!1||s._insertItem(e,u);var l=r.onLoad;l&&l(u,i)}catch(c){o(c)}}function o(t,e){var n=r.onError;if(!n)throw new Error(t);n(t,e)}if(!t)return null;r="function"==typeof r?{onLoad:r}:r||{};var h=paper,u=null;if("string"!=typeof t||/^.*</.test(t)){if("undefined"!=typeof File&&t instanceof File){var l=new FileReader;return l.onload=function(){a(l.result)},l.onerror=function(){o(l.error)},l.readAsText(t)}a(t)}else{var c=i.getElementById(t);c?a(c):Q.request({url:t,async:!0,onLoad:a,onError:o})}return u}var A,T={},z={"#document":function(t,e,n,i){for(var r=t.childNodes,s=0,a=r.length;s<a;s++){var o=r[s];if(1===o.nodeType)return P(o,n,i)}},g:h,svg:h,clippath:h,polygon:u,polyline:u,path:l,lineargradient:f,radialgradient:f,image:function(e){var n=new S(t(e,"href",!0));return n.on("load",function(){var t=a(e);this.setSize(t);var n=this._matrix._transformPoint(s(e).add(t.divide(2)));this.translate(n)}),n},symbol:function(t,e,n,i){return new I(h(t,e,n,i),(!0))},defs:h,use:function(e){var n=(t(e,"href",!0)||"").substring(1),i=T[n],r=s(e);return i?i instanceof I?i.place(r):i.clone().translate(r):null},circle:function(e){return new C.Circle(s(e,"cx","cy"),t(e,"r"))},ellipse:function(t){return new C.Ellipse({center:s(t,"cx","cy"),radius:a(t,"rx","ry")})},rect:function(t){return new C.Rectangle(new g(s(t),a(t)),a(t,"rx","ry"))},line:function(t){return new E.Line(s(t,"x1","y1"),s(t,"x2","y2"))},text:function(t){var e=new F(s(t).add(s(t,"dx","dy")));return e.setContent(t.textContent.trim()||""),e}},L=r.set(r.each(it,function(t){this[t.attribute]=function(e,n){if(e[t.set]&&(e[t.set](o(n,t.type,t.fromSVG)),"color"===t.type)){var i=e[t.get]();if(i){if(i._scaleToBounds){var r=e.getBounds();i.transform((new p).translate(r.getPoint()).scale(r.getSize()))}e instanceof C&&i.transform((new p).translate(e.getPosition(!0).negate()))}}}},{}),{id:function(t,e){T[e]=t,t.setName&&t.setName(e)},"clip-path":function(t,e){var n=k(e);if(n){if(n=n.clone(),n.setClipMask(!0),!(t instanceof x))return new x(n,t);t.insertChild(0,n)}},gradientTransform:_,transform:_,"fill-opacity":v,"stroke-opacity":v,visibility:function(t,e){t.setVisible&&t.setVisible("visible"===e)},display:function(t,e){t.setVisible&&t.setVisible(null!==e)},"stop-color":function(t,e){t.setColor&&t.setColor(e)},"stop-opacity":function(t,e){t._color&&t._color.setAlpha(parseFloat(e))},offset:function(t,e){if(t.setOffset){var n=e.match(/(.*)%$/);t.setOffset(n?n[1]/100:parseFloat(e))}},viewBox:function(t,e,n,i,r){var s,h,u=new g(o(e,"array")),l=a(i,null,null,!0);if(t instanceof x){var c=l?l.divide(u.getSize()):1,h=(new p).scale(c).translate(u.getPoint().negate());s=t}else t instanceof I&&(l&&u.setSize(l),s=t._item);if(s){if("visible"!==m(i,"overflow",r)){var f=new C.Rectangle(u);f.setClipMask(!0),s.addChild(f)}h&&s.transform(h)}}});w.inject({importSVG:function(t,e){return M(t,e,this)}}),y.inject({importSVG:function(t,e){return this.activate(),M(t,e,this)}})},r.exports.PaperScript=function(){function t(t,e,n){var i=p[e];if(t&&t[i]){var r=t[i](n);return"!="===e?!r:r}switch(e){case"+":return t+n;case"-":return t-n;case"*":return t*n;case"/":return t/n;case"%":return t%n;case"==":return t==n;case"!=":return t!=n}}function e(t,e){var n=m[t];if(n&&e&&e[n])return e[n]();switch(t){case"+":return+e;case"-":return-e}}function s(t,e){return v.acorn.parse(t,e)}function o(t,e){function r(t){for(var e=0,n=f.length;e<n;e++){var i=f[e];if(i[0]>=t)break;t+=i[1]}return t}function a(e){return t.substring(r(e.range[0]),r(e.range[1]))}function o(e,n){return t.substring(r(e.range[1]),r(n.range[0]))}function h(e,n){for(var i=r(e.range[0]),s=r(e.range[1]),a=0,o=f.length-1;o>=0;o--)if(i>f[o][0]){a=o+1;break}f.splice(a,0,[i,n.length-s+i]),t=t.substring(0,i)+n+t.substring(s)}function u(t,e){if(t){for(var n in t)if("range"!==n&&"loc"!==n){var i=t[n];if(Array.isArray(i))for(var r=0,s=i.length;r<s;r++)u(i[r],t);else i&&"object"==typeof i&&u(i,t)}switch(t.type){case"UnaryExpression":if(t.operator in m&&"Literal"!==t.argument.type){var l=a(t.argument);h(t,'$__("'+t.operator+'", '+l+")")}break;case"BinaryExpression":if(t.operator in p&&"Literal"!==t.left.type){var c=a(t.left),f=a(t.right),d=o(t.left,t.right),_=t.operator;h(t,"__$__("+c+","+d.replace(new RegExp("\\"+_),'"'+_+'"')+", "+f+")")}break;case"UpdateExpression":case"AssignmentExpression":var g=e&&e.type;if(!("ForStatement"===g||"BinaryExpression"===g&&/^[=!<>]/.test(e.operator)||"MemberExpression"===g&&e.computed))if("UpdateExpression"===t.type){var l=a(t.argument),v="__$__("+l+', "'+t.operator[0]+'", 1)',y=l+" = "+v;t.prefix||"AssignmentExpression"!==g&&"VariableDeclarator"!==g||(a(e.left||e.id)===l&&(y=v),y=l+"; "+y),h(t,y)}else if(/^.=$/.test(t.operator)&&"Literal"!==t.left.type){var c=a(t.left),f=a(t.right);h(t,c+" = __$__("+c+', "'+t.operator[0]+'", '+f+")")}}}}function l(t){var e="",n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(t=(Math.abs(t)<<1)+(t<0?1:0);t||!e;){var i=31&t;t>>=5,t&&(i|=32),e+=n[i]}return e}if(!t)return"";e=e||{};var c,f=[],d=e.url||"",_=paper.agent,g=_.versionNumber,v=!1,y=e.sourceMaps,w=e.source||t,x=/\r\n|\n|\r/gm,b=e.offset||0;if(y&&(_.chrome&&g>=30||_.webkit&&g>=537.76||_.firefox&&g>=23||_.node)){if(_.node)b-=2;else if(n&&d&&!n.location.href.indexOf(d)){var C=i.getElementsByTagName("html")[0].innerHTML;b=C.substr(0,C.indexOf(t)+1).match(x).length+1}v=b>0&&!(_.chrome&&g>=36||_.safari&&g>=600||_.firefox&&g>=40||_.node);var S=["AA"+l(v?0:b)+"A"];S.length=(t.match(x)||[]).length+1+(v?b:0),c={version:3,file:d,names:[],mappings:S.join(";AACA"),sourceRoot:"",sources:[d],sourcesContent:[w]}}return u(s(t,{ranges:!0})),c&&(v&&(t=new Array(b+1).join("\n")+t),/^(inline|both)$/.test(y)&&(t+="\n//# sourceMappingURL=data:application/json;base64,"+n.btoa(unescape(encodeURIComponent(JSON.stringify(c))))),t+="\n//# sourceURL="+(d||"paperscript")),{url:d,source:w,code:t,map:c}}function h(n,s,a){function h(t,e){for(var i in t)!e&&/^_/.test(i)||!new RegExp("([\\b\\s\\W]|^)"+i.replace(/\$/g,"\\$")+"\\b").test(n)||(g.push(i),v.push(t[i]))}paper=s;var u,l=s.getView(),f=/\btool\.\w+|\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\b/.test(n)&&!/\bnew\s+Tool\b/.test(n)?new K:null,d=f?f._events:[],_=["onFrame","onResize"].concat(d),g=[],v=[],p="object"==typeof n?n:o(n,a);n=p.code,h({__$__:t,$__:e,paper:s,view:l,tool:f},!0),h(s),_=r.each(_,function(t){new RegExp("\\s+"+t+"\\b").test(n)&&(g.push(t),this.push(t+": "+t))},[]).join(", "),_&&(n+="\nreturn { "+_+" };");var m=paper.agent;if(i&&(m.chrome||m.firefox&&m.versionNumber<40)){var y=i.createElement("script"),w=i.head||i.getElementsByTagName("head")[0];m.firefox&&(n="\n"+n),y.appendChild(i.createTextNode("paper._execute = function("+g+") {"+n+"\n}")),w.appendChild(y),u=paper._execute,delete paper._execute,w.removeChild(y)}else u=Function(g,n);var x=u.apply(s,v)||{};return r.each(d,function(t){var e=x[t];e&&(f[t]=e)}),l&&(x.onResize&&l.setOnResize(x.onResize),l.emit("resize",{size:l.size,delta:new c}),x.onFrame&&l.setOnFrame(x.onFrame),l.requestUpdate()),p}function u(t){if(/^text\/(?:x-|)paperscript$/.test(t.type)&&"true"!==a.getAttribute(t,"ignore")){var e=a.getAttribute(t,"canvas"),n=i.getElementById(e),r=t.src||t.getAttribute("data-src"),s=a.hasAttribute(t,"async"),o="data-paper-scope";if(!n)throw new Error('Unable to find canvas with id "'+e+'"');var u=a.get(n.getAttribute(o))||(new a).setup(n);return n.setAttribute(o,u._id),r?Q.request({url:r,async:s,mimeType:"text/plain",onLoad:function(t){h(t,u,r)}}):h(t.innerHTML,u,t.baseURI),t.setAttribute("data-paper-ignore","true"),u}}function l(){r.each(i&&i.getElementsByTagName("script"),u)}function f(t){return t?u(t):l()}var _,g,v=this;!function(t,e){return"object"==typeof _&&"object"==typeof module?e(_):"function"==typeof g&&g.amd?g(["exports"],e):void e(t.acorn||(t.acorn={}))}(this,function(t){"use strict";function e(t){ct=t||{};for(var e in gt)Object.prototype.hasOwnProperty.call(ct,e)||(ct[e]=gt[e]);_t=ct.sourceFile||null}function n(t,e){var n=vt(ft,t);e+=" ("+n.line+":"+n.column+")";var i=new SyntaxError(e);throw i.pos=t,i.loc=n,i.raisedAt=pt,i}function i(t){function e(t){if(1==t.length)return n+="return str === "+JSON.stringify(t[0])+";";n+="switch(str){";for(var e=0;e<t.length;++e)n+="case "+JSON.stringify(t[e])+":";n+="return true}return false;"}t=t.split(" ");var n="",i=[];t:for(var r=0;r<t.length;++r){for(var s=0;s<i.length;++s)if(i[s][0].length==t[r].length){i[s].push(t[r]);continue t}i.push([t[r]])}if(i.length>3){i.sort(function(t,e){return e.length-t.length}),n+="switch(str.length){";for(var r=0;r<i.length;++r){var a=i[r];n+="case "+a[0].length+":",e(a)}n+="}"}else e(t);return new Function("str",n)}function r(){this.line=kt,this.column=pt-It}function s(){kt=1,pt=It=0,St=!0,u()}function a(t,e){yt=pt,ct.locations&&(xt=new r),bt=t,u(),Ct=e,St=t.beforeExpr}function o(){var t=ct.onComment&&ct.locations&&new r,e=pt,i=ft.indexOf("*/",pt+=2);if(-1===i&&n(pt-2,"Unterminated comment"),pt=i+2,ct.locations){Xe.lastIndex=e;for(var s;(s=Xe.exec(ft))&&s.index<pt;)++kt,It=s.index+s[0].length}ct.onComment&&ct.onComment(!0,ft.slice(e+2,i),e,pt,t,ct.locations&&new r)}function h(){for(var t=pt,e=ct.onComment&&ct.locations&&new r,n=ft.charCodeAt(pt+=2);dt>pt&&10!==n&&13!==n&&8232!==n&&8233!==n;)++pt,n=ft.charCodeAt(pt);ct.onComment&&ct.onComment(!1,ft.slice(t+2,pt),t,pt,e,ct.locations&&new r)}function u(){for(;dt>pt;){var t=ft.charCodeAt(pt);if(32===t)++pt;else if(13===t){++pt;var e=ft.charCodeAt(pt);10===e&&++pt,ct.locations&&(++kt,It=pt)}else if(10===t||8232===t||8233===t)++pt,ct.locations&&(++kt,It=pt);else if(t>8&&14>t)++pt;else if(47===t){var e=ft.charCodeAt(pt+1);if(42===e)o();else{if(47!==e)break;h()}}else if(160===t)++pt;else{if(!(t>=5760&&Ue.test(String.fromCharCode(t))))break;++pt}}}function l(){var t=ft.charCodeAt(pt+1);return t>=48&&57>=t?S(!0):(++pt,a(we))}function c(){var t=ft.charCodeAt(pt+1);return St?(++pt,x()):61===t?w(Se,2):w(be,1)}function f(){var t=ft.charCodeAt(pt+1);return 61===t?w(Se,2):w(Be,1)}function d(t){var e=ft.charCodeAt(pt+1);return e===t?w(124===t?Pe:Me,2):61===e?w(Se,2):w(124===t?Ae:ze,1)}function _(){var t=ft.charCodeAt(pt+1);return 61===t?w(Se,2):w(Te,1)}function g(t){var e=ft.charCodeAt(pt+1);return e===t?45==e&&62==ft.charCodeAt(pt+2)&&Je.test(ft.slice(Mt,pt))?(pt+=3,h(),u(),y()):w(ke,2):61===e?w(Se,2):w(Ne,1)}function v(t){var e=ft.charCodeAt(pt+1),n=1;return e===t?(n=62===t&&62===ft.charCodeAt(pt+2)?3:2,61===ft.charCodeAt(pt+n)?w(Se,n+1):w(Le,n)):33==e&&60==t&&45==ft.charCodeAt(pt+2)&&45==ft.charCodeAt(pt+3)?(pt+=4,h(),u(),y()):(61===e&&(n=61===ft.charCodeAt(pt+2)?3:2),w(Ee,n))}function p(t){var e=ft.charCodeAt(pt+1);return 61===e?w(Oe,61===ft.charCodeAt(pt+2)?3:2):w(61===t?Ce:Ie,1)}function m(t){switch(t){case 46:return l();case 40:return++pt,a(ge);case 41:return++pt,a(ve);case 59:return++pt,a(me);case 44:return++pt,a(pe);case 91:return++pt,a(ce);case 93:return++pt,a(fe);case 123:return++pt,a(de);case 125:return++pt,a(_e);case 58:return++pt,a(ye);case 63:return++pt,a(xe);case 48:var e=ft.charCodeAt(pt+1);if(120===e||88===e)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return S(!1);case 34:case 39:return k(t);case 47:return c(t);case 37:case 42:return f();case 124:case 38:return d(t);case 94:return _();case 43:case 45:return g(t);case 60:case 62:return v(t);case 61:case 33:return p(t);case 126:return w(Ie,1)}return!1}function y(t){if(t?pt=mt+1:mt=pt,ct.locations&&(wt=new r),t)return x();if(pt>=dt)return a(Ft);var e=ft.charCodeAt(pt);if(Ye(e)||92===e)return M();var i=m(e);if(i===!1){var s=String.fromCharCode(e);if("\\"===s||Ge.test(s))return M();n(pt,"Unexpected character '"+s+"'")}return i}function w(t,e){var n=ft.slice(pt,pt+e);pt+=e,a(t,n)}function x(){for(var t,e,i="",r=pt;;){pt>=dt&&n(r,"Unterminated regular expression");var s=ft.charAt(pt);if(Je.test(s)&&n(r,"Unterminated regular expression"),t)t=!1;else{if("["===s)e=!0;else if("]"===s&&e)e=!1;else if("/"===s&&!e)break;t="\\"===s}++pt}var i=ft.slice(r,pt);++pt;var o=P();o&&!/^[gmsiy]*$/.test(o)&&n(r,"Invalid regexp flag");try{var h=new RegExp(i,o)}catch(u){u instanceof SyntaxError&&n(r,u.message),n(u)}return a(Nt,h)}function b(t,e){for(var n=pt,i=0,r=0,s=null==e?1/0:e;s>r;++r){var a,o=ft.charCodeAt(pt);if(a=o>=97?o-97+10:o>=65?o-65+10:o>=48&&57>=o?o-48:1/0,a>=t)break;++pt,i=i*t+a}return pt===n||null!=e&&pt-n!==e?null:i}function C(){pt+=2;var t=b(16);return null==t&&n(mt+2,"Expected hexadecimal number"),Ye(ft.charCodeAt(pt))&&n(pt,"Identifier directly after number"),a(Lt,t)}function S(t){var e=pt,i=!1,r=48===ft.charCodeAt(pt);t||null!==b(10)||n(e,"Invalid number"),46===ft.charCodeAt(pt)&&(++pt,b(10),i=!0);var s=ft.charCodeAt(pt);69!==s&&101!==s||(s=ft.charCodeAt(++pt),43!==s&&45!==s||++pt,null===b(10)&&n(e,"Invalid number"),i=!0),Ye(ft.charCodeAt(pt))&&n(pt,"Identifier directly after number");var o,h=ft.slice(e,pt);return i?o=parseFloat(h):r&&1!==h.length?/[89]/.test(h)||Ot?n(e,"Invalid number"):o=parseInt(h,8):o=parseInt(h,10),a(Lt,o)}function k(t){pt++;for(var e="";;){pt>=dt&&n(mt,"Unterminated string constant");var i=ft.charCodeAt(pt);if(i===t)return++pt,a(Bt,e);if(92===i){i=ft.charCodeAt(++pt);var r=/^[0-7]+/.exec(ft.slice(pt,pt+3));for(r&&(r=r[0]);r&&parseInt(r,8)>255;)r=r.slice(0,-1);if("0"===r&&(r=null),++pt,r)Ot&&n(pt-2,"Octal literal in strict mode"),e+=String.fromCharCode(parseInt(r,8)),pt+=r.length-1;else switch(i){case 110:e+="\n";break;case 114:e+="\r";break;case 120:e+=String.fromCharCode(I(2));break;case 117:e+=String.fromCharCode(I(4));break;case 85:e+=String.fromCharCode(I(8));break;case 116:e+="\t";break;case 98:e+="\b";break;case 118:e+="\x0B";break;case 102:e+="\f";break;case 48:e+="\0";break;case 13:10===ft.charCodeAt(pt)&&++pt;case 10:ct.locations&&(It=pt,++kt);break;default:e+=String.fromCharCode(i)}}else 13!==i&&10!==i&&8232!==i&&8233!==i||n(mt,"Unterminated string constant"),e+=String.fromCharCode(i),++pt}}function I(t){var e=b(16,t);return null===e&&n(mt,"Bad character escape sequence"),e}function P(){Fe=!1;for(var t,e=!0,i=pt;;){var r=ft.charCodeAt(pt);if(Ke(r))Fe&&(t+=ft.charAt(pt)),++pt;else{if(92!==r)break;Fe||(t=ft.slice(i,pt)),Fe=!0,117!=ft.charCodeAt(++pt)&&n(pt,"Expecting Unicode escape sequence \\uXXXX"),++pt;var s=I(4),a=String.fromCharCode(s);a||n(pt-1,"Invalid Unicode escape"),(e?Ye(s):Ke(s))||n(pt-4,"Invalid Unicode escape"),t+=a}e=!1}return Fe?t:ft.slice(i,pt)}function M(){var t=P(),e=jt;return!Fe&&He(t)&&(e=le[t]),a(e,t)}function A(){Pt=mt,Mt=yt,At=xt,y()}function T(t){if(Ot=t,pt=mt,ct.locations)for(;It>pt;)It=ft.lastIndexOf("\n",It-2)+1,--kt;u(),y()}function z(){this.type=null,this.start=mt,this.end=null}function O(){this.start=wt,this.end=null,null!==_t&&(this.source=_t)}function E(){var t=new z;return ct.locations&&(t.loc=new O),ct.directSourceFile&&(t.sourceFile=ct.directSourceFile),ct.ranges&&(t.range=[mt,0]),t}function L(t){var e=new z;return e.start=t.start,ct.locations&&(e.loc=new O,e.loc.start=t.loc.start),ct.ranges&&(e.range=[t.range[0],0]),e}function N(t,e){return t.type=e,t.end=Mt,ct.locations&&(t.loc.end=At),ct.ranges&&(t.range[1]=Mt),t}function B(t){return ct.ecmaVersion>=5&&"ExpressionStatement"===t.type&&"Literal"===t.expression.type&&"use strict"===t.expression.value}function j(t){return bt===t?(A(),!0):void 0}function F(){return!ct.strictSemicolons&&(bt===Ft||bt===_e||Je.test(ft.slice(Mt,mt)))}function D(){j(me)||F()||q()}function R(t){bt===t?A():q()}function q(){n(mt,"Unexpected token")}function V(t){"Identifier"!==t.type&&"MemberExpression"!==t.type&&n(t.start,"Assigning to rvalue"),Ot&&"Identifier"===t.type&&Ve(t.name)&&n(t.start,"Assigning to "+t.name+" in strict mode")}function H(t){Pt=Mt=pt,ct.locations&&(At=new r),Tt=Ot=null,zt=[],y();var e=t||E(),n=!0;for(t||(e.body=[]);bt!==Ft;){var i=U();e.body.push(i),n&&B(i)&&T(!0),n=!1}return N(e,"Program")}function U(){(bt===be||bt===Se&&"/="==Ct)&&y(!0);var t=bt,e=E();switch(t){case Dt:case Vt:A();var i=t===Dt;j(me)||F()?e.label=null:bt!==jt?q():(e.label=lt(),D());for(var r=0;r<zt.length;++r){var s=zt[r];if(null==e.label||s.name===e.label.name){if(null!=s.kind&&(i||"loop"===s.kind))break;if(e.label&&i)break}}return r===zt.length&&n(e.start,"Unsyntactic "+t.keyword),N(e,i?"BreakStatement":"ContinueStatement");case Ht:return A(),D(),N(e,"DebuggerStatement");case Zt:return A(),zt.push(Qe),e.body=U(),zt.pop(),R(ne),e.test=Z(),D(),N(e,"DoWhileStatement");case $t:if(A(),zt.push(Qe),R(ge),bt===me)return G(e,null);if(bt===ee){var a=E();return A(),J(a,!0),N(a,"VariableDeclaration"),1===a.declarations.length&&j(ue)?$(e,a):G(e,a)}var a=X(!1,!0);return j(ue)?(V(a),$(e,a)):G(e,a);case Jt:return A(),ht(e,!0);case Xt:return A(),e.test=Z(),e.consequent=U(),e.alternate=j(Wt)?U():null,N(e,"IfStatement");case Yt:return Tt||ct.allowReturnOutsideFunction||n(mt,"'return' outside of function"),A(),j(me)||F()?e.argument=null:(e.argument=X(),D()),N(e,"ReturnStatement");case Kt:A(),e.discriminant=Z(),e.cases=[],R(de),zt.push(tn);for(var o,h;bt!=_e;)if(bt===Rt||bt===Ut){var u=bt===Rt;o&&N(o,"SwitchCase"),e.cases.push(o=E()),o.consequent=[],A(),u?o.test=X():(h&&n(Pt,"Multiple default clauses"),h=!0,o.test=null),R(ye)}else o||q(),o.consequent.push(U());return o&&N(o,"SwitchCase"),A(),zt.pop(),N(e,"SwitchStatement");case Qt:return A(),Je.test(ft.slice(Mt,mt))&&n(Mt,"Illegal newline after throw"),e.argument=X(),D(),N(e,"ThrowStatement");case te:if(A(),e.block=W(),e.handler=null,bt===qt){var l=E();A(),R(ge),l.param=lt(),Ot&&Ve(l.param.name)&&n(l.param.start,"Binding "+l.param.name+" in strict mode"),R(ve),l.guard=null,l.body=W(),e.handler=N(l,"CatchClause")}return e.guardedHandlers=Et,e.finalizer=j(Gt)?W():null,e.handler||e.finalizer||n(e.start,"Missing catch or finally clause"),N(e,"TryStatement");case ee:return A(),J(e),D(),N(e,"VariableDeclaration");case ne:return A(),e.test=Z(),zt.push(Qe),e.body=U(),zt.pop(),N(e,"WhileStatement");case ie:return Ot&&n(mt,"'with' in strict mode"),A(),e.object=Z(),e.body=U(),N(e,"WithStatement");case de:return W();case me:return A(),N(e,"EmptyStatement");default:var c=Ct,f=X();if(t===jt&&"Identifier"===f.type&&j(ye)){for(var r=0;r<zt.length;++r)zt[r].name===c&&n(f.start,"Label '"+c+"' is already declared");var d=bt.isLoop?"loop":bt===Kt?"switch":null;return zt.push({name:c,kind:d}),e.body=U(),zt.pop(),e.label=f,N(e,"LabeledStatement")}return e.expression=f,D(),N(e,"ExpressionStatement")}}function Z(){R(ge);var t=X();return R(ve),t}function W(t){var e,n=E(),i=!0,r=!1;for(n.body=[],R(de);!j(_e);){var s=U();n.body.push(s),i&&t&&B(s)&&(e=r,T(r=!0)),i=!1}return r&&!e&&T(!1),N(n,"BlockStatement")}function G(t,e){return t.init=e,R(me),t.test=bt===me?null:X(),R(me),t.update=bt===ve?null:X(),R(ve),t.body=U(),zt.pop(),N(t,"ForStatement")}function $(t,e){return t.left=e,t.right=X(),R(ve),t.body=U(),zt.pop(),N(t,"ForInStatement")}function J(t,e){for(t.declarations=[],t.kind="var";;){var i=E();if(i.id=lt(),Ot&&Ve(i.id.name)&&n(i.id.start,"Binding "+i.id.name+" in strict mode"),i.init=j(Ce)?X(!0,e):null,t.declarations.push(N(i,"VariableDeclarator")),!j(pe))break}return t}function X(t,e){var n=Y(e);if(!t&&bt===pe){var i=L(n);for(i.expressions=[n];j(pe);)i.expressions.push(Y(e));return N(i,"SequenceExpression")}return n}function Y(t){var e=K(t);if(bt.isAssign){var n=L(e);return n.operator=Ct,n.left=e,A(),n.right=Y(t),V(e),N(n,"AssignmentExpression")}return e}function K(t){var e=Q(t);if(j(xe)){var n=L(e);return n.test=e,n.consequent=X(!0),R(ye),n.alternate=X(!0,t),N(n,"ConditionalExpression")}return e}function Q(t){return tt(et(),-1,t)}function tt(t,e,n){var i=bt.binop;if(null!=i&&(!n||bt!==ue)&&i>e){var r=L(t);r.left=t,r.operator=Ct;var s=bt;A(),r.right=tt(et(),i,n);var a=N(r,s===Pe||s===Me?"LogicalExpression":"BinaryExpression");return tt(a,e,n)}return t}function et(){if(bt.prefix){var t=E(),e=bt.isUpdate;return t.operator=Ct,t.prefix=!0,St=!0,A(),t.argument=et(),e?V(t.argument):Ot&&"delete"===t.operator&&"Identifier"===t.argument.type&&n(t.start,"Deleting local variable in strict mode"),N(t,e?"UpdateExpression":"UnaryExpression")}for(var i=nt();bt.postfix&&!F();){var t=L(i);t.operator=Ct,t.prefix=!1,t.argument=i,V(i),A(),i=N(t,"UpdateExpression")}return i}function nt(){return it(rt())}function it(t,e){if(j(we)){var n=L(t);return n.object=t,n.property=lt(!0),n.computed=!1,it(N(n,"MemberExpression"),e)}if(j(ce)){var n=L(t);return n.object=t,n.property=X(),n.computed=!0,R(fe),it(N(n,"MemberExpression"),e)}if(!e&&j(ge)){var n=L(t);return n.callee=t,n.arguments=ut(ve,!1),it(N(n,"CallExpression"),e)}return t}function rt(){switch(bt){case se:var t=E();return A(),N(t,"ThisExpression");case jt:return lt();case Lt:case Bt:case Nt:var t=E();return t.value=Ct,t.raw=ft.slice(mt,yt),A(),N(t,"Literal");case ae:case oe:case he:var t=E();return t.value=bt.atomValue,t.raw=bt.keyword,A(),N(t,"Literal");case ge:var e=wt,n=mt;A();var i=X();return i.start=n,i.end=yt,ct.locations&&(i.loc.start=e,i.loc.end=xt),ct.ranges&&(i.range=[n,yt]),R(ve),i;case ce:var t=E();return A(),t.elements=ut(fe,!0,!0),N(t,"ArrayExpression");case de:return at();case Jt:var t=E();return A(),ht(t,!1);case re:return st();default:q()}}function st(){var t=E();return A(),t.callee=it(rt(),!0),j(ge)?t.arguments=ut(ve,!1):t.arguments=Et,N(t,"NewExpression")}function at(){var t=E(),e=!0,i=!1;for(t.properties=[],A();!j(_e);){if(e)e=!1;else if(R(pe),ct.allowTrailingCommas&&j(_e))break;var r,s={key:ot()},a=!1;if(j(ye)?(s.value=X(!0),r=s.kind="init"):ct.ecmaVersion>=5&&"Identifier"===s.key.type&&("get"===s.key.name||"set"===s.key.name)?(a=i=!0,r=s.kind=s.key.name,s.key=ot(),bt!==ge&&q(),s.value=ht(E(),!1)):q(),"Identifier"===s.key.type&&(Ot||i))for(var o=0;o<t.properties.length;++o){var h=t.properties[o];if(h.key.name===s.key.name){var u=r==h.kind||a&&"init"===h.kind||"init"===r&&("get"===h.kind||"set"===h.kind);u&&!Ot&&"init"===r&&"init"===h.kind&&(u=!1),u&&n(s.key.start,"Redefinition of property")}}t.properties.push(s)}return N(t,"ObjectExpression")}function ot(){return bt===Lt||bt===Bt?rt():lt(!0)}function ht(t,e){bt===jt?t.id=lt():e?q():t.id=null,t.params=[];var i=!0;for(R(ge);!j(ve);)i?i=!1:R(pe),t.params.push(lt());var r=Tt,s=zt;if(Tt=!0,zt=[],t.body=W(!0),Tt=r,zt=s,Ot||t.body.body.length&&B(t.body.body[0]))for(var a=t.id?-1:0;a<t.params.length;++a){var o=0>a?t.id:t.params[a];if((qe(o.name)||Ve(o.name))&&n(o.start,"Defining '"+o.name+"' in strict mode"),a>=0)for(var h=0;a>h;++h)o.name===t.params[h].name&&n(o.start,"Argument name clash in strict mode")}return N(t,e?"FunctionDeclaration":"FunctionExpression")}function ut(t,e,n){for(var i=[],r=!0;!j(t);){if(r)r=!1;else if(R(pe),e&&ct.allowTrailingCommas&&j(t))break;n&&bt===pe?i.push(null):i.push(X(!0))}return i}function lt(t){var e=E();return t&&"everywhere"==ct.forbidReserved&&(t=!1),bt===jt?(!t&&(ct.forbidReserved&&(3===ct.ecmaVersion?De:Re)(Ct)||Ot&&qe(Ct))&&-1==ft.slice(mt,yt).indexOf("\\")&&n(mt,"The keyword '"+Ct+"' is reserved"),e.name=Ct):t&&bt.keyword?e.name=bt.keyword:q(),St=!1,A(),N(e,"Identifier")}t.version="0.5.0";var ct,ft,dt,_t;t.parse=function(t,n){return ft=String(t),dt=ft.length,e(n),s(),H(ct.program)};var gt=t.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,allowReturnOutsideFunction:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null},vt=t.getLineInfo=function(t,e){for(var n=1,i=0;;){Xe.lastIndex=i;var r=Xe.exec(t);if(!(r&&r.index<e))break;++n,i=r.index+r[0].length}return{line:n,column:e-i}};t.tokenize=function(t,n){function i(t){return Mt=yt,y(t),r.start=mt,r.end=yt,r.startLoc=wt,r.endLoc=xt,r.type=bt,r.value=Ct,r}ft=String(t),dt=ft.length,e(n),s();var r={};return i.jumpTo=function(t,e){if(pt=t,ct.locations){kt=1,It=Xe.lastIndex=0;for(var n;(n=Xe.exec(ft))&&n.index<t;)++kt,It=n.index+n[0].length}St=e,u()},i};var pt,mt,yt,wt,xt,bt,Ct,St,kt,It,Pt,Mt,At,Tt,zt,Ot,Et=[],Lt={type:"num"},Nt={type:"regexp"},Bt={type:"string"},jt={type:"name"},Ft={type:"eof"},Dt={keyword:"break"},Rt={keyword:"case",beforeExpr:!0},qt={keyword:"catch"},Vt={keyword:"continue"},Ht={keyword:"debugger"},Ut={keyword:"default"},Zt={keyword:"do",isLoop:!0},Wt={keyword:"else",beforeExpr:!0},Gt={keyword:"finally"},$t={keyword:"for",isLoop:!0},Jt={keyword:"function"},Xt={keyword:"if"},Yt={keyword:"return",beforeExpr:!0},Kt={keyword:"switch"},Qt={keyword:"throw",beforeExpr:!0},te={keyword:"try"},ee={keyword:"var"},ne={keyword:"while",isLoop:!0},ie={keyword:"with"},re={keyword:"new",beforeExpr:!0},se={keyword:"this"},ae={keyword:"null",atomValue:null},oe={keyword:"true",atomValue:!0},he={keyword:"false",atomValue:!1},ue={keyword:"in",binop:7,beforeExpr:!0},le={"break":Dt,"case":Rt,"catch":qt,"continue":Vt,"debugger":Ht,"default":Ut,"do":Zt,"else":Wt,"finally":Gt,"for":$t,"function":Jt,"if":Xt,"return":Yt,"switch":Kt,"throw":Qt,"try":te,"var":ee,"while":ne,"with":ie,"null":ae,"true":oe,"false":he,"new":re,"in":ue,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":se,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},ce={type:"[",beforeExpr:!0},fe={type:"]"},de={type:"{",beforeExpr:!0},_e={type:"}"},ge={type:"(",beforeExpr:!0},ve={type:")"},pe={type:",",beforeExpr:!0},me={type:";",beforeExpr:!0},ye={type:":",beforeExpr:!0},we={type:"."},xe={type:"?",beforeExpr:!0},be={binop:10,beforeExpr:!0},Ce={isAssign:!0,beforeExpr:!0},Se={isAssign:!0,beforeExpr:!0},ke={postfix:!0,prefix:!0,isUpdate:!0},Ie={prefix:!0,beforeExpr:!0},Pe={binop:1,beforeExpr:!0},Me={binop:2,beforeExpr:!0},Ae={binop:3,beforeExpr:!0},Te={binop:4,beforeExpr:!0},ze={binop:5,beforeExpr:!0},Oe={binop:6,beforeExpr:!0},Ee={binop:7,beforeExpr:!0},Le={binop:8,beforeExpr:!0},Ne={binop:9,prefix:!0,beforeExpr:!0},Be={binop:10,beforeExpr:!0};t.tokTypes={bracketL:ce,bracketR:fe,braceL:de,braceR:_e,parenL:ge,parenR:ve,comma:pe,semi:me,colon:ye,dot:we,question:xe,slash:be,eq:Ce,name:jt,eof:Ft,num:Lt,regexp:Nt,string:Bt};for(var je in le)t.tokTypes["_"+je]=le[je];var Fe,De=i("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),Re=i("class enum extends super const export import"),qe=i("implements interface let package private protected public static yield"),Ve=i("eval arguments"),He=i("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Ue=/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/,Ze="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",We="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",Ge=new RegExp("["+Ze+"]"),$e=new RegExp("["+Ze+We+"]"),Je=/[\n\r\u2028\u2029]/,Xe=/\r\n|[\n\r\u2028\u2029]/g,Ye=t.isIdentifierStart=function(t){
-return 65>t?36===t:91>t||(97>t?95===t:123>t||t>=170&&Ge.test(String.fromCharCode(t)))},Ke=t.isIdentifierChar=function(t){return 48>t?36===t:58>t||!(65>t)&&(91>t||(97>t?95===t:123>t||t>=170&&$e.test(String.fromCharCode(t))))},Qe={kind:"loop"},tn={kind:"switch"}});var p={"+":"__add","-":"__subtract","*":"__multiply","/":"__divide","%":"__modulo","==":"__equals","!=":"__equals"},m={"-":"__negate","+":null},y=r.each(["add","subtract","multiply","divide","modulo","equals","negate"],function(t){this["__"+t]="#"+t},{});return c.inject(y),d.inject(y),D.inject(y),n&&("complete"===i.readyState?setTimeout(l):U.add(n,{load:l})),{compile:o,execute:h,load:f,parse:s}}.call(this),paper=new(a.inject(r.exports,{enumerable:!0,Base:r,Numerical:u,Key:J,DomEvent:U,DomElement:H,document:i,window:n,Symbol:I,PlacedSymbol:k})),paper.agent.node&&require("./node/extend")(paper),"function"==typeof define&&define.amd?define("paper",paper):"object"==typeof module&&module&&(module.exports=paper),paper}.call(this,"object"==typeof self?self:null);
\ No newline at end of file

From 6154b44d68f99194e3e17da600247b176fe9df81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 21:20:47 +0200
Subject: [PATCH 45/58] Gulp: Cleanup publish task.

---
 gulp/tasks/publish.js | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/gulp/tasks/publish.js b/gulp/tasks/publish.js
index 376e404c..cd58e99c 100644
--- a/gulp/tasks/publish.js
+++ b/gulp/tasks/publish.js
@@ -31,8 +31,8 @@ gulp.task('publish', function() {
 });
 
 gulp.task('publish:version', function() {
-    // Since we're executing this on the develop branch but we don't wan the
-    // version suffixed, reset the version value again.
+    // reset the version value since we're executing this on the develop branch,
+    // but we don't wan the published version suffixed with '-develop'.
     options.resetVersion();
     return gulp.src([ 'package.json', 'component.json' ])
         .pipe(bump({ version: options.version }))
@@ -44,6 +44,7 @@ gulp.task('publish:dist', ['dist']);
 gulp.task('publish:commit', function() {
     var message = 'Release version ' + options.version;
     return gulp.src('.')
+        .pipe(git.checkout('develop'))
         .pipe(git.add())
         .pipe(git.commit(message))
         .pipe(git.tag('v' + options.version, message));
@@ -54,12 +55,12 @@ gulp.task('publish:release', function() {
         .pipe(git.checkout('master'))
         .pipe(git.merge('develop', { args: '-X theirs' }))
         .pipe(git.push('origin', ['master', 'develop'], { args: '--tags' }))
-        .pipe(shell('npm publish'))
-        .pipe(git.checkout('develop'));
+        .pipe(shell('npm publish'));
 });
 
 gulp.task('publish:load', ['load'], function() {
     return gulp.src('dist')
+        .pipe(git.checkout('develop'))
         .pipe(git.add())
         .pipe(git.commit('Switch back to load.js versions on develop branch.'))
         .pipe(git.push('origin', 'develop'));

From bf2eada11c6d235ea1b13f56104a5f7213fc8f6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 21:31:25 +0200
Subject: [PATCH 46/58] Remove component.json and clean up package files a bit.

Component is not maintained anymore, per https://github.com/componentjs/component/issues/639
---
 bower.json            |  4 ++--
 component.json        | 34 ----------------------------------
 gulp/tasks/publish.js |  2 +-
 package.json          |  1 +
 4 files changed, 4 insertions(+), 37 deletions(-)
 delete mode 100644 component.json

diff --git a/bower.json b/bower.json
index 7be82ba4..782f4801 100644
--- a/bower.json
+++ b/bower.json
@@ -14,10 +14,10 @@
   ],
   "main": "dist/paper-full.js",
   "ignore": [
-    "build",
+    "package.json",
+    "gulpfile.js",
     "gulp",
     "node_modules",
-    "package.json",
     "projects",
     "src",
     "test",
diff --git a/component.json b/component.json
deleted file mode 100644
index c48eed0c..00000000
--- a/component.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "name": "paper",
-  "version": "0.10.2",
-  "description": "The Swiss Army Knife of Vector Graphics Scripting",
-  "license": "MIT",
-  "repo": "paperjs/paper.js",
-  "main": [
-    "dist/paper-full.js"
-  ],
-  "scripts": [
-    "dist/paper-full.js"
-  ],
-  "files": [
-    "AUTHORS.md",
-    "LICENSE.txt",
-    "README.md"
-  ],
-  "keywords": [
-    "vector",
-    "graphic",
-    "graphics",
-    "2d",
-    "geometry",
-    "bezier",
-    "curve",
-    "curves",
-    "path",
-    "paths",
-    "canvas",
-    "svg",
-    "paper",
-    "paper.js"
-  ]
-}
diff --git a/gulp/tasks/publish.js b/gulp/tasks/publish.js
index cd58e99c..b31ce172 100644
--- a/gulp/tasks/publish.js
+++ b/gulp/tasks/publish.js
@@ -34,7 +34,7 @@ gulp.task('publish:version', function() {
     // reset the version value since we're executing this on the develop branch,
     // but we don't wan the published version suffixed with '-develop'.
     options.resetVersion();
-    return gulp.src([ 'package.json', 'component.json' ])
+    return gulp.src([ 'package.json' ])
         .pipe(bump({ version: options.version }))
         .pipe(gulp.dest('.'));
 });
diff --git a/package.json b/package.json
index 75c2710c..d976af33 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
   },
   "files": [
     "AUTHORS.md",
+    "CHANGELOG.md",
     "dist/",
     "examples/",
     "LICENSE.txt",

From a14e1e4c97d07fc516c78929931c393a12304545 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 23:36:11 +0200
Subject: [PATCH 47/58] Replace extend() with Object.assign()

---
 gulp/tasks/build.js   | 3 +--
 gulp/utils/options.js | 1 -
 package.json          | 1 -
 3 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/gulp/tasks/build.js b/gulp/tasks/build.js
index 7fb687e5..e3a55158 100644
--- a/gulp/tasks/build.js
+++ b/gulp/tasks/build.js
@@ -16,7 +16,6 @@ var gulp = require('gulp'),
     uncomment = require('gulp-uncomment'),
     whitespace = require('gulp-whitespace'),
     del = require('del'),
-    extend = require('extend'),
     options = require('../utils/options.js');
 
 // Options to be used in Prepro.js preprocessing through the global __options
@@ -51,7 +50,7 @@ buildNames.forEach(function(name) {
                     // Note that this would be merge in with already existing
                     // objects.
                     return {
-                        __options: extend({}, options, buildOptions[name])
+                        __options: Object.assign({}, options, buildOptions[name])
                     };
                 }
             }))
diff --git a/gulp/utils/options.js b/gulp/utils/options.js
index 7773e863..bfd3763e 100644
--- a/gulp/utils/options.js
+++ b/gulp/utils/options.js
@@ -11,7 +11,6 @@
  */
 
 var execSync = require('child_process').execSync,
-    extend = require('extend'),
     // Require the __options object, so we have access to the version number and
     // make amendments, e.g. the release date.
     options = require('../../src/options.js');
diff --git a/package.json b/package.json
index d976af33..36da3c7b 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,6 @@
   "devDependencies": {
     "acorn": "~0.5.0",
     "del": "^2.2.1",
-    "extend": "^3.0.0",
     "gulp": "^3.9.1",
     "gulp-bump": "^2.2.0",
     "gulp-cached": "^1.1.0",

From 4df2dfb34366405502a10e37269f92560564bc73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sat, 9 Jul 2016 23:49:11 +0200
Subject: [PATCH 48/58] No need for npm prepublish now that we have the gulp
 publish task.

---
 gulp/tasks/publish.js | 2 +-
 gulp/tasks/test.js    | 2 +-
 package.json          | 1 -
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/gulp/tasks/publish.js b/gulp/tasks/publish.js
index b31ce172..5ddbe2fb 100644
--- a/gulp/tasks/publish.js
+++ b/gulp/tasks/publish.js
@@ -31,7 +31,7 @@ gulp.task('publish', function() {
 });
 
 gulp.task('publish:version', function() {
-    // reset the version value since we're executing this on the develop branch,
+    // Reset the version value since we're executing this on the develop branch,
     // but we don't wan the published version suffixed with '-develop'.
     options.resetVersion();
     return gulp.src([ 'package.json' ])
diff --git a/gulp/tasks/test.js b/gulp/tasks/test.js
index 22ebb275..79f1adbb 100644
--- a/gulp/tasks/test.js
+++ b/gulp/tasks/test.js
@@ -11,8 +11,8 @@
  */
 
 var gulp = require('gulp'),
-    qunits = require('gulp-qunits'),
     gutil = require('gulp-util'),
+    qunits = require('gulp-qunits'),
     webserver = require('gulp-webserver');
 
 gulp.task('test', ['test:phantom', 'test:node']);
diff --git a/package.json b/package.json
index 36da3c7b..dcfd0af4 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,6 @@
   ],
   "main": "dist/paper-full.js",
   "scripts": {
-    "prepublish": "gulp build minify docs",
     "precommit": "gulp jshint",
     "prepush": "gulp test",
     "build": "gulp build",

From 73fc111b503a5f9c32ffd983babd1d9026bfff20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Mon, 11 Jul 2016 19:48:17 +0200
Subject: [PATCH 49/58] SVG: Correctly handle relative "moveto" commands.

Closes #1101
---
 src/path/PathItem.js | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/path/PathItem.js b/src/path/PathItem.js
index 61a1e896..cd15f1b0 100644
--- a/src/path/PathItem.js
+++ b/src/path/PathItem.js
@@ -99,8 +99,10 @@ var PathItem = Item.extend(/** @lends PathItem# */{
             coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
             var length = coords && coords.length;
             relative = command === lower;
+            // Fix issues with z in the middle of SVG path data, not followed by
+            // a m command, see #413:
             if (previous === 'z' && !/[mz]/.test(lower))
-                this.moveTo(current = start);
+                this.moveTo(current);
             switch (lower) {
             case 'm':
             case 'l':
@@ -170,6 +172,8 @@ var PathItem = Item.extend(/** @lends PathItem# */{
                 // Merge first and last segment with Numerical.EPSILON tolerance
                 // to address imprecisions in relative SVG data.
                 this.closePath(/*#=*/Numerical.EPSILON);
+                // Correctly handle relative m commands, see #1101:
+                current = start;
                 break;
             }
             previous = lower;

From 89c60b1a056e657526cf9e1acc4a4bbb33c1e51d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Tue, 12 Jul 2016 19:11:09 +0200
Subject: [PATCH 50/58] Loosely couple Node.js code to canvas module.

Treat absence of canvas module like a web worker context.
Relates to #1103
---
 gulp/tasks/build.js     |  2 +-
 src/core/PaperScript.js |  2 +-
 src/export.js           |  2 +-
 src/init.js             | 13 +++++++------
 src/item/Raster.js      |  2 +-
 src/net/Http.js         |  2 +-
 src/node/canvas.js      | 21 +++++++++++++++++----
 src/node/window.js      |  2 +-
 src/svg/SvgExport.js    |  2 +-
 src/svg/SvgImport.js    | 12 +++++++-----
 test/helpers.js         |  2 +-
 11 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/gulp/tasks/build.js b/gulp/tasks/build.js
index e3a55158..ba2397e7 100644
--- a/gulp/tasks/build.js
+++ b/gulp/tasks/build.js
@@ -47,7 +47,7 @@ buildNames.forEach(function(name) {
                 evaluate: ['src/constants.js'],
                 setup: function() {
                     // Return objects to be defined in the preprocess-scope.
-                    // Note that this would be merge in with already existing
+                    // Note that this would be merged in with already existing
                     // objects.
                     return {
                         __options: Object.assign({}, options, buildOptions[name])
diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js
index 048fce4f..560094d0 100644
--- a/src/core/PaperScript.js
+++ b/src/core/PaperScript.js
@@ -347,7 +347,7 @@ Base.exports.PaperScript = function() {
             }
             if (/^(inline|both)$/.test(sourceMaps)) {
                 code += "\n//# sourceMappingURL=data:application/json;base64,"
-                        + window.btoa(unescape(encodeURIComponent(
+                        + self.btoa(unescape(encodeURIComponent(
                             JSON.stringify(map))));
             }
             code += "\n//# sourceURL=" + (url || 'paperscript');
diff --git a/src/export.js b/src/export.js
index 60a61a5c..6b9358ea 100644
--- a/src/export.js
+++ b/src/export.js
@@ -36,7 +36,7 @@ paper = new (PaperScope.inject(Base.exports, {
 // - PaperScript support in require() with sourceMaps
 // - exportFrames / exportImage on CanvasView
 if (paper.agent.node)
-    require('./node/extend')(paper);
+    require('./node/extend.js')(paper);
 
 // https://github.com/umdjs/umd
 if (typeof define === 'function' && define.amd) {
diff --git a/src/init.js b/src/init.js
index dec12155..de416b51 100644
--- a/src/init.js
+++ b/src/init.js
@@ -19,11 +19,12 @@
 /* global document:true, window:true */
 // Create a window variable valid in the paper.js scope, that points to the
 // native window in browsers and the emulated JSDom one in node.js
-// In workers, window is null (but self is defined), so we can use the validity
-// of the local window object to detect a worker-like context in the library.
-var window = self ? self.window : require('./node/window'),
-    document = window && window.document;
-// Make sure 'self' always points to a window object, also on Node.js.
+// In workers, and on Node.js when no Canvas is present, `window` is null (but
+// `self` is defined), so we can use the validity of the local window object to
+// detect a worker-like context in the library.
+// Make sure `self` always points to a window object, also on Node.js.
+self = self || require('./node/window.js');
 // NOTE: We're not modifying the global `self` here. We receive its value passed
 // to the paper.js function scope, and this is the one that is modified here.
-self = self || window;
+var window = self.window,
+    document = self.document;
diff --git a/src/item/Raster.js b/src/item/Raster.js
index 8b8fba05..a7355af2 100644
--- a/src/item/Raster.js
+++ b/src/item/Raster.js
@@ -379,7 +379,7 @@ var Raster = Item.extend(/** @lends Raster# */{
     },
 
     setSource: function(src) {
-        var image = new window.Image(),
+        var image = new self.Image(),
             crossOrigin = this._crossOrigin;
         if (crossOrigin)
             image.crossOrigin = crossOrigin;
diff --git a/src/net/Http.js b/src/net/Http.js
index e5a304af..012f6b92 100644
--- a/src/net/Http.js
+++ b/src/net/Http.js
@@ -13,7 +13,7 @@
 var Http = {
     request: function(options) {
         // Code borrowed from Coffee Script and extended:
-        var xhr = new window.XMLHttpRequest();
+        var xhr = new self.XMLHttpRequest();
         xhr.open((options.method || 'get').toUpperCase(), options.url,
                 Base.pick(options.async, true));
         if (options.mimeType)
diff --git a/src/node/canvas.js b/src/node/canvas.js
index c6bc25ef..df4e8880 100644
--- a/src/node/canvas.js
+++ b/src/node/canvas.js
@@ -10,16 +10,29 @@
  * All rights reserved.
  */
 
-var Canvas = require('canvas'),
-    idlUtils = require('jsdom/lib/jsdom/living/generated/utils');
-
 // Add some useful extensions to HTMLCanvasElement:
 // - HTMLCanvasElement#type, so we can switch to a PDF canvas
 // - Various Node Canvas methods, routed through from HTMLCanvasElement:
 //   toBuffer, pngStream, createPNGStream, jpgStream, createJPGStream
 
 module.exports = function(window) {
-    var HTMLCanvasElement = window.HTMLCanvasElement;
+    var Canvas;
+    try {
+        Canvas = require('canvas');
+    } catch(e) {
+        // Remove `self.window`, so we still have the global `self` reference,
+        // but no `window` object:
+        // - On the browser, this corresponds to a worker context.
+        // - On Node.js, it basically means the canvas is missing or not working
+        //   which can be treated the same way.
+        delete window.window;
+        console.info(
+                'Unable to load Canvas module. Running in a headless context.');
+        return;
+    }
+
+    var idlUtils = require('jsdom/lib/jsdom/living/generated/utils'),
+        HTMLCanvasElement = window.HTMLCanvasElement;
 
     // Add fake HTMLCanvasElement#type property:
     Object.defineProperty(HTMLCanvasElement.prototype, 'type', {
diff --git a/src/node/window.js b/src/node/window.js
index 598526c6..5987e4f5 100644
--- a/src/node/window.js
+++ b/src/node/window.js
@@ -27,7 +27,7 @@ var document = jsdom.jsdom('<html><body></body></html>', {
     }),
     window = document.defaultView;
 
-require('./canvas')(window);
+require('./canvas.js')(window);
 
 // Define XMLSerializer and DOMParser shims, to emulate browser behavior.
 // Effort to bring this to jsdom: https://github.com/tmpvar/jsdom/issues/1368
diff --git a/src/svg/SvgExport.js b/src/svg/SvgExport.js
index 15808d73..ecf19f23 100644
--- a/src/svg/SvgExport.js
+++ b/src/svg/SvgExport.js
@@ -369,7 +369,7 @@ new function() {
             definitions = null;
         }
         return options.asString
-                ? new window.XMLSerializer().serializeToString(svg)
+                ? new self.XMLSerializer().serializeToString(svg)
                 : svg;
     }
 
diff --git a/src/svg/SvgImport.js b/src/svg/SvgImport.js
index 8a750375..96f96739 100644
--- a/src/svg/SvgImport.js
+++ b/src/svg/SvgImport.js
@@ -553,10 +553,12 @@ new function() {
         // WebKit. We also get variations of quotes or no quotes, single or
         // double, so handle it all with one regular expression:
         var match = value && value.match(/\((?:["'#]*)([^"')]+)/),
-            res = match && definitions[match[1]
-                // This is required by Firefox, which can produce absolute urls
-                // for local gradients, see #1001:
-                .replace(window.location.href.split('#')[0] + '#', '')];
+            name = match && match[1],
+            res = name && definitions[window
+                    // This is required by Firefox, which can produce absolute
+                    // urls for local gradients, see #1001:
+                    ? name.replace(window.location.href.split('#')[0] + '#', '')
+                    : name];
         // Patch in support for SVG's gradientUnits="objectBoundingBox" through
         // Color#_scaleToBounds
         if (res && res._scaleToBounds) {
@@ -659,7 +661,7 @@ new function() {
 
         function onLoad(svg) {
             try {
-                var node = typeof svg === 'object' ? svg : new window.DOMParser()
+                var node = typeof svg === 'object' ? svg : new self.DOMParser()
                         .parseFromString(svg, 'image/svg+xml');
                 if (!node.nodeName) {
                     node = null;
diff --git a/test/helpers.js b/test/helpers.js
index 4a6f7513..676a0e48 100644
--- a/test/helpers.js
+++ b/test/helpers.js
@@ -86,7 +86,7 @@ var equals = function(actual, expected, message, options) {
             || type === 'boolean' && 'Boolean'
             || type === 'undefined' && 'Undefined'
             || Array.isArray(expected) && 'Array'
-            || expected instanceof window.Element && 'Element' // handle DOM Elements
+            || expected instanceof self.Element && 'Element' // handle DOM Elements
             || (cls = expected && expected._class) // check _class 2nd last
             || type === 'object' && 'Object'; // Object as catch-all
     var comparator = type && comparators[type];

From 8a45c5dff9da9a55a5d8bca7133481fba64d4dd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Tue, 12 Jul 2016 19:27:35 +0200
Subject: [PATCH 51/58] Fix Node.js unit-tests, and add CHANGELOG entry for
 #1103

---
 CHANGELOG.md    | 6 ++++++
 test/helpers.js | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22d3d8d8..3ad479eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Change Log
 
+## `0.10.3` (Unreleased)
+
+### Changed
+- Loosely couple Node.js / Electron code to Canvas module, and treat its absence
+  like a headless web worker context in the browser (#1103).
+
 ## `0.10.2`
 
 ### Fixed
diff --git a/test/helpers.js b/test/helpers.js
index 676a0e48..4a6f7513 100644
--- a/test/helpers.js
+++ b/test/helpers.js
@@ -86,7 +86,7 @@ var equals = function(actual, expected, message, options) {
             || type === 'boolean' && 'Boolean'
             || type === 'undefined' && 'Undefined'
             || Array.isArray(expected) && 'Array'
-            || expected instanceof self.Element && 'Element' // handle DOM Elements
+            || expected instanceof window.Element && 'Element' // handle DOM Elements
             || (cls = expected && expected._class) // check _class 2nd last
             || type === 'object' && 'Object'; // Object as catch-all
     var comparator = type && comparators[type];

From 6ca3bb1c639cedfdfc836d2573a18ebbf32d137b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Wed, 13 Jul 2016 18:43:15 +0200
Subject: [PATCH 52/58] Prevent Path#getStrokeBounds() from accidentally
 modifying segments.

Closes #1102
---
 src/path/Path.js | 40 +++++++++++++++++-----------------------
 1 file changed, 17 insertions(+), 23 deletions(-)

diff --git a/src/path/Path.js b/src/path/Path.js
index 41666fac..46869774 100644
--- a/src/path/Path.js
+++ b/src/path/Path.js
@@ -2703,22 +2703,19 @@ statics: {
 
     _addBevelJoin: function(segment, join, radius, miterLimit, matrix,
             strokeMatrix, addPoint, isArea) {
-        // Handles both 'bevel' and 'miter' joins, as they share a lot of code.
+        // Handles both 'bevel' and 'miter' joins, as they share a lot of code,
+        // using different matrices to transform segment points and stroke
+        // vectors to support Style#strokeScaling.
         var curve2 = segment.getCurve(),
             curve1 = curve2.getPrevious(),
-            point = curve2.getPointAtTime(0),
-            normal1 = curve1.getNormalAtTime(1),
-            normal2 = curve2.getNormalAtTime(0),
-            step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
-        normal1.setLength(step);
-        normal2.setLength(step);
-        // use different matrices to transform segment points and stroke vectors
-        // to support Style#strokeScaling.
-        if (matrix)
-            matrix._transformPoint(point, point);
-        if (strokeMatrix) {
-            strokeMatrix._transformPoint(normal1, normal1);
-            strokeMatrix._transformPoint(normal2, normal2);
+            point = curve2.getPoint1().transform(matrix),
+            normal1 = curve1.getNormalAtTime(1).multiply(radius)
+                .transform(strokeMatrix),
+            normal2 = curve2.getNormalAtTime(0).multiply(radius)
+                .transform(strokeMatrix);
+        if (normal1.getDirectedAngle(normal2) < 0) {
+            normal1 = normal1.negate();
+            normal2 = normal2.negate();
         }
         if (isArea) {
             addPoint(point);
@@ -2748,16 +2745,13 @@ statics: {
     _addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,
             addPoint, isArea) {
         // Handles both 'square' and 'butt' caps, as they share a lot of code.
-        // Calculate the corner points of butt and square caps
-        var point = segment._point,
+        // Calculate the corner points of butt and square caps, using different
+        // matrices to transform segment points and stroke vectors to support
+        // Style#strokeScaling.
+        var point = segment._point.transform(matrix),
             loc = segment.getLocation(),
-            normal = loc.getNormal().multiply(radius); // normal is normalized
-        // use different matrices to transform segment points and stroke vectors
-        // to support Style#strokeScaling.
-        if (matrix)
-            matrix._transformPoint(point, point);
-        if (strokeMatrix)
-            strokeMatrix._transformPoint(normal, normal);
+            // NOTE: normal is normalized, so multiply instead of normalize.
+            normal = loc.getNormal().multiply(radius).transform(strokeMatrix);
         if (isArea) {
             addPoint(point.subtract(normal));
             addPoint(point.add(normal));

From 80f4ba947f881973d81c109d7796ca75dfcbeefd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Wed, 13 Jul 2016 21:04:53 +0200
Subject: [PATCH 53/58] First attempt at supporting JSPM.

Relates to #1104
---
 CHANGELOG.md | 5 +++++
 package.json | 1 +
 2 files changed, 6 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3ad479eb..f57f3b79 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,11 @@
 - Loosely couple Node.js / Electron code to Canvas module, and treat its absence
   like a headless web worker context in the browser (#1103).
 
+### Fixed
+- Prevent `Path#getStrokeBounds(matrix)` from accidentally modifying segments
+  (#1102).
+- Compatibility with JSPM (#1104).
+
 ## `0.10.2`
 
 ### Fixed
diff --git a/package.json b/package.json
index dcfd0af4..0612ca4d 100644
--- a/package.json
+++ b/package.json
@@ -77,6 +77,7 @@
   "browser": {
     "canvas": false,
     "jsdom": false,
+    "jsdom/lib/jsdom/living/generated/utils": false,
     "source-map-support": false,
     "./dist/node/window.js": false,
     "./dist/node/extend.js": false

From 083a2c6e0df5736184817a6770a2213f36e224bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Thu, 14 Jul 2016 09:14:11 +0200
Subject: [PATCH 54/58] Boolean: Prevent rare exception where an encountered
 segment is not part of a valid path anymore.

Relates to #1091
---
 src/path/PathItem.Boolean.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js
index 916c9587..93e292be 100644
--- a/src/path/PathItem.Boolean.js
+++ b/src/path/PathItem.Boolean.js
@@ -527,7 +527,7 @@ PathItem.inject(new function() {
                 // are bringing us back to the beginning, and are both valid,
                 // meaning they are part of the boolean result.
                 if (seg !== exclude && (isStart(seg) || isStart(nextSeg)
-                    || !seg._visited && !nextSeg._visited
+                    || nextSeg && !seg._visited && !nextSeg._visited
                     // Self-intersections (!operator) don't need isValid() calls
                     && (!operator || isValid(seg) && (isValid(nextSeg)
                         // If the next segment isn't valid, its intersection

From 38e5fc1488c269fb39b8274c21ffec446052082f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Thu, 14 Jul 2016 09:32:29 +0200
Subject: [PATCH 55/58] Tests: Reference GitHub issues where they're knonw in
 PathItem#contains() tests.

---
 test/tests/PathItem_Contains.js | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/test/tests/PathItem_Contains.js b/test/tests/PathItem_Contains.js
index 2cfd2ed5..f556603c 100644
--- a/test/tests/PathItem_Contains.js
+++ b/test/tests/PathItem_Contains.js
@@ -17,7 +17,7 @@ function testPoint(item, point, inside, message) {
             + ' should be ' + (inside ? 'inside' : 'outside') + '.'));
 }
 
-test('Path#contains() (Regular Polygon)', function() {
+test('Path#contains() (regular polygon: #208)', function() {
     var path = new Path.RegularPolygon([0, 0], 6, 20);
 
     testPoint(path, new Point(0, -20), true);
@@ -39,7 +39,7 @@ test('Path#contains() (Regular Polygon)', function() {
     testPoint(path, new Point(10, 20), false);
 });
 
-test('Path#contains() (Circle Contours)', function() {
+test('Path#contains() (circle contours)', function() {
     var path = new Path.Circle({
         center: [100, 100],
         radius: 50,
@@ -56,7 +56,7 @@ test('Path#contains() (Circle Contours)', function() {
     testPoint(path, path.bounds.bottomRight, false);
 });
 
-test('Path#contains() (Transformed Circle Contours)', function() {
+test('Path#contains() (transformed circle contours)', function() {
     var path = new Path.Circle({
         center: [200, 200],
         radius: 50,
@@ -74,7 +74,7 @@ test('Path#contains() (Transformed Circle Contours)', function() {
     testPoint(path, path.bounds.bottomRight, false);
 });
 
-test('Path#contains() (Round Rectangle)', function() {
+test('Path#contains() (round rectangle: #227)', function() {
     var rectangle = new Rectangle({
         point: new Point(0, 0),
         size: new Size(200, 40)
@@ -83,14 +83,14 @@ test('Path#contains() (Round Rectangle)', function() {
     testPoint(path, new Point(100, 20), true);
 });
 
-test('Path#contains() (Open Circle)', function() {
+test('Path#contains() (open circle)', function() {
     var path = new Path.Circle([100, 100], 100);
     path.closed = false;
     path.fillColor = '#ff0000';
     testPoint(path, new Point(40, 160), false);
 });
 
-test('CompoundPath#contains() (Donut)', function() {
+test('CompoundPath#contains() (donut)', function() {
     var path = new CompoundPath([
         new Path.Circle([0, 0], 50),
         new Path.Circle([0, 0], 25)
@@ -163,7 +163,7 @@ test('Shape#contains()', function() {
     testPoint(shape, new Point(1.1, 0).multiply(half), false);
 });
 
-test('Path#contains() (Rectangle Contours)', function() {
+test('Path#contains() (rectangle contours)', function() {
     var path = new Path.Rectangle(new Point(100, 100), [200, 200]),
         curves = path.getCurves();
 
@@ -174,7 +174,7 @@ test('Path#contains() (Rectangle Contours)', function() {
 });
 
 
-test('Path#contains() (Rotated Rectangle Contours)', function() {
+test('Path#contains() (rotated rectangle contours)', function() {
     var path = new Path.Rectangle(new Point(100, 100), [200, 200]),
         curves = path.getCurves();
 
@@ -200,7 +200,7 @@ test('Path#contains() (touching stationary point with changing orientation)', fu
     testPoint(path, new Point(200, 200), true);
 });
 
-test('Path#contains() (complex shape)', function() {
+test('Path#contains() (complex shape: #400)', function() {
     var path = new Path({
         pathData: 'M301 162L307 154L315 149L325 139.5L332.5 135.5L341 128.5L357.5 117.5L364.5 114.5L368.5 110.5L380 105.5L390.5 102L404 96L410.5 96L415 97.5L421 104L425.5 113.5L428.5 126L429.5 134L429.5 141L429.5 148L425.5 161.5L425.5 169L414 184.5L409.5 191L401 201L395 209L386 214.5L378.5 217L368 220L348 219.5L338 218L323.5 212.5L312 205.5L302.5 197.5L295.5 189L291.5 171.5L294 168L298 165.5L301 162z',
         fillColor: 'blue',
@@ -215,7 +215,7 @@ test('Path#contains() (complex shape)', function() {
 });
 
 
-test('Path#contains() (straight curves with zero-winding)', function() {
+test('Path#contains() (straight curves with zero-winding: #943)', function() {
     var pointData = [
         [[250, 230], true, true, false, true],
         [[200, 230], true, true, true, true],
@@ -282,7 +282,7 @@ test('Path#contains() (straight curves with zero-winding)', function() {
     }
 });
 
-test('CompoundPath#contains() (nested touching circles)', function() {
+test('CompoundPath#contains() (nested touching circles: #944)', function() {
     var c1 = new Path.Circle({
         center: [200, 200],
         radius: 100

From 41dce862d4597ce3d08b0d5b551d7b3e3ebfcf57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Thu, 14 Jul 2016 10:21:11 +0200
Subject: [PATCH 56/58] Fix CompoundPath#getLastCurve() and improve
 documentation.

---
 src/path/CompoundPath.js | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/path/CompoundPath.js b/src/path/CompoundPath.js
index d367fde6..201e3a7c 100644
--- a/src/path/CompoundPath.js
+++ b/src/path/CompoundPath.js
@@ -170,7 +170,8 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
     },
 
     /**
-     * The first Segment contained within the path.
+     * The first Segment contained within the compound-path, a short-cut to
+     * calling {@link Path#getFirstSegment()} on {@link Item#getFirstChild()}.
      *
      * @bean
      * @type Segment
@@ -181,7 +182,8 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
     },
 
     /**
-     * The last Segment contained within the path.
+     * The last Segment contained within the compound-path, a short-cut to
+     * calling {@link Path#getLastSegment()} on {@link Item#getLastChild()}.
      *
      * @bean
      * @type Segment
@@ -207,7 +209,8 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
     },
 
     /**
-     * The first Curve contained within the path.
+     * The first Curve contained within the compound-path, a short-cut to
+     * calling {@link Path#getFirstCurve()} on {@link Item#getFirstChild()}.
      *
      * @bean
      * @type Curve
@@ -218,14 +221,15 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
     },
 
     /**
-     * The last Curve contained within the path.
+     * The last Curve contained within the compound-path, a short-cut to
+     * calling {@link Path#getLastCurve()} on {@link Item#getLastChild()}.
      *
      * @bean
      * @type Curve
      */
     getLastCurve: function() {
         var last = this.getLastChild();
-        return last && last.getFirstCurve();
+        return last && last.getLastCurve();
     },
 
     /**

From c2df96c44045ece30adbcb321f00a9c7d9f4ce88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Thu, 14 Jul 2016 10:24:04 +0200
Subject: [PATCH 57/58] Implement CompoundPath#closed.

---
 src/path/CompoundPath.js | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/src/path/CompoundPath.js b/src/path/CompoundPath.js
index 201e3a7c..03a65b04 100644
--- a/src/path/CompoundPath.js
+++ b/src/path/CompoundPath.js
@@ -169,6 +169,30 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
             this.reverse();
     },
 
+    /**
+     * Specifies whether the compound-path is fully closed, meaning all its
+     * contained sub-paths are closed path.
+     *
+     * @bean
+     * @type Boolean
+     * @see Path#isClosed()
+     */
+    isClosed: function() {
+        var children = this._children;
+        for (var i = 0, l = children.length; i < l; i++) {
+            if (!children[i]._closed)
+                return false;
+        }
+        return true;
+    },
+
+    setClosed: function(closed) {
+        var children = this._children;
+        for (var i = 0, l = children.length; i < l; i++) {
+            children[i].setClosed(closed);
+        }
+    },
+
     /**
      * The first Segment contained within the compound-path, a short-cut to
      * calling {@link Path#getFirstSegment()} on {@link Item#getFirstChild()}.

From acfe6cddeb2d548048972bff6d9f355e2c1383af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Thu, 14 Jul 2016 10:49:12 +0200
Subject: [PATCH 58/58] Boolean: Improve handling of open paths.

Relates to #1089
---
 src/path/PathItem.Boolean.js | 22 +++++++++++++---------
 src/path/PathItem.js         |  2 +-
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js
index 93e292be..ae0bc239 100644
--- a/src/path/PathItem.Boolean.js
+++ b/src/path/PathItem.Boolean.js
@@ -47,10 +47,12 @@ PathItem.inject(new function() {
      * remove empty curves, #resolveCrossings() to resolve self-intersection
      * make sure all paths have correct winding direction.
      */
-    function preparePath(path, resolve) {
+    function preparePath(path, closed) {
         var res = path.clone(false).reduce({ simplify: true })
                 .transform(null, true, true);
-        return resolve ? res.resolveCrossings() : res;
+        if (closed)
+            res.setClosed(true);
+        return closed ? res.resolveCrossings() : res;
     }
 
     function createResult(ctor, paths, reduce, path1, path2) {
@@ -74,8 +76,10 @@ PathItem.inject(new function() {
         // Add a simple boolean property to check for a given operation,
         // e.g. `if (operator.unite)`
         operator[operation] = true;
-        // If path1 is open, delegate to computeOpenBoolean()
-        if (!path1._children && !path1._closed)
+        // If path1 is open, delegate to computeOpenBoolean().
+        // NOTE: Do not access private _closed property here, since path1 may
+        // be a CompoundPath.
+        if (!path1.isClosed())
             return computeOpenBoolean(path1, path2, operator);
         // We do not modify the operands themselves, but create copies instead,
         // fas produced by the calls to preparePath().
@@ -144,11 +148,11 @@ PathItem.inject(new function() {
 
     function computeOpenBoolean(path1, path2, operator) {
         // Only support subtract and intersect operations between an open
-        // and a closed path. Assume that compound-paths are closed.
-        // TODO: Should we complain about not supported operations?
-        if (!path2 || !path2._children && !path2._closed
-                || !operator.subtract && !operator.intersect)
-            return null;
+        // and a closed path.
+        if (!path2 || !operator.subtract && !operator.intersect) {
+            throw new Error('Boolean operations on open paths only support ' +
+                    'subtraction and intersection with another path.');
+        }
         var _path1 = preparePath(path1, false),
             _path2 = preparePath(path2, false),
             crossings = _path1.getCrossings(_path2),
diff --git a/src/path/PathItem.js b/src/path/PathItem.js
index cd15f1b0..5fbef743 100644
--- a/src/path/PathItem.js
+++ b/src/path/PathItem.js
@@ -188,7 +188,7 @@ var PathItem = Item.extend(/** @lends PathItem# */{
 
     _contains: function(point) {
         // NOTE: point is reverse transformed by _matrix, so we don't need to
-        // apply here.
+        // apply the matrix here.
 /*#*/ if (__options.nativeContains || !__options.booleanOperations) {
         // To compare with native canvas approach:
         var ctx = CanvasProvider.getContext(1, 1);