-Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
+Copyright (c) 2014-2021 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
Virtual World Framework Apache 2.0 license (https://github.com/NikolaySuslov/livecodingspace/blob/master/licenses/LICENSE_VWF.md)
*/
@@ -12,12 +12,19 @@ import { WorldApp } from '/web/world-app.js';
import { Widgets } from '/lib/ui/widgets.js';
import {Spinner} from '/lib/ui/spinjs/spin.js';
+import { Standalone } from '/web/standalone.js';
+import '/lib/ui/shoelace/dist/shoelace.js';
+import { setBasePath } from '/lib/ui/shoelace/dist/utilities/base-path.js';
+import { h, text, patch } from '/lib/ui/superfine.js';
+
import { createAdapter } from '/lib/fun/@most/adapter/dist/index.mjs';
import * as mostSubject from '/lib/fun/@most/subject/dist/index.all.js';
class App {
constructor() {
console.log("app constructor");
+ setBasePath('/lib/ui/shoelace');
+
this.widgets = new Widgets;
//globals
window._app = this;
@@ -75,6 +82,7 @@ class App {
page('/debug', this.HandleDebugIndex);
page('/settings', this.HandleSettingsIndex);
page('/profile', this.HandleUserIndex);
+ page('/login', this.HandleUserLogin);
page('/worlds', this.HandleIndex);
page('/:user', this.HandleUserWorlds);
page('/:user/worlds', this.HandleUserWorlds);
@@ -111,7 +119,11 @@ class App {
'd3DoF': false,
'd6DoF': false,
'streamMsg': false,
- 'multisocket': false
+ 'multisocket': false,
+ 'edit': false,
+ 'standalone': false,
+ "standaloneWorldName": "concert",
+ "standaloneUserName": "aaa"
}
let conf = JSON.parse(localStorage.getItem('lcs_config'));
@@ -186,6 +198,8 @@ class App {
let manualConfig = localStorage.getItem('lcs_app_manual_settings');
let lcsappConfig = localStorage.getItem('lcs_app');
+ let edit = localStorage.getItem('edit');
+
localStorage.clear();
if (config)
@@ -200,6 +214,9 @@ class App {
if (lcsappConfig)
localStorage.setItem('lcs_app', lcsappConfig);
+ if (edit)
+ localStorage.setItem('edit', edit);
+
}
setupLoadScreen(){
@@ -530,6 +547,32 @@ class App {
}
+ HandleUserLogin(ctx) {
+
+ console.log("user login");
+
+ let userAlias = ctx.params.user;
+ let worldName = ctx.params.space;
+ let saveName = ctx.params.savename;
+
+ window._app.hideProgressBar();
+ //window._app.hideUIControl();
+
+
+ _app.generalIndex().then(res=>{
+
+ if (!_app.indexApp) {
+ _app.indexApp = new IndexApp('login');
+ }
+
+ // let worldApp = new WorldApp(userAlias, worldName, saveName);
+Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
+Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
+Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
+ let m = new Pt_1.Group(new Pt_1.Pt(-0.16666666666666666, 0.5, -0.5, 0.16666666666666666), new Pt_1.Pt(0.5, -1, 0, 0.6666666666666666), new Pt_1.Pt(-0.5, 0.5, 0.5, 0.16666666666666666), new Pt_1.Pt(0.16666666666666666, 0, 0, 0));
+ return Curve._calcPt(ctrls, LinearAlgebra_1.Mat.multiply([step], m, true)[0]);
+ let m = new Pt_1.Group(new Pt_1.Pt(-0.16666666666666666, 0.5, -0.5, 0.16666666666666666), new Pt_1.Pt(-1.5, 2, 0, -0.3333333333333333), new Pt_1.Pt(1.5, -2.5, 0.5, 0.16666666666666666), new Pt_1.Pt(0.16666666666666666, 0, 0, 0));
+ let h = LinearAlgebra_1.Mat.multiply([step], m, true)[0].multiply(tension);
Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
+
+This driver includes the port and some code parts from the "Croquet synced video demo" for implementing Player elements syncing within LiveCoding.space applications and LCS Reflector / Luminary.
+
+Croquet synced video demo License
+Copyright 2020 Croquet Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
*/
+
// VWF & Tone driver
-import {Fabric} from '/core/vwf/fabric.js';
+
+import { Fabric } from '/core/vwf/fabric.js';
//import * as Tone from '/drivers/view/tonejs/dist/Tone.js';
+ // console.log("change playbackRate for ", el.ID, playbackRate);
+ // })
+ // }
+
+ viewNode.lastRateAdjust = vwf.time() * 1000; // make sure we don't adjust rate until playback has settled in, and after any emergency jump we decide to do
+ viewNode.jumpIfNeeded = false;
+ // if the video is blocked from playing, enter a stepping mode in which we move the video forward with successive pause() calls
+Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
+
+This driver includes the port and some code parts from the "Croquet synced video demo" for implementing video elements syncing within LiveCoding.space applications and LCS Reflector / Luminary.
+
+Croquet synced video demo License
+Copyright 2020 Croquet Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+ viewNode.lastRateAdjust = vwf.time() * 1000; // make sure we don't adjust rate until playback has settled in, and after any emergency jump we decide to do
+ viewNode.jumpIfNeeded = false;
+ // if the video is blocked from playing, enter a stepping mode in which we move the video forward with successive pause() calls
+ const videoDiffMS = videoDiff * 1000; // +ve means *ahead* of where it should be
+ if (videoDiff < video.duration / 2) { // otherwise presumably measured across a loop restart; just ignore.
+ if (viewNode.jumpIfNeeded) { //this.jumpIfNeeded
+ viewNode.jumpIfNeeded = false;
+ // if there's a difference greater than 500ms, try to jump the video to the right place
+ if (Math.abs(videoDiffMS) > 500) {
+ console.log(`jumping video by ${-Math.round(videoDiffMS)}ms`);
+ video.currentTime = this.wrappedTime(videoTime - videoDiff + 0.1, true, video.duration); // 0.1 to counteract the delay that the jump itself tends to introduce; true to ensure we're not jumping beyond the last video frame
+ }
+ } else {
+ // every 3s, check video lag/advance, and set the playback rate accordingly.
+ // current adjustment settings:
+ // > 150ms off: set playback 3% faster/slower than normal
+ // > 50ms: 1% faster/slower
+ // < 25ms: normal (i.e., hysteresis between 50ms and 25ms in the same sense)
+ * @description Object inherited by many Two.js objects in order to facilitate custom events.
+ */
+ var Events = {
+
+ /**
+ * @name Two.Events#on
+ * @function
+ * @param {String} [name] - The name of the event to bind a function to.
+ * @param {Function} [handler] - The function to be invoked when the event is dispatched.
+ * @description Call to add a listener to a specific event name.
+ */
+ on: addEventListener,
+
+ /**
+ * @name Two.Events#off
+ * @function
+ * @param {String} [name] - The name of the event intended to be removed.
+ * @param {Function} [handler] - The handler intended to be reomved.
+ * @description Call to remove listeners from a specific event. If only `name` is passed then all the handlers attached to that `name` will be removed. If no arguments are passed then all handlers for every event on the obejct are removed.
+ */
+ off: removeEventListener,
+
+ /**
+ * @name Two.Events#trigger
+ * @function
+ * @param {String} name - The name of the event to dispatch.
+ * @param arguments - Anything can be passed after the name and those will be passed on to handlers attached to the event in the order they are passed.
+ * @description Call to trigger a custom event. Any additional arguments passed after the name will be passed along to the attached handlers.
+ */
+ trigger: function(name) {
+ var scope = this;
+ if (!scope._events) return scope;
+ var args = Array.prototype.slice.call(arguments, 1);
+ var events = scope._events[name];
+ if (events) dispatch(scope, events, args);
+ return scope;
+ },
+
+ listen: function(obj, name, handler) {
+
+ var bound = this;
+
+ if (obj) {
+
+ var event = function () {
+ handler.apply(bound, arguments);
+ };
+
+ // Add references about the object that assigned this listener
+ event.obj = obj;
+ event.name = name;
+ event.handler = handler;
+
+ obj.on(name, event);
+
+ }
+
+ return bound;
+
+ },
+
+ ignore: function(obj, name, handler) {
+
+ var scope = this;
+ obj.off(name, handler);
+ return scope;
+
+ },
+
+ /**
+ * @name Two.Events.Types
+ * @property {Object} - Object of different types of Two.js specific events.
+ */
+ Types: {
+ play: 'play',
+ pause: 'pause',
+ update: 'update',
+ render: 'render',
+ resize: 'resize',
+ change: 'change',
+ remove: 'remove',
+ insert: 'insert',
+ order: 'order',
+ load: 'load'
+ }
+
+ };
+
+
+ /**
+ * @name Two.Events.bind
+ * @function
+ * @description Alias for {@link Two.Events.on}.
+ */
+ Events.bind = addEventListener;
+
+ /**
+ * @name Two.Events.unbind
+ * @function
+ * @description Alias for {@link Two.Events.off}.
+ */
+ Events.unbind = removeEventListener;
+
+ /**
+ * @private
+ * @returns {Two.Events} - Returns an instance of self for the purpose of chaining.
+ */
+ function addEventListener(name, handler) {
+
+ var scope = this;
+
+ scope._events || (scope._events = {});
+ var list = scope._events[name] || (scope._events[name] = []);
+
+ list.push(handler);
+
+ return scope;
+
+ }
+
+ /**
+ * @private
+ * @returns {Two.Events} - Returns an instance of self for the purpose of chaining.
+ */
+ function removeEventListener(name, handler) {
+
+ var scope = this;
+
+ if (!scope._events) {
+ return scope;
+ }
+ if (!name && !handler) {
+ scope._events = {};
+ return scope;
+ }
+
+ var names = name ? [name] : Object.keys(scope._events);
+ * @param {Number} [x=0] - Any number to represent the horizontal x-component of the vector.
+ * @param {Number} [y=0] - Any number to represent the vertical y-component of the vector.
+ * @description A class to store x / y component vector data. In addition to storing data `Two.Vector` has suped up methods for commonplace mathematical operations.
+ */
+ function Vector(x, y) {
+
+ /**
+ * @name Two.Vector#x
+ * @property {Number} - The horizontal x-component of the vector.
+ */
+ this.x = x || 0;
+
+ /**
+ * @name Two.Vector#y
+ * @property {Number} - The vertical y-component of the vector.
+ */
+ this.y = y || 0;
+
+ }
+
+ _.extend(Vector, {
+
+ /**
+ * @name Two.Vector.zero
+ * @readonly
+ * @property {Two.Vector} - Handy reference to a vector with component values 0, 0 at all times.
+ */
+ zero: new Vector(),
+
+ /**
+ * @name Two.Vector.add
+ * @function
+ * @param {Two.Vector} v1
+ * @param {Two.Vector} v2
+ * @returns {Two.Vector}
+ * @description Add two vectors together.
+ */
+ add: function(v1, v2) {
+ return new Vector(v1.x + v2.x, v1.y + v2.y);
+ },
+
+ /**
+ * @name Two.Vector.sub
+ * @function
+ * @param {Two.Vector} v1
+ * @param {Two.Vector} v2
+ * @returns {Two.Vector}
+ * @description Subtract two vectors: `v2` from `v1`.
+ */
+ sub: function(v1, v2) {
+ return new Vector(v1.x - v2.x, v1.y - v2.y);
+ },
+
+ /**
+ * @name Two.Vector.subtract
+ * @function
+ * @description Alias for {@link Two.Vector.sub}.
+ */
+ subtract: function(v1, v2) {
+ return Vector.sub(v1, v2);
+ },
+
+ /**
+ * @name Two.Vector.ratioBetween
+ * @function
+ * @param {Two.Vector} A
+ * @param {Two.Vector} B
+ * @returns {Number} The ratio betwen two points `v1` and `v2`.
+ * @returns {Number} The squared distance between points `v1` and `v2`.
+ */
+ distanceBetweenSquared: function(v1, v2) {
+
+ var dx = v1.x - v2.x;
+ var dy = v1.y - v2.y;
+
+ return dx * dx + dy * dy;
+
+ },
+
+ /**
+ * @name Two.Vector.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Vector} to any object. Handy if you'd like to extend the {@link Two.Vector} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ // /**
+ // * Override Backbone bind / on in order to add properly broadcasting.
+ // * This allows Two.Vector to not broadcast events unless event listeners
+ // * are explicity bound to it.
+ // */
+
+ object.bind = object.on = function() {
+
+ if (!this._bound) {
+ this._x = this.x;
+ this._y = this.y;
+ Object.defineProperty(this, 'x', xgs);
+ Object.defineProperty(this, 'y', ygs);
+ _.extend(this, BoundProto);
+ this._bound = true; // Reserved for event initialization check
+ }
+
+ Events.bind.apply(this, arguments);
+
+ return this;
+
+ };
+
+ }
+
+ });
+
+ _.extend(Vector.prototype, Events, {
+
+ constructor: Vector,
+
+ /**
+ * @name Two.Vector#set
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @description Set the x / y components of a vector to specific number values.
+ */
+ set: function(x, y) {
+ this.x = x;
+ this.y = y;
+ return this;
+ },
+
+ /**
+ * @name Two.Vector#copy
+ * @function
+ * @param {Two.Vector} v
+ * @description Copy the x / y components of another object `v`.
+ */
+ copy: function(v) {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ },
+
+ /**
+ * @name Two.Vector#clear
+ * @function
+ * @description Set the x / y component values of the vector to zero.
+ */
+ clear: function() {
+ this.x = 0;
+ this.y = 0;
+ return this;
+ },
+
+ /**
+ * @name Two.Vector#clone
+ * @function
+ * @description Create a new vector and copy the existing values onto the newly created instance.
+ */
+ clone: function() {
+ return new Vector(this.x, this.y);
+ },
+
+ /**
+ * @name Two.Vector#add
+ * @function
+ * @param {Two.Vector} v
+ * @description Add an object with x / y component values to the instance.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Vector#add
+ * @function
+ * @param {Number} v
+ * @description Add the **same** number to both x / y component values of the instance.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Vector#add
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @description Add `x` / `y` values to their respective component value on the instance.
+ * @description Alias for {@link Two.Vector.divide}.
+ */
+ divideSelf: function(v) {
+ return this.divide.apply(this, arguments);
+ },
+
+ /**
+ * @name Two.Vector#divideScalar
+ * @function
+ * @param {Number} s - The scalar to divide by.
+ * @description Divide the vector by a single number. Shorthand to call {@link Two.Vector#divide} directly.
+ */
+ divideScalar: function(s) {
+ return this.divide(s);
+ },
+
+ /**
+ * @name Two.Vector#negate
+ * @function
+ * @description Invert each component's sign value.
+ */
+ negate: function() {
+ return this.multiply(-1);
+ },
+
+ /**
+ * @name Two.Vector#negate
+ * @function
+ * @returns {Number}
+ * @description Get the [dot product](https://en.wikipedia.org/wiki/Dot_product) of the vector.
+ */
+ dot: function(v) {
+ return this.x * v.x + this.y * v.y;
+ },
+
+ /**
+ * @name Two.Vector#length
+ * @function
+ * @returns {Number}
+ * @description Get the length of a vector.
+ */
+ length: function() {
+ return Math.sqrt(this.lengthSquared());
+ },
+
+ /**
+ * @name Two.Vector#lengthSquared
+ * @function
+ * @returns {Number}
+ * @description Get the length of the vector to the power of two. Widely used as less expensive than {@link Two.Vector#length}, because it isn't square-rooting any numbers.
+ */
+ lengthSquared: function() {
+ return this.x * this.x + this.y * this.y;
+ },
+
+ /**
+ * @name Two.Vector#normalize
+ * @function
+ * @description Normalize the vector from negative one to one.
+ */
+ normalize: function() {
+ return this.divideScalar(this.length());
+ },
+
+ /**
+ * @name Two.Vector#distanceTo
+ * @function
+ * @returns {Number}
+ * @description Get the distance between two vectors.
+ */
+ distanceTo: function(v) {
+ return Math.sqrt(this.distanceToSquared(v));
+ },
+
+ /**
+ * @name Two.Vector#distanceToSquared
+ * @function
+ * @returns {Number}
+ * @description Get the distance between two vectors to the power of two. Widely used as less expensive than {@link Two.Vector#distanceTo}, because it isn't square-rooting any numbers.
+ */
+ distanceToSquared: function(v) {
+ var dx = this.x - v.x,
+ dy = this.y - v.y;
+ return dx * dx + dy * dy;
+ },
+
+ /**
+ * @name Two.Vector#setLength
+ * @function
+ * @param {Number} l - length to set vector to.
+ * @description Set the length of a vector.
+ */
+ setLength: function(l) {
+ return this.normalize().multiplyScalar(l);
+ },
+
+ /**
+ * @name Two.Vector#equals
+ * @function
+ * @param {Two.Vector} v - The vector to compare against.
+ * @param {Number} [eps=0.0001] - An options epsilon for precision.
+ * @returns {Boolean}
+ * @description Qualify if one vector roughly equal another. With a margin of error defined by epsilon.
+ * @param {Number} [x=0] - The x position of the root anchor point.
+ * @param {Number} [y=0] - The y position of the root anchor point.
+ * @param {Number} [lx=0] - The x position of the left handle point.
+ * @param {Number} [ly=0] - The y position of the left handle point.
+ * @param {Number} [rx=0] - The x position of the right handle point.
+ * @param {Number} [ry=0] - The y position of the right handle point.
+ * @param {String} [command=Two.Commands.move] - The command to describe how to render. Applicable commands are {@link Two.Commands}
+ * @extends Two.Vector
+ * @description An object that holds 3 {@link Two.Vector}s, the anchor point and its corresponding handles: `left` and `right`. In order to properly describe the bezier curve about the point there is also a command property to describe what type of drawing should occur when Two.js renders the anchors.
+ */
+ function Anchor(x, y, lx, ly, rx, ry, command) {
+
+ Vector.call(this, x, y);
+
+ this._broadcast = (function() {
+ this.trigger(Events.Types.change);
+ }).bind(this);
+
+ this._command = command || Commands.move;
+ this._relative = true;
+
+ var ilx = typeof lx === 'number';
+ var ily = typeof ly === 'number';
+ var irx = typeof rx === 'number';
+ var iry = typeof ry === 'number';
+
+ // Append the `controls` object only if control points are specified,
+ // keeping the Two.Anchor inline with a Two.Vector until it needs to
+ // evolve beyond those functions - e.g: a simple 2 component vector.
+ if (ilx || ily || irx || iry) {
+ Anchor.AppendCurveProperties(this);
+ }
+
+ if (ilx) {
+ this.controls.left.x = lx;
+ }
+ if (ily) {
+ this.controls.left.y = ly;
+ }
+ if (irx) {
+ this.controls.right.x = rx;
+ }
+ if (iry) {
+ this.controls.right.y = ry;
+ }
+
+ }
+
+ _.extend(Anchor, {
+
+ /**
+ * @name Two.Anchor.AppendCurveProperties
+ * @function
+ * @param {Two.Anchor} anchor - The instance to append the `control`object to.
+ * @description Adds the `controls` property as an object with `left` and `right` properties to access the bezier control handles that define how the curve is drawn. It also sets the `relative` property to `true` making vectors in the `controls` object relative to their corresponding root anchor point.
+ */
+ AppendCurveProperties: function(anchor) {
+
+ anchor.relative = true;
+
+ /**
+ * @name Two.Anchor#controls
+ * @property {Object} controls
+ * @description An plain object that holds the controls handles for a {@link Two.Anchor}.
+ */
+ anchor.controls = {};
+
+ /**
+ * @name Two.Anchor#controls#left
+ * @property {Two.Vector} left
+ * @description The "left" control point to define handles on a bezier curve.
+ */
+ anchor.controls.left = new Vector(0, 0);
+
+ /**
+ * @name Two.Anchor#controls#right
+ * @property {Two.Vector} right
+ * @description The "left" control point to define handles on a bezier curve.
+ */
+ anchor.controls.right = new Vector(0, 0);
+
+ },
+
+ /**
+ * @name Two.Anchor.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Anchor} to any object. Handy if you'd like to extend the {@link Two.Anchor} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ /**
+ * @name Two.Anchor#command
+ * @property {Two.Commands}
+ * @description A draw command associated with the anchor point.
+ */
+ Object.defineProperty(object, 'command', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._command;
+ },
+
+ set: function(c) {
+ this._command = c;
+ if (this._command === Commands.curve && !_.isObject(this.controls)) {
+ Anchor.AppendCurveProperties(this);
+ }
+ this.trigger(Events.Types.change);
+ }
+
+ });
+
+ /**
+ * @name Two.Anchor#relative
+ * @property {Boolean}
+ * @description A boolean to render control points relative to the root anchor point or in global coordinate-space to the rest of the scene.
+ // Make it possible to bind and still have the Anchor specific
+ // inheritance from Two.Vector. In this case relying on `Two.Vector`
+ // to do much of the heavy event-listener binding / unbinding.
+ object.bind = object.on = function() {
+ var bound = this._bound;
+ Vector.prototype.bind.apply(this, arguments);
+ if (!bound) {
+ _.extend(this, AnchorProto);
+ }
+ };
+
+ }
+
+ });
+
+ var AnchorProto = {
+
+ constructor: Anchor,
+
+ /**
+ * @name Two.Anchor#listen
+ * @function
+ * @description Convenience method used mainly by {@link Two.Path#vertices} to listen and propagate changes from control points up to their respective anchors and further if necessary.
+ * @param {Two.Anchor} v - The anchor to apply values to.
+ * @description Copy the properties of one {@link Two.Anchor} onto another.
+ */
+ copy: function(v) {
+
+ this.x = v.x;
+ this.y = v.y;
+
+ if (typeof v.command === 'string') {
+ this.command = v.command;
+ }
+ if (_.isObject(v.controls)) {
+ if (!_.isObject(this.controls)) {
+ Anchor.AppendCurveProperties(this);
+ }
+ // TODO: Do we need to listen here?
+ this.controls.left.copy(v.controls.left);
+ this.controls.right.copy(v.controls.right);
+ }
+ if (typeof v.relative === 'boolean') {
+ this.relative = v.relative;
+ }
+
+ // TODO: Hack for `Two.Commands.arc`
+ if (this.command === Commands.arc) {
+ this.rx = v.rx;
+ this.ry = v.ry;
+ this.xAxisRotation = v.xAxisRotation;
+ this.largeArcFlag = v.largeArcFlag;
+ this.sweepFlag = v.sweepFlag;
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Anchor#clone
+ * @function
+ * @returns {Two.Anchor}
+ * @description Create a new {@link Two.Anchor}, set all its values to the current instance and return it for use.
+ */
+ clone: function() {
+
+ var controls = this.controls;
+
+ var clone = new Anchor(
+ this.x,
+ this.y,
+ controls && controls.left.x,
+ controls && controls.left.y,
+ controls && controls.right.x,
+ controls && controls.right.y,
+ this.command
+ );
+ clone.relative = this._relative;
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Anchor#toObject
+ * @function
+ * @returns {Object} - An object with properties filled out to mirror {@link Two.Anchor}.
+ * @description Create a JSON compatible plain object of the current instance. Intended for use with storing values in a database.
+ */
+ toObject: function() {
+ var o = {
+ x: this.x,
+ y: this.y
+ };
+ if (this._command) {
+ o.command = this._command;
+ }
+ if (this._relative) {
+ o.relative = this._relative;
+ }
+ if (this.controls) {
+ o.controls = {
+ left: this.controls.left.toObject(),
+ right: this.controls.right.toObject()
+ };
+ }
+ return o;
+ },
+
+ /**
+ * @name Two.Anchor#toString
+ * @function
+ * @returns {String} - A String with comma-separated values reflecting the various values on the current instance.
+ * @description Create a string form of the current instance. Intended for use with storing values in a database. This is lighter to store than the JSON compatible {@link Two.Anchor#toObject}.
+ * @description The id of the next requestAnimationFrame function.
+ */
+ nextFrameID: null,
+
+ // Primitive
+
+ /**
+ * @name Two.Types
+ * @property {Object} - The different rendering types available in the library.
+ */
+ Types: {
+ webgl: 'WebGLRenderer',
+ svg: 'SVGRenderer',
+ canvas: 'CanvasRenderer'
+ },
+
+ /**
+ * @name Two.Version
+ * @property {String} - The current working version of the library.
+ */
+ Version: 'v0.7.6',
+
+ /**
+ * @name Two.PublishDate
+ * @property {String} - The automatically generated publish date in the build process to verify version release candidates.
+ */
+ PublishDate: '2021-06-08T20:19:33.699Z',
+
+ /**
+ * @name Two.Identifier
+ * @property {String} - String prefix for all Two.js object's ids. This trickles down to SVG ids.
+ */
+ Identifier: 'two-',
+
+ /**
+ * @name Two.Resolution
+ * @property {Number} - Default amount of vertices to be used for interpreting Arcs and ArcSegments.
+ */
+ Resolution: 12,
+
+ /**
+ * @name Two.AutoCalculateImportedMatrices
+ * @property {Boolean} - When importing SVGs through the {@link two#interpret} and {@link two#load}, this boolean determines whether Two.js infers and then overrides the exact transformation matrix of the reference SVG.
+ * @nota-bene `false` copies the exact transformation matrix values, but also sets the path's `matrix.manual = true`.
+ */
+ AutoCalculateImportedMatrices: true,
+
+ /**
+ * @name Two.Instances
+ * @property {Two[]} - Registered list of all Two.js instances in the current session.
+ */
+ Instances: [],
+
+ /**
+ * @function Two.uniqueId
+ * @description Simple method to access an incrementing value. Used for `id` allocation on all Two.js objects.
+ * @returns {Number} Ever increasing Number.
+ */
+ uniqueId: function() {
+ return count++;
+ }
+
+ };
+
+ var HALF_PI$3 = Math.PI / 2;
+
+ /**
+ * @name Two.Utils.Curve
+ * @property {Object} - Additional utility constant variables related to curve math and calculations.
+ */
+ var Curve = {
+
+ CollinearityEpsilon: Math.pow(10, -30),
+
+ RecursionLimit: 16,
+
+ CuspLimit: 0,
+
+ Tolerance: {
+ distance: 0.25,
+ angle: 0,
+ epsilon: Number.EPSILON
+ },
+
+ // Lookup tables for abscissas and weights with values for n = 2 .. 16.
+ // As values are symmetric, only store half of them and adapt algorithm
+ * @param {Number} t - Zero-to-one value describing what percentage to calculate.
+ * @param {Number} a - The firt point's component value.
+ * @param {Number} b - The first point's bezier component value.
+ * @param {Number} c - The second point's bezier component value.
+ * @param {Number} d - The second point's component value.
+ * @returns {Number} The coordinate value for a specific component along a cubic bezier curve by `t`.
+ */
+ var getComponentOnCubicBezier = function(t, a, b, c, d) {
+ var k = 1 - t;
+ return (k * k * k * a) + (3 * k * k * t * b) + (3 * k * t * t * c) +
+ (t * t * t * d);
+ };
+
+ /**
+ * @name Two.Utils.subdivide
+ * @function
+ * @param {Number} x1 - x position of first anchor point.
+ * @param {Number} y1 - y position of first anchor point.
+ * @param {Number} x2 - x position of first anchor point's "right" bezier handle.
+ * @param {Number} y2 - y position of first anchor point's "right" bezier handle.
+ * @param {Number} x3 - x position of second anchor point's "left" bezier handle.
+ * @param {Number} y3 - y position of second anchor point's "left" bezier handle.
+ * @param {Number} x4 - x position of second anchor point.
+ * @param {Number} y4 - y position of second anchor point.
+ * @param {Number} [limit=Two.Utils.Curve.RecursionLimit] - The amount of vertices to create by subdividing.
+ * @returns {Anchor[]} A list of anchor points ordered in between `x1`, `y1` and `x4`, `y4`
+ * @description Given 2 points (a, b) and corresponding control point for each return an array of points that represent points plotted along the curve. The number of returned points is determined by `limit`.
+ var x = getComponentOnCubicBezier(t, x1, x2, x3, x4);
+ var y = getComponentOnCubicBezier(t, y1, y2, y3, y4);
+ result.push(new Anchor(x, y));
+ }
+
+ return result;
+
+ };
+
+ /**
+ * @name Two.Utils.getCurveLength
+ * @function
+ * @param {Number} x1 - x position of first anchor point.
+ * @param {Number} y1 - y position of first anchor point.
+ * @param {Number} x2 - x position of first anchor point's "right" bezier handle.
+ * @param {Number} y2 - y position of first anchor point's "right" bezier handle.
+ * @param {Number} x3 - x position of second anchor point's "left" bezier handle.
+ * @param {Number} y3 - y position of second anchor point's "left" bezier handle.
+ * @param {Number} x4 - x position of second anchor point.
+ * @param {Number} y4 - y position of second anchor point.
+ * @param {Number} [limit=Two.Utils.Curve.RecursionLimit] - The amount of vertices to create by subdividing.
+ * @returns {Number} The length of a curve.
+ * @description Given 2 points (a, b) and corresponding control point for each, return a float that represents the length of the curve using Gauss-Legendre algorithm. Limit iterations of calculation by `limit`.
+ sum = n & 1 ? w[i++] * f(B) : 0; // Handle odd n
+ while (i < m) {
+ var Ax = A * x[i];
+ sum += w[i++] * (f(B + Ax) + f(B - Ax));
+ }
+ return A * sum;
+ };
+
+ /**
+ * @name Two.Utils.getCurveFromPoints
+ * @function
+ * @param {Anchor[]} points
+ * @param {Boolean} closed
+ * @description Sets the bezier handles on {@link Anchor}s in the `points` list with estimated values to create a catmull-rom like curve. Used by {@link Two.Path#plot}.
+ */
+ var getCurveFromPoints = function(points, closed) {
+ var cos$5 = Math.cos, sin$5 = Math.sin, tan = Math.tan;
+ var array = [];
+
+ /**
+ * @name Two.Matrix
+ * @class
+ * @param {Number} [a=1] - The value for element at the first column and first row.
+ * @param {Number} [b=0] - The value for element at the second column and first row.
+ * @param {Number} [c=0] - The value for element at the third column and first row.
+ * @param {Number} [d=0] - The value for element at the first column and second row.
+ * @param {Number} [e=1] - The value for element at the second column and second row.
+ * @param {Number} [f=0] - The value for element at the third column and second row.
+ * @param {Number} [g=0] - The value for element at the first column and third row.
+ * @param {Number} [h=0] - The value for element at the second column and third row.
+ * @param {Number} [i=1] - The value for element at the third column and third row.
+ * @description A class to store 3 x 3 transformation matrix information. In addition to storing data `Two.Matrix` has suped up methods for commonplace mathematical operations.
+ * @nota-bene Order is based on how to construct transformation strings for the browser.
+ */
+ function Matrix(a, b, c, d, e, f) {
+
+ /**
+ * @name Two.Matrix#elements
+ * @property {Number[]} - The underlying data stored as an array.
+ */
+ this.elements = new NumArray(9);
+
+ var elements = a;
+ if (!Array.isArray(elements)) {
+ elements = Array.prototype.slice.call(arguments);
+ }
+
+ // initialize the elements with default values.
+ this.identity();
+
+ if (elements.length > 0) {
+ this.set(elements);
+ }
+
+ }
+
+ setMatrix(Matrix);
+
+ _.extend(Matrix, {
+
+ /**
+ * @name Two.Matrix.Identity
+ * @property {Number[]} - A stored reference to the default value of a 3 x 3 matrix.
+ */
+ Identity: [
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
+ ],
+
+ /**
+ * @name Two.Matrix.Multiply
+ * @function
+ * @param {Two.Matrix} A
+ * @param {Two.Matrix} B
+ * @param {Two.Matrix} [C] - An optional matrix to apply the multiplication to.
+ * @returns {Two.Matrix} - If an optional `C` matrix isn't passed then a new one is created and returned.
+ * @description Multiply two matrices together and return the result.
+ */
+ Multiply: function(A, B, C) {
+
+ if (B.length <= 3) { // Multiply Vector
+
+ var x, y, z, e = A;
+
+ var a = B[0] || 0,
+ b = B[1] || 0,
+ c = B[2] || 0;
+
+ // Go down rows first
+ // a, d, g, b, e, h, c, f, i
+
+ x = e[0] * a + e[1] * b + e[2] * c;
+ y = e[3] * a + e[4] * b + e[5] * c;
+ z = e[6] * a + e[7] * b + e[8] * c;
+
+ return { x: x, y: y, z: z };
+
+ }
+
+ var A0 = A[0], A1 = A[1], A2 = A[2];
+ var A3 = A[3], A4 = A[4], A5 = A[5];
+ var A6 = A[6], A7 = A[7], A8 = A[8];
+
+ var B0 = B[0], B1 = B[1], B2 = B[2];
+ var B3 = B[3], B4 = B[4], B5 = B[5];
+ var B6 = B[6], B7 = B[7], B8 = B[8];
+
+ C = C || new NumArray(9);
+
+ C[0] = A0 * B0 + A1 * B3 + A2 * B6;
+ C[1] = A0 * B1 + A1 * B4 + A2 * B7;
+ C[2] = A0 * B2 + A1 * B5 + A2 * B8;
+ C[3] = A3 * B0 + A4 * B3 + A5 * B6;
+ C[4] = A3 * B1 + A4 * B4 + A5 * B7;
+ C[5] = A3 * B2 + A4 * B5 + A5 * B8;
+ C[6] = A6 * B0 + A7 * B3 + A8 * B6;
+ C[7] = A6 * B1 + A7 * B4 + A8 * B7;
+ C[8] = A6 * B2 + A7 * B5 + A8 * B8;
+
+ return C;
+
+ }
+
+ });
+
+ _.extend(Matrix.prototype, Events, {
+
+ constructor: Matrix,
+
+ /**
+ * @name Two.Matrix#manual
+ * @property {Boolean} - Determines whether Two.js automatically calculates the values for the matrix or if the developer intends to manage the matrix.
+ * @nota-bene - Setting to `true` nullifies {@link Two.Shape#translation}, {@link Two.Shape#rotation}, and {@link Two.Shape#scale}.
+ */
+ manual: false,
+
+ /**
+ * @name Two.Matrix#set
+ * @function
+ * @param {Number} a - The value for element at the first column and first row.
+ * @param {Number} b - The value for element at the second column and first row.
+ * @param {Number} c - The value for element at the third column and first row.
+ * @param {Number} d - The value for element at the first column and second row.
+ * @param {Number} e - The value for element at the second column and second row.
+ * @param {Number} f - The value for element at the third column and second row.
+ * @param {Number} g - The value for element at the first column and third row.
+ * @param {Number} h - The value for element at the second column and third row.
+ * @param {Number} i - The value for element at the third column and third row.
+ * @description Set an array of values onto the matrix. Order described in {@link Two.Matrix}.
+ */
+
+ /**
+ * @name Two.Matrix#set
+ * @function
+ * @param {Number[]} a - The array of elements to apply.
+ * @description Set an array of values onto the matrix. Order described in {@link Two.Matrix}.
+ */
+ set: function(a, b, c, d, e, f, g, h, i) {
+
+ var elements;
+
+ if (typeof b === 'undefined') {
+ elements = a;
+ a = elements[0];
+ b = elements[1];
+ c = elements[2];
+ d = elements[3];
+ e = elements[4];
+ f = elements[5];
+ g = elements[6];
+ h = elements[7];
+ i = elements[8];
+ }
+
+ this.elements[0] = a;
+ this.elements[1] = b;
+ this.elements[2] = c;
+ this.elements[3] = d;
+ this.elements[4] = e;
+ this.elements[5] = f;
+ this.elements[6] = g;
+ this.elements[7] = h;
+ this.elements[8] = i;
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#copy
+ * @function
+ * @description Copy the matrix of one to the current instance.
+ */
+ copy: function(m) {
+
+ this.elements[0] = m.elements[0];
+ this.elements[1] = m.elements[1];
+ this.elements[2] = m.elements[2];
+ this.elements[3] = m.elements[3];
+ this.elements[4] = m.elements[4];
+ this.elements[5] = m.elements[5];
+ this.elements[6] = m.elements[6];
+ this.elements[7] = m.elements[7];
+ this.elements[8] = m.elements[8];
+
+ this.manual = m.manual;
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#identity
+ * @function
+ * @description Turn matrix to the identity, like resetting.
+ */
+ identity: function() {
+
+ this.elements[0] = Matrix.Identity[0];
+ this.elements[1] = Matrix.Identity[1];
+ this.elements[2] = Matrix.Identity[2];
+ this.elements[3] = Matrix.Identity[3];
+ this.elements[4] = Matrix.Identity[4];
+ this.elements[5] = Matrix.Identity[5];
+ this.elements[6] = Matrix.Identity[6];
+ this.elements[7] = Matrix.Identity[7];
+ this.elements[8] = Matrix.Identity[8];
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#multiply
+ * @function
+ * @param {Number} a - The scalar to be multiplied.
+ * @description Multiply all components of the matrix against a single scalar value.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Matrix#multiply
+ * @function
+ * @param {Number} a - The x component to be multiplied.
+ * @param {Number} b - The y component to be multiplied.
+ * @param {Number} c - The z component to be multiplied.
+ * @description Multiply all components of a matrix against a 3 component vector.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Matrix#multiply
+ * @function
+ * @param {Number} a - The value at the first column and first row of the matrix to be multiplied.
+ * @param {Number} b - The value at the second column and first row of the matrix to be multiplied.
+ * @param {Number} c - The value at the third column and first row of the matrix to be multiplied.
+ * @param {Number} d - The value at the first column and second row of the matrix to be multiplied.
+ * @param {Number} e - The value at the second column and second row of the matrix to be multiplied.
+ * @param {Number} f - The value at the third column and second row of the matrix to be multiplied.
+ * @param {Number} g - The value at the first column and third row of the matrix to be multiplied.
+ * @param {Number} h - The value at the second column and third row of the matrix to be multiplied.
+ * @param {Number} i - The value at the third column and third row of the matrix to be multiplied.
+ * @description Multiply all components of a matrix against another matrix.
+ * @overloaded
+ */
+ multiply: function(a, b, c, d, e, f, g, h, i) {
+
+ // Multiply scalar
+
+ if (typeof b === 'undefined') {
+
+ this.elements[0] *= a;
+ this.elements[1] *= a;
+ this.elements[2] *= a;
+ this.elements[3] *= a;
+ this.elements[4] *= a;
+ this.elements[5] *= a;
+ this.elements[6] *= a;
+ this.elements[7] *= a;
+ this.elements[8] *= a;
+
+ return this.trigger(Events.Types.change);
+
+ }
+
+ if (typeof d === 'undefined') { // Multiply Vector
+
+ var x, y, z;
+ a = a || 0;
+ b = b || 0;
+ c = c || 0;
+ e = this.elements;
+
+ // Go down rows first
+ // a, d, g, b, e, h, c, f, i
+
+ x = e[0] * a + e[1] * b + e[2] * c;
+ y = e[3] * a + e[4] * b + e[5] * c;
+ z = e[6] * a + e[7] * b + e[8] * c;
+
+ return { x: x, y: y, z: z };
+
+ }
+
+ // Multiple matrix
+
+ var A = this.elements;
+ var B = [a, b, c, d, e, f, g, h, i];
+
+ var A0 = A[0], A1 = A[1], A2 = A[2];
+ var A3 = A[3], A4 = A[4], A5 = A[5];
+ var A6 = A[6], A7 = A[7], A8 = A[8];
+
+ var B0 = B[0], B1 = B[1], B2 = B[2];
+ var B3 = B[3], B4 = B[4], B5 = B[5];
+ var B6 = B[6], B7 = B[7], B8 = B[8];
+
+ this.elements[0] = A0 * B0 + A1 * B3 + A2 * B6;
+ this.elements[1] = A0 * B1 + A1 * B4 + A2 * B7;
+ this.elements[2] = A0 * B2 + A1 * B5 + A2 * B8;
+
+ this.elements[3] = A3 * B0 + A4 * B3 + A5 * B6;
+ this.elements[4] = A3 * B1 + A4 * B4 + A5 * B7;
+ this.elements[5] = A3 * B2 + A4 * B5 + A5 * B8;
+
+ this.elements[6] = A6 * B0 + A7 * B3 + A8 * B6;
+ this.elements[7] = A6 * B1 + A7 * B4 + A8 * B7;
+ this.elements[8] = A6 * B2 + A7 * B5 + A8 * B8;
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#inverse
+ * @function
+ * @param {Two.Matrix} [out] - The optional matrix to apply the inversion to.
+ * @description Return an inverted version of the matrix. If no optional one is passed a new matrix is created and returned.
+ * @description A list of class strings stored if imported / interpreted from an SVG element.
+ */
+ this.classList = [];
+
+ /**
+ * @name Two.Shape#matrix
+ * @property {Two.Matrix}
+ * @description The transformation matrix of the shape.
+ * @nota-bene {@link Two.Shape#translation}, {@link Two.Shape#rotation}, {@link Two.Shape#scale}, {@link Two.Shape#skewX}, and {@link Two.Shape#skewY} apply their values to the matrix when changed. The matrix is what is sent to the renderer to be drawn.
+ */
+ this.matrix = new Matrix();
+
+ /**
+ * @name Two.Shape#translation
+ * @property {Two.Vector} - The x and y value for where the shape is placed relative to its parent.
+ */
+ this.translation = new Vector();
+
+ /**
+ * @name Two.Shape#rotation
+ * @property {Number} - The value in Number for how much the shape is rotated relative to its parent.
+ */
+ this.rotation = 0;
+
+ /**
+ * @name Two.Shape#scale
+ * @property {Number} - The value for how much the shape is scaled relative to its parent.
+ * @nota-bene This value can be replaced with a {@link Two.Vector} to do non-uniform scaling. e.g: `shape.scale = new Two.Vector(2, 1);`
+ */
+ this.scale = 1;
+
+ /**
+ * @name Two.Shape#skewX
+ * @property {Number} - The value in Number for how much the shape is skewed relative to its parent.
+ * @description Skew the shape by an angle in the x axis direction.
+ */
+ this.skewX = 0;
+
+ /**
+ * @name Two.Shape#skewY
+ * @property {Number} - The value in Number for how much the shape is skewed relative to its parent.
+ * @description Skew the shape by an angle in the y axis direction.
+ */
+ this.skewY = 0;
+
+ }
+
+ _.extend(Shape, {
+
+ /**
+ * @name Two.Shape.FlagMatrix
+ * @function
+ * @description Utility function used in conjunction with event handlers to update the flagMatrix of a shape.
+ */
+ FlagMatrix: function() {
+ this._flagMatrix = true;
+ },
+
+ /**
+ * @name Two.Shape.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Shape} to any object. Handy if you'd like to extend the {@link Two.Shape} class on a custom class.
+ * @property {Boolean} - Determines whether the {@link Two.Group#className} need updating.
+ */
+ _flagClassName: false,
+
+ // Underlying Properties
+
+ _id: '',
+
+ /**
+ * @name Two.Shape#_translation
+ * @private
+ * @property {Two.Vector} - The translation values as a {@link Two.Vector}.
+ */
+ _translation: null,
+
+ /**
+ * @name Two.Shape#_rotation
+ * @private
+ * @property {Number} - The rotation value in Number.
+ */
+ _rotation: 0,
+
+ /**
+ * @name Two.Shape#_translation
+ * @private
+ * @property {Two.Vector} - The translation values as a {@link Two.Vector}.
+ */
+ _scale: 1,
+
+ /**
+ * @name Two.Shape#_skewX
+ * @private
+ * @property {Number} - The rotation value in Number.
+ */
+ _skewX: 0,
+
+ /**
+ * @name Two.Shape#_skewY
+ * @private
+ * @property {Number} - The rotation value in Number.
+ */
+ _skewY: 0,
+
+ /**
+ * @name Two.Shape#className
+ * @property {String} - A class to be applied to the element to be compatible with CSS styling.
+ * @nota-bene Only available for the SVG renderer.
+ */
+ _className: '',
+
+ /**
+ * @name Two.Shape#addTo
+ * @function
+ * @param {Two.Group} group - The parent the shape adds itself to.
+ * @description Convenience method to add itself to the scenegraph.
+ */
+ addTo: function(group) {
+ group.add(this);
+ return this;
+ },
+
+ /**
+ * @name Two.Shape#clone
+ * @function
+ * @param {Two.Group} [parent] - Optional argument to automatically add the shape to a scenegraph.
+ * @returns {Two.Shape}
+ * @description Create a new {@link Two.Shape} with the same values as the current shape.
+ */
+ clone: function(parent) {
+
+ var clone = new Shape();
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone._update();
+
+ },
+
+ /**
+ * @name Two.Shape#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ * @description An `Array` like object with additional event propagation on actions. `pop`, `shift`, and `splice` trigger `removed` events. `push`, `unshift`, and `splice` with more than 2 arguments trigger 'inserted'. Finally, `sort` and `reverse` trigger `order` events.
+ */
+ function Collection() {
+
+ Array.call(this);
+
+ if (arguments[0] && Array.isArray(arguments[0])) {
+ if (arguments[0].length > 0) {
+ Array.prototype.push.apply(this, arguments[0]);
+ }
+ } else if (arguments.length > 0) {
+ Array.prototype.push.apply(this, arguments);
+ }
+
+ }
+
+ Collection.prototype = new Array();
+
+ _.extend(Collection.prototype, Events, {
+
+ constructor: Collection,
+
+ pop: function() {
+ var popped = Array.prototype.pop.apply(this, arguments);
+ this.trigger(Events.Types.remove, [popped]);
+ return popped;
+ },
+
+ shift: function() {
+ var shifted = Array.prototype.shift.apply(this, arguments);
+ this.trigger(Events.Types.remove, [shifted]);
+ return shifted;
+ },
+
+ push: function() {
+ var pushed = Array.prototype.push.apply(this, arguments);
+ this.trigger(Events.Types.insert, arguments);
+ return pushed;
+ },
+
+ unshift: function() {
+ var unshifted = Array.prototype.unshift.apply(this, arguments);
+ this.trigger(Events.Types.insert, arguments);
+ return unshifted;
+ },
+
+ splice: function() {
+ var spliced = Array.prototype.splice.apply(this, arguments);
+ * @description A children collection which is accesible both by index and by object `id`.
+ */
+ function Children(children) {
+
+ Collection.apply(this, arguments);
+
+ Object.defineProperty(this, '_events', {
+ value : {},
+ enumerable: false
+ });
+
+ /**
+ * @name Two.Group.Children#ids
+ * @property {Object} - Map of all elements in the list keyed by `id`s.
+ */
+ this.ids = {};
+
+ this.attach(
+ Array.isArray(children) ? children : Array.prototype.slice.call(arguments)
+ );
+
+ this.on(Events.Types.insert, this.attach);
+ this.on(Events.Types.remove, this.detach);
+
+ }
+
+ Children.prototype = new Collection();
+
+ _.extend(Children.prototype, {
+
+ constructor: Children,
+
+ /**
+ * @function
+ * @name Two.Group.Children#attach
+ * @param {Two.Shape[]} children - The objects which extend {@link Two.Shape} to be added.
+ * @description Adds elements to the `ids` map.
+ */
+ attach: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if (child && child.id) {
+ this.ids[child.id] = child;
+ }
+ }
+ return this;
+ },
+
+ /**
+ * @function
+ * @name Two.Group.Children#detach
+ * @param {Two.Shape[]} children - The objects which extend {@link Two.Shape} to be removed.
+ * @description Removes elements to the `ids` map.
+ */
+ detach: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ delete this.ids[children[i].id];
+ }
+ return this;
+ }
+
+ });
+
+ // Constants
+
+ var min$3 = Math.min, max$3 = Math.max;
+
+ /**
+ * @name Two.Group
+ * @class
+ * @extends Two.Shape
+ * @param {Two.Shape[]} [children] - A list of objects that inherit {@link Two.Shape}. For instance, the array could be a {@link Two.Path}, {@link Two.Text}, and {@link Two.RoundedRectangle}.
+ * @description This is the primary class for grouping objects that are then drawn in Two.js. In Illustrator this is a group, in After Effects it would be a Null Object. Whichever the case, the `Two.Group` contains a transformation matrix and commands to style its children, but it by itself doesn't render to the screen.
+ * @nota-bene The {@link Two#scene} is an instance of `Two.Group`.
+ */
+ function Group(children) {
+
+ Shape.call(this, true);
+
+ this._renderer.type = 'group';
+
+ /**
+ * @name Two.Group#additions
+ * @property {Two.Shape[]}
+ * @description An automatically updated list of children that need to be appended to the renderer's scenegraph.
+ */
+ this.additions = [];
+
+ /**
+ * @name Two.Group#subtractions
+ * @property {Two.Shape[]}
+ * @description An automatically updated list of children that need to be removed from the renderer's scenegraph.
+ */
+ this.subtractions = [];
+
+ /**
+ * @name Two.Group#children
+ * @property {Two.Group.Children}
+ * @description A list of all the children in the scenegraph.
+ * @nota-bene Ther order of this list indicates the order each element is rendered to the screen.
+ */
+ this.children = Array.isArray(children) ? children : Array.prototype.slice.call(arguments);
+
+ }
+
+ _.extend(Group, {
+
+ Children: Children,
+
+ /**
+ * @name Two.Group.InsertChildren
+ * @function
+ * @param {Two.Shape[]} children - The objects to be inserted.
+ * @description Cached method to let renderers know children have been added to a {@link Two.Group}.
+ */
+ InsertChildren: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ replaceParent.call(this, children[i], this);
+ }
+ },
+
+ /**
+ * @name Two.Group.RemoveChildren
+ * @function
+ * @param {Two.Shape[]} children - The objects to be removed.
+ * @description Cached method to let renderers know children have been removed from a {@link Two.Group}.
+ */
+ RemoveChildren: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ replaceParent.call(this, children[i]);
+ }
+ },
+
+ /**
+ * @name Two.Group.OrderChildren
+ * @function
+ * @description Cached method to let renderers know order has been updated on a {@link Two.Group}.
+ */
+ OrderChildren: function(children) {
+ this._flagOrder = true;
+ },
+
+ /**
+ * @name Two.Group.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Group}.
+ */
+ Properties: [
+ 'fill',
+ 'stroke',
+ 'linewidth',
+ 'cap',
+ 'join',
+ 'miter',
+
+ 'closed',
+ 'curved',
+ 'automatic'
+ ],
+
+ /**
+ * @name Two.Group.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Group} to any object. Handy if you'd like to extend the {@link Two.Group} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ var properties = Group.Properties;
+
+ Object.defineProperty(object, 'visible', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._visible;
+ },
+
+ set: function(v) {
+ this._flagVisible = this._visible !== v || this._flagVisible;
+ this._visible = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'opacity', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._opacity;
+ },
+
+ set: function(v) {
+ this._flagOpacity = this._opacity !== v || this._flagOpacity;
+ this._opacity = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'beginning', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._beginning;
+ },
+
+ set: function(v) {
+ this._flagBeginning = this._beginning !== v || this._flagBeginning;
+ this._beginning = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'ending', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._ending;
+ },
+
+ set: function(v) {
+ this._flagEnding = this._ending !== v || this._flagEnding;
+ this._ending = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'length', {
+
+ enumerable: true,
+
+ get: function() {
+ if (this._flagLength || this._length <= 0) {
+ this._length = 0;
+ if (!this.children) {
+ return this._length;
+ }
+ for (var i = 0; i < this.children.length; i++) {
+ var child = this.children[i];
+ this._length += child.length;
+ }
+ }
+ return this._length;
+ }
+
+ });
+
+ Shape.MakeObservable(object);
+ Group.MakeGetterSetters(object, properties);
+
+ Object.defineProperty(object, 'children', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._children;
+ },
+
+ set: function(children) {
+
+ var insertChildren = Group.InsertChildren.bind(this);
+ var removeChildren = Group.RemoveChildren.bind(this);
+ var orderChildren = Group.OrderChildren.bind(this);
+ * @param {Two.Group} group - The group to apply getters and setters.
+ * @param {String} key - The key which will become a property on the group.
+ * @description Convenience method to apply getter / setter logic specific to how `Two.Group`s trickle down styles to their children. Used in {@link Two.Group.MakeObservable}.
+ */
+ MakeGetterSetter: function(group, key) {
+
+ var secret = '_' + key;
+
+ Object.defineProperty(group, key, {
+
+ enumerable: true,
+
+ get: function() {
+ return this[secret];
+ },
+
+ set: function(v) {
+ this[secret] = v;
+ // Trickle down styles
+ for (var i = 0; i < this.children.length; i++) {
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what all child shapes should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _fill: '#fff',
+
+ /**
+ * @name Two.Group#stroke
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what all child shapes should be outlined in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _stroke: '#000',
+
+ /**
+ * @name Two.Group#linewidth
+ * @property {Number} - The thickness in pixels of the stroke for all child shapes.
+ */
+ _linewidth: 1.0,
+
+ /**
+ * @name Two.Group#opacity
+ * @property {Number} - The opaqueness of all child shapes.
+ * @nota-bene Becomes multiplied by the individual child's opacity property.
+ */
+ _opacity: 1.0,
+
+ /**
+ * @name Two.Group#visible
+ * @property {Boolean} - Display the path or not.
+ * @nota-bene For {@link Two.CanvasRenderer} and {@link Two.WebGLRenderer} when set to false all updating is disabled improving performance dramatically with many objects in the scene.
+ * @property {Boolean} - Determines whether a final line is drawn between the final point in the `vertices` array and the first point of all child shapes.
+ */
+ _closed: true,
+
+ /**
+ * @name Two.Group#curved
+ * @property {Boolean} - When the child's path is `automatic = true` this boolean determines whether the lines between the points are curved or not.
+ */
+ _curved: false,
+
+ /**
+ * @name Two.Group#automatic
+ * @property {Boolean} - Determines whether or not Two.js should calculate curves, lines, and commands automatically for you or to let the developer manipulate them for themselves.
+ */
+ _automatic: true,
+
+ /**
+ * @name Two.Group#beginning
+ * @property {Number} - Number between zero and one to state the beginning of where the path is rendered.
+ * @description {@link Two.Group#beginning} is a percentage value that represents at what percentage into all child shapes should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Group#ending}.
+ */
+ _beginning: 0,
+
+ /**
+ * @name Two.Group#ending
+ * @property {Number} - Number between zero and one to state the ending of where the path is rendered.
+ * @description {@link Two.Group#ending} is a percentage value that represents at what percentage into all child shapes should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Group#beginning}.
+ */
+ _ending: 1.0,
+
+ /**
+ * @name Two.Group#length
+ * @property {Number} - The sum of distances between all child lengths.
+ */
+ _length: 0,
+
+ /**
+ * @name Two.Group#mask
+ * @property {Two.Shape} - The Two.js object to clip from a group's rendering.
+ */
+ _mask: null,
+
+ /**
+ * @name Two.Group#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Group}
+ * @description Create a new instance of {@link Two.Group} with the same properties of the current group.
+ */
+ clone: function(parent) {
+
+ // /**
+ // * TODO: Group has a gotcha in that it's at the moment required to be bound to
+ // * an instance of two in order to add elements correctly. This needs to
+ // * be rethought and fixed.
+ // */
+
+ var clone = new Group();
+ var children = this.children.map(function(child) {
+ return child.clone();
+ });
+
+ clone.add(children);
+
+ clone.opacity = this.opacity;
+
+ if (this.mask) {
+ clone.mask = this.mask;
+ }
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.className = this.className;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone._update();
+
+ },
+
+ /**
+ * @name Two.Group#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the group.
+ for (var i = 0; i < this.children.length; i++) {
+ var child = this.children[i];
+ if (child.isShape) {
+ child.translation.x -= cx;
+ child.translation.y -= cy;
+ }
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Group#getById
+ * @function
+ * @description Recursively search for id. Returns the first element found.
+ * @returns {Two.Shape} - Or `null` if nothing is found.
+ */
+ getById: function (id) {
+ var found = null;
+ function search(node) {
+ if (node.id === id) {
+ return node;
+ } else if (node.children) {
+ for (var i = 0; i < node.children.length; i++) {
+ found = search(node.children[i]);
+ if (found) {
+ return found;
+ }
+ }
+ }
+ return null;
+ }
+ return search(this);
+ },
+
+ /**
+ * @name Two.Group#getByClassName
+ * @function
+ * @description Recursively search for classes. Returns an array of matching elements.
+ * @returns {Two.Shape[]} - Or empty array if nothing is found.
+ */
+ getByClassName: function(className) {
+ var found = [];
+ function search(node) {
+ if (Array.prototype.indexOf.call(node.classList, className) >= 0) {
+ found.push(node);
+ }
+ if (node.children) {
+ for (var i = 0; i < node.children.length; i++) {
+ var child = node.children[i];
+ search(child);
+ }
+ }
+ return found;
+ }
+ return search(this);
+ },
+
+ /**
+ * @name Two.Group#getByType
+ * @function
+ * @description Recursively search for children of a specific type, e.g. {@link Two.Path}. Pass a reference to this type as the param. Returns an array of matching elements.
+ * @returns {Two.Shape[]} - Empty array if nothing is found.
+ */
+ getByType: function(type) {
+ var found = [];
+ function search(node) {
+ if (node instanceof type) {
+ found.push(node);
+ }
+ if (node.children) {
+ for (var i = 0; i < node.children.length; i++) {
+ var child = node.children[i];
+ search(child);
+ }
+ }
+ return found;
+ }
+ return search(this);
+ },
+
+ /**
+ * @name Two.Group#add
+ * @function
+ * @param {Two.Shape[]} objects - An array of objects to be added. Can be also be supplied as individual arguments.
+ * @description Add objects to the group.
+ */
+ add: function(objects) {
+
+ // Allow to pass multiple objects either as array or as multiple arguments
+ // If it's an array also create copy of it in case we're getting passed
+ * @description Apply `noFill` method to all child shapes.
+ */
+ noFill: function() {
+ this.children.forEach(function(child) {
+ child.noFill();
+ });
+ return this;
+ },
+
+ /**
+ * @name Two.Group#noStroke
+ * @function
+ * @description Apply `noStroke` method to all child shapes.
+ */
+ noStroke: function() {
+ this.children.forEach(function(child) {
+ child.noStroke();
+ });
+ return this;
+ },
+
+ /**
+ * @name Two.Group#subdivide
+ * @function
+ * @description Apply `subdivide` method to all child shapes.
+ */
+ subdivide: function() {
+ var args = arguments;
+ this.children.forEach(function(child) {
+ child.subdivide.apply(child, args);
+ });
+ return this;
+ },
+
+ /**
+ * @name Two.Group#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ var i, l, child;
+
+ if (this._flagBeginning || this._flagEnding) {
+
+ var beginning = Math.min(this._beginning, this._ending);
+ var ending = Math.max(this._beginning, this._ending);
+ * @param {Object} [parameters] - This object is inherited when constructing a new instance of {@link Two}.
+ * @param {Element} [parameters.domElement] - The `<canvas />` to draw to. If none given a new one will be constructed.
+ * @param {Boolean} [parameters.overdraw] - Determines whether the canvas should clear the background or not. Defaults to `true`.
+ * @param {Boolean} [parameters.smoothing=true] - Determines whether the canvas should antialias drawing. Set it to `false` when working with pixel art. `false` can lead to better performance, since it would use a cheaper interpolation algorithm.
+ * @description This class is used by {@link Two} when constructing with `type` of `Two.Types.canvas`. It takes Two.js' scenegraph and renders it to a `<canvas />`.
+ */
+ function Renderer$2(params) {
+
+ // It might not make a big difference on GPU backed canvases.
+ var smoothing = (params.smoothing !== false);
+
+ /**
+ * @name Two.CanvasRenderer#domElement
+ * @property {Element} - The `<canvas />` associated with the Two.js scene.
+ function renderArcEstimate(ctx, ox, oy, rx, ry, startAngle, endAngle, clockwise, xAxisRotation) {
+
+ var epsilon = Curve.Tolerance.epsilon;
+ var deltaAngle = endAngle - startAngle;
+ var samePoints = Math.abs(deltaAngle) < epsilon;
+
+ // ensures that deltaAngle is 0 .. 2 PI
+ deltaAngle = mod(deltaAngle, TWO_PI$5);
+
+ if (deltaAngle < epsilon) {
+
+ if (samePoints) {
+
+ deltaAngle = 0;
+
+ } else {
+
+ deltaAngle = TWO_PI$5;
+
+ }
+
+ }
+
+ if (clockwise === true && ! samePoints) {
+
+ if (deltaAngle === TWO_PI$5) {
+
+ deltaAngle = - TWO_PI$5;
+
+ } else {
+
+ deltaAngle = deltaAngle - TWO_PI$5;
+
+ }
+
+ }
+
+ for (var i = 0; i < Constants.Resolution; i++) {
+
+ var t = i / (Constants.Resolution - 1);
+
+ var angle = startAngle + t * deltaAngle;
+ var x = ox + rx * Math.cos(angle);
+ var y = oy + ry * Math.sin(angle);
+
+ if (xAxisRotation !== 0) {
+
+ var cos = Math.cos(xAxisRotation);
+ var sin = Math.sin(xAxisRotation);
+
+ var tx = x - ox;
+ var ty = y - oy;
+
+ // Rotate the point about the center of the ellipse.
+ x = tx * cos - ty * sin + ox;
+ y = tx * sin + ty * cos + oy;
+
+ }
+
+ ctx.lineTo(x, y);
+
+ }
+
+ }
+
+ function svgAngle(ux, uy, vx, vy) {
+
+ var dot = ux * vx + uy * vy;
+ var len = sqrt(ux * ux + uy * uy) * sqrt(vx * vx + vy * vy);
+ // floating point precision, slightly over values appear
+ var ang = acos(max$2(-1, min$2(1, dot / len)));
+ if ((ux * vy - uy * vx) < 0) {
+ ang = - ang;
+ }
+
+ return ang;
+
+ }
+
+ var CanvasShim = {
+
+ Image: null,
+
+ isHeadless: false,
+
+ /**
+ * @name Two.Utils.shim
+ * @function
+ * @param {canvas} canvas - The instanced `Canvas` object provided by `node-canvas`.
+ * @param {Image} [Image] - The prototypical `Image` object provided by `node-canvas`. This is only necessary to pass if you're going to load bitmap imagery.
+ * @returns {canvas} Returns the instanced canvas object you passed from with additional attributes needed for Two.js.
+ * @description Convenience method for defining all the dependencies from the npm package `node-canvas`. See [node-canvas](https://github.com/Automattic/node-canvas) for additional information on setting up HTML5 `<canvas />` drawing in a node.js environment.
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = root$1.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+ }
+
+ return request;
+
+ }
+
+ };
+
+ var temp = (root$1.document ? root$1.document.createElement('div') : {});
+ temp.id = 'help-two-load';
+
+ Object.defineProperty(dom, 'temp', {
+ enumerable: true,
+ get: function() {
+ if (_.isElement(temp) && !root$1.document.head.contains(temp)) {
+ _.extend(temp.style, {
+ display: 'none'
+ });
+ root$1.document.head.appendChild(temp);
+ }
+ return temp;
+ }
+ });
+
+ /**
+ * @name Two.Utils.Error
+ * @class
+ * @description Custom error throwing for Two.js specific identification.
+ */
+ function TwoError(message) {
+ this.name = 'Two.js';
+ this.message = message;
+ }
+
+ TwoError.prototype = new Error();
+
+ _.extend(TwoError.prototype, {
+ constructor: TwoError
+ });
+
+ /**
+ * @name Two.Utils.defineGetterSetter
+ * @function
+ * @this Two#
+ * @param {String} property - The property to add an enumerable getter / setter to.
+ * @description Convenience function to setup the flag based getter / setter that most properties are defined as in Two.js.
+ */
+ var defineGetterSetter = function(property) {
+
+ var object = this;
+ var secret = '_' + property;
+ var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);
+
+ Object.defineProperty(object, property, {
+ enumerable: true,
+ get: function() {
+ return this[secret];
+ },
+ set: function(v) {
+ this[secret] = v;
+ this[flag] = true;
+ }
+ });
+
+ };
+
+ /**
+ * @name Two.Registry
+ * @class
+ * @description An arbitrary class to manage a directory of things. Mainly used for keeping tabs of textures in Two.js.
+ */
+ function Registry() {
+
+ this.map = {};
+
+ }
+
+ _.extend(Registry.prototype, {
+
+ constructor: Registry,
+
+ /**
+ * @name Two.Registry#add
+ * @function
+ * @param {String} id - A unique identifier.
+ * @param value - Any type of variable to be registered to the directory.
+ * @description Adds any value to the directory. Assigned by the `id`.
+ */
+ add: function(id, obj) {
+ this.map[id] = obj;
+ return this;
+ },
+
+ /**
+ * @name Two.Registry#remove
+ * @function
+ * @param {String} id - A unique identifier.
+ * @description Remove any value from the directory by its `id`.
+ */
+ remove: function(id) {
+ delete this.map[id];
+ return this;
+ },
+
+ /**
+ * @name Two.Registry#get
+ * @function
+ * @param {String} id - A unique identifier.
+ * @returns {?Object} The associated value. If unavailable then `undefined` is returned.
+ * @description Get a registered value by its `id`.
+ */
+ get: function(id) {
+ return this.map[id];
+ },
+
+ /**
+ * @name Two.Registry#contains
+ * @function
+ * @param {String} id - A unique identifier.
+ * @returns {Boolean}
+ * @description Convenience method to see if a value is registered to an `id` already.
+ */
+ contains: function(id) {
+ return id in this.map;
+ }
+
+ });
+
+ /**
+ * @name Two.Stop
+ * @class
+ * @param {Number} [offset] - The offset percentage of the stop represented as a zero-to-one value. Default value flip flops from zero-to-one as new stops are created.
+ * @param {String} [color] - The color of the stop. Default value flip flops from white to black as new stops are created.
+ * @param {Number} [opacity] - The opacity value. Default value is 1, cannot be lower than 0.
+ * @nota-bene Used specifically in conjunction with {@link Two.Gradient}s to control color graduation.
+ */
+ function Stop(offset, color, opacity) {
+
+ /**
+ * @name Two.Stop#renderer
+ * @property {Object}
+ * @description Object access to store relevant renderer specific variables. Warning: manipulating this object can create unintended consequences.
+ * @nota-bene With the {@link Two.SvgRenderer} you can access the underlying SVG element created via `shape.renderer.elem`.
+ */
+ this.renderer = {};
+ this._renderer.type = 'stop';
+
+ /**
+ * @name Two.Stop#offset
+ * @property {Number} - The offset percentage of the stop represented as a zero-to-one value.
+ this.color = (typeof color === 'string') ? color
+ : Stop.Index <= 0 ? '#fff' : '#000';
+
+ Stop.Index = (Stop.Index + 1) % 2;
+
+ }
+
+ _.extend(Stop, {
+
+ /**
+ * @name Two.Stop.Index
+ * @property {Number} - The current index being referenced for calculating a stop's default offset value.
+ */
+ Index: 0,
+
+ /**
+ * @name Two.Stop.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Stop}.
+ */
+ Properties: [
+ 'offset',
+ 'opacity',
+ 'color'
+ ],
+
+ /**
+ * @name Two.Stop.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Stop} to any object. Handy if you'd like to extend the {@link Two.Stop} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ _.each(Stop.Properties, function(property) {
+
+ var object = this;
+ var secret = '_' + property;
+ var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);
+
+ Object.defineProperty(object, property, {
+ enumerable: true,
+ get: function() {
+ return this[secret];
+ },
+ set: function(v) {
+ this[secret] = v;
+ this[flag] = true;
+ if (this.parent) {
+ this.parent._flagStops = true;
+ }
+ }
+ });
+
+ }, object);
+
+ Object.defineProperty(object, 'renderer', {
+
+ enumerable: false,
+
+ get: function() {
+ return this._renderer;
+ },
+
+ set: function(obj) {
+ this._renderer = obj;
+ }
+
+ });
+
+ }
+
+ });
+
+ _.extend(Stop.prototype, Events, {
+
+ constructor: Stop,
+
+ /**
+ * @name Two.Stop#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Stop}
+ * @description Create a new instance of {@link Two.Stop} with the same properties of the current path.
+ */
+ clone: function() {
+
+ var clone = new Stop();
+
+ _.each(Stop.Properties, function(property) {
+ clone[property] = this[property];
+ }, this);
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Stop#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = {};
+
+ _.each(Stop.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.Stop#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @param {Two.Stop[]} [stops] - A list of {@link Two.Stop}s that contain the gradient fill pattern for the gradient.
+ * @description This is the base class for constructing different types of gradients with Two.js. The two common gradients are {@link Two.LinearGradient} and {@link Two.RadialGradient}.
+ */
+ function Gradient(stops) {
+
+ /**
+ * @name Two.Gradient#renderer
+ * @property {Object}
+ * @description Object access to store relevant renderer specific variables. Warning: manipulating this object can create unintended consequences.
+ * @nota-bene With the {@link Two.SvgRenderer} you can access the underlying SVG element created via `shape.renderer.elem`.
+ */
+ this.renderer = {};
+ this._renderer.type = 'gradient';
+
+ /**
+ * @name Two.Gradient#id
+ * @property {String} - Session specific unique identifier.
+ * @nota-bene In the {@link Two.SvgRenderer} change this to change the underlying SVG element's id too.
+ * @property {String} - Indicates what happens if the gradient starts or ends inside the bounds of the target rectangle. Possible values are `'pad'`, `'reflect'`, and `'repeat'`.
+ * @see {@link https://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementSpreadMethodAttribute} for more information
+ */
+ this.spread = 'pad';
+
+ /**
+ * @name Two.Gradient#stops
+ * @property {Two.Stop[]} - An ordered list of {@link Two.Stop}s for rendering the gradient.
+ */
+ if (stops) {
+ this.stops = stops;
+ }
+
+ }
+
+ _.extend(Gradient, {
+
+ /**
+ * @name Two.Gradient.Stop
+ * @see {@link Two.Stop}
+ */
+ Stop: Stop,
+
+ /**
+ * @name Two.Gradient.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Gradient}.
+ */
+ Properties: [
+ 'spread'
+ ],
+
+ /**
+ * @name Two.Gradient.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Gradient} to any object. Handy if you'd like to extend the {@link Two.Gradient} class on a custom class.
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Gradient}
+ * @description Create a new instance of {@link Two.Gradient} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var stops = this.stops.map(function(s) {
+ return s.clone();
+ });
+
+ var clone = new Gradient(stops);
+
+ _.each(Gradient.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Gradient#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = {
+ stops: this.stops.map(function(s) {
+ return s.toObject();
+ })
+ };
+
+ _.each(Gradient.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.Gradient#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagSpread || this._flagStops) {
+ this.trigger(Events.Types.change);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Gradient#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagSpread = this._flagStops = false;
+
+ return this;
+
+ }
+
+ });
+
+ Gradient.MakeObservable(Gradient.prototype);
+
+ /**
+ * @name Two.LinearGradient
+ * @class
+ * @extends Two.Gradient
+ * @param {Number} [x1=0] - The x position of the first end point of the linear gradient.
+ * @param {Number} [y1=0] - The y position of the first end point of the linear gradient.
+ * @param {Number} [x2=0] - The x position of the second end point of the linear gradient.
+ * @param {Number} [y2=0] - The y position of the second end point of the linear gradient.
+ * @param {Two.Stop[]} [stops] - A list of {@link Two.Stop}s that contain the gradient fill pattern for the gradient.
+ * @nota-bene The linear gradient lives within the space of the parent object's matrix space.
+ */
+ function LinearGradient(x1, y1, x2, y2, stops) {
+
+ Gradient.call(this, stops);
+
+ this._renderer.type = 'linear-gradient';
+
+ var flagEndPoints = LinearGradient.FlagEndPoints.bind(this);
+
+ /**
+ * @name Two.LinearGradient#left
+ * @property {Two.Vector} - The x and y value for where the first end point is placed on the canvas.
+ */
+ this.left = new Vector().bind(Events.Types.change, flagEndPoints);
+ /**
+ * @name Two.LinearGradient#right
+ * @property {Two.Vector} - The x and y value for where the second end point is placed on the canvas.
+ */
+ this.right = new Vector().bind(Events.Types.change, flagEndPoints);
+
+ if (typeof x1 === 'number') {
+ this.left.x = x1;
+ }
+ if (typeof y1 === 'number') {
+ this.left.y = y1;
+ }
+ if (typeof x2 === 'number') {
+ this.right.x = x2;
+ }
+ if (typeof y2 === 'number') {
+ this.right.y = y2;
+ }
+
+ }
+
+ _.extend(LinearGradient, {
+
+ /**
+ * @name Two.LinearGradient.Stop
+ * @see {@link Two.Stop}
+ */
+ Stop: Stop,
+
+ /**
+ * @name Two.LinearGradient.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.LinearGradient} to any object. Handy if you'd like to extend the {@link Two.LinearGradient} class on a custom class.
+ */
+ MakeObservable: function(object) {
+ Gradient.MakeObservable(object);
+ },
+
+ /**
+ * @name Two.LinearGradient.FlagEndPoints
+ * @function
+ * @description Cached method to let renderers know end points have been updated on a {@link Two.LinearGradient}.
+ * @property {Boolean} - Determines whether the {@link Two.LinearGradient#left} or {@link Two.LinearGradient#right} changed and needs to update.
+ */
+ _flagEndPoints: false,
+
+ /**
+ * @name Two.LinearGradient#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Gradient}
+ * @description Create a new instance of {@link Two.LinearGradient} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var stops = this.stops.map(function(stop) {
+ return stop.clone();
+ });
+
+ var clone = new LinearGradient(this.left._x, this.left._y,
+ this.right._x, this.right._y, stops);
+
+ _.each(Gradient.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.LinearGradient#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = Gradient.prototype.toObject.call(this);
+
+ result.left = this.left.toObject();
+ result.right = this.right.toObject();
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.LinearGradient#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagEndPoints || this._flagSpread || this._flagStops) {
+ this.trigger(Events.Types.change);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.LinearGradient#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @param {Number} [x=0] - The x position of the origin of the radial gradient.
+ * @param {Number} [y=0] - The y position of the origin of the radial gradient.
+ * @param {Number} [radius=0] - The radius of the radial gradient.
+ * @param {Two.Stop[]} [stops] - A list of {@link Two.Stop}s that contain the gradient fill pattern for the gradient.
+ * @param {Number} [focalX=0] - The x position of the focal point on the radial gradient.
+ * @param {Number} [focalY=0] - The y position of the focal point on the radial gradient.
+ * @nota-bene The radial gradient lives within the space of the parent object's matrix space.
+ */
+ function RadialGradient(cx, cy, r, stops, fx, fy) {
+
+ Gradient.call(this, stops);
+
+ this._renderer.type = 'radial-gradient';
+
+ /**
+ * @name Two.RadialGradient#center
+ * @property {Two.Vector} - The x and y value for where the origin of the radial gradient is.
+ */
+ this.center = new Vector()
+ .bind(Events.Types.change, (function() {
+ this._flagCenter = true;
+ }).bind(this));
+
+ this.radius = typeof r === 'number' ? r : 20;
+
+ /**
+ * @name Two.RadialGradient#focal
+ * @property {Two.Vector} - The x and y value for where the focal point of the radial gradient is.
+ * @nota-bene This effects the spray or spread of the radial gradient.
+ */
+ this.focal = new Vector()
+ .bind(Events.Types.change, (function() {
+ this._flagFocal = true;
+ }).bind(this));
+
+ if (typeof cx === 'number') {
+ this.center.x = cx;
+ }
+ if (typeof cy === 'number') {
+ this.center.y = cy;
+ }
+
+ this.focal.copy(this.center);
+
+ if (typeof fx === 'number') {
+ this.focal.x = fx;
+ }
+ if (typeof fy === 'number') {
+ this.focal.y = fy;
+ }
+
+ }
+
+ _.extend(RadialGradient, {
+
+ /**
+ * @name Two.RadialGradient.Stop
+ * @see {@link Two.Stop}
+ */
+ Stop: Stop,
+
+ /**
+ * @name Two.RadialGradient.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.RadialGradient}.
+ */
+ Properties: [
+ 'radius'
+ ],
+
+ /**
+ * @name Two.RadialGradient.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.RadialGradient} to any object. Handy if you'd like to extend the {@link Two.RadialGradient} class on a custom class.
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = Gradient.prototype.toObject.call(this);
+
+ _.each(RadialGradient.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ result.center = this.center.toObject();
+ result.focal = this.focal.toObject();
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.RadialGradient#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagRadius || this._flatCenter || this._flagFocal
+ || this._flagSpread || this._flagStops) {
+ this.trigger(Events.Types.change);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.RadialGradient#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @param {String|HTMLImageElement} [src] - The URL path to an image file or an `<img />` element.
+ * @param {Function} [callback] - An optional callback function once the image has been loaded.
+ * @description Fundamental to work with bitmap data, a.k.a. pregenerated imagery, in Two.js. Supported formats include jpg, png, gif, and tiff. See {@link Two.Texture.RegularExpressions} for a full list of supported formats.
+ */
+ function Texture(src, callback) {
+
+ /**
+ * @name Two.Texture#renderer
+ * @property {Object}
+ * @description Object access to store relevant renderer specific variables. Warning: manipulating this object can create unintended consequences.
+ * @nota-bene With the {@link Two.SvgRenderer} you can access the underlying SVG element created via `shape.renderer.elem`.
+ * @property {Two.Vector} - A two-component vector describing any pixel offset of the texture when applied to a {@link Two.Path}.
+ */
+ this.offset = new Vector();
+
+ if (typeof callback === 'function') {
+ var loaded = (function() {
+ this.unbind(Events.Types.load, loaded);
+ if (typeof callback === 'function') {
+ callback();
+ }
+ }).bind(this);
+ this.bind(Events.Types.load, loaded);
+ }
+
+ /**
+ * @name Two.Texture#src
+ * @property {String} - The URL path to the image data.
+ * @nota-bene This property is ultimately serialized in a {@link Two.Registry} to cache retrieval.
+ */
+ if (typeof src === 'string') {
+ this.src = src;
+ } else if (typeof src === 'object') {
+ var elemString = Object.prototype.toString.call(src);
+ if (
+ elemString === '[object HTMLImageElement]' ||
+ elemString === '[object HTMLCanvasElement]' ||
+ elemString === '[object HTMLVideoElement]' ||
+ elemString === '[object Image]'
+ ) {
+ /**
+ * @name Two.Texture#image
+ * @property {Element} - The corresponding DOM Element of the texture. Can be a `<img />`, `<canvas />`, or `<video />` element. See {@link Two.Texture.RegularExpressions} for a full list of supported elements.
+ * @nota-bene In headless environments this is a `Canvas.Image` object. See {@link https://github.com/Automattic/node-canvas} for more information on headless image objects.
+ */
+ this.image = src;
+ }
+ }
+
+ this._update();
+
+ }
+
+ _.extend(Texture, {
+
+ /**
+ * @name Two.Texture.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Texture}.
+ */
+ Properties: [
+ 'id',
+ 'src',
+ 'loaded',
+ 'repeat'
+ ],
+
+ /**
+ * @name Two.Texture.RegularExpressions
+ * @property {Object} - A map of compatible DOM Elements categorized by media format.
+ */
+ RegularExpressions: regex$1,
+
+ /**
+ * @name Two.Texture.ImageRegistry
+ * @property {Two.Registry} - A canonical listing of image data used in a single session of Two.js.
+ * @nota-bene This object is used to cache image data between different textures.
+ */
+ ImageRegistry: new Registry(),
+
+ /**
+ * @name Two.Texture.getAbsoluteURL
+ * @property {Function} - Serializes a URL as an absolute path for canonical attribution in {@link Two.ImageRegistry}.
+ * @param {String} path
+ * @returns {String} - The serialized absolute path.
+ */
+ getAbsoluteURL: function(path) {
+ if (!anchor) {
+ // TODO: Fix for headless environments
+ return path;
+ }
+ anchor.href = path;
+ return anchor.href;
+ },
+
+ /**
+ * @name Two.Texture.loadHeadlessBuffer
+ * @property {Function} - Loads an image as a buffer in headless environments.
+ * @param {Two.Texture} texture - The {@link Two.Texture} to be loaded.
+ * @param {Function} loaded - The callback function to be triggered once the image is loaded.
+ * @nota-bene - This function uses node's `fs.readFileSync` to spoof the `<img />` loading process in the browser.
+ */
+ loadHeadlessBuffer: function(texture, loaded) {
+
+ texture.image.onload = loaded;
+ texture.image.src = texture.src;
+
+ },
+
+ /**
+ * @name Two.Texture.getTag
+ * @property {Function} - Retrieves the tag name of an image, video, or canvas node.
+ * @param {HTMLImageElement} - The image to infer the tag name from.
+ * @returns {String} - Returns the tag name of an image, video, or canvas node.
+ * @property {Function} - Convenience function to set {@link Two.Texture#image} properties with canonincal versions set in {@link Two.Texture.ImageRegistry}.
+ * @param {String} src - The URL path of the image.
+ * @returns {HTMLImageElement} - Returns either a cached version of the image or a new one that is registered in {@link Two.Texture.ImageRegistry}.
+ */
+ getImage: function(src) {
+
+ var absoluteSrc = Texture.getAbsoluteURL(src);
+
+ if (Texture.ImageRegistry.contains(absoluteSrc)) {
+ return Texture.ImageRegistry.get(absoluteSrc);
+ }
+
+ var image;
+
+ if (CanvasShim.Image) {
+
+ // TODO: Fix for headless environments
+ image = new CanvasShim.Image();
+ Renderer$2.Utils.shim(image, 'img');
+
+ } else if (root$1.document) {
+
+ if (regex$1.video.test(absoluteSrc)) {
+ image = document.createElement('video');
+ } else {
+ image = document.createElement('img');
+ }
+
+ } else {
+
+ console.warn('Two.js: no prototypical image defined for Two.Texture');
+
+ }
+
+ image.crossOrigin = 'anonymous';
+
+ return image;
+
+ },
+
+ /**
+ * @name Two.Register
+ * @interface
+ * @description A collection of functions to register different types of textures. Used internally by a {@link Two.Texture}.
+ * @description Cached method to let renderers know `offset` has been updated on a {@link Two.Texture}.
+ */
+ FlagOffset: function() {
+ this._flagOffset = true;
+ },
+
+ /**
+ * @name Two.Texture.FlagScale
+ * @function
+ * @description Cached method to let renderers know `scale` has been updated on a {@link Two.Texture}.
+ */
+ FlagScale: function() {
+ this._flagScale = true;
+ },
+
+ /**
+ * @name Two.Texture.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Texture} to any object. Handy if you'd like to extend or inherit the {@link Two.Texture} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagSrc || this._flagImage) {
+
+ this.trigger(Events.Types.change);
+
+ if (this._flagSrc || this._flagImage) {
+ this.loaded = false;
+ Texture.load(this, (function() {
+ this.loaded = true;
+ this
+ .trigger(Events.Types.change)
+ .trigger(Events.Types.load);
+ }).bind(this));
+ }
+
+ }
+
+ if (this._image && this._image.readyState >= 4) {
+ this._flagVideo = true;
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Texture#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @param {Two.Anchor[]} [vertices] - A list of {@link Two.Anchor}s that represent the order and coordinates to construct the rendered shape.
+ * @param {Boolean} [closed=false] - Describes whether the shape is closed or open.
+ * @param {Boolean} [curved=false] - Describes whether the shape automatically calculates bezier handles for each vertex.
+ * @param {Boolean} [manual=false] - Describes whether the developer controls how vertices are plotted or if Two.js automatically plots coordinates based on closed and curved booleans.
+ * @description This is the primary primitive class for creating all drawable shapes in Two.js. Unless specified methods return their instance of `Two.Path` for the purpose of chaining.
+ */
+ function Path(vertices, closed, curved, manual) {
+ * @property {Boolean} - Determines whether a final line is drawn between the final point in the `vertices` array and the first point.
+ */
+ this._closed = !!closed;
+
+ /**
+ * @name Two.Path#curved
+ * @property {Boolean} - When the path is `automatic = true` this boolean determines whether the lines between the points are curved or not.
+ */
+ this._curved = !!curved;
+
+ /**
+ * @name Two.Path#beginning
+ * @property {Number} - Number between zero and one to state the beginning of where the path is rendered.
+ * @description {@link Two.Path#beginning} is a percentage value that represents at what percentage into the path should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Path#ending}.
+ */
+ this.beginning = 0;
+
+ /**
+ * @name Two.Path#ending
+ * @property {Number} - Number between zero and one to state the ending of where the path is rendered.
+ * @description {@link Two.Path#ending} is a percentage value that represents at what percentage into the path should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Path#beginning}.
+ */
+ this.ending = 1;
+
+ // Style properties
+
+ /**
+ * @name Two.Path#fill
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the path should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ this.fill = '#fff';
+
+ /**
+ * @name Two.Path#stroke
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the path should be outlined in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ this.stroke = '#000';
+
+ /**
+ * @name Two.Path#linewidth
+ * @property {Number} - The thickness in pixels of the stroke.
+ */
+ this.linewidth = 1.0;
+
+ /**
+ * @name Two.Path#opacity
+ * @property {Number} - The opaqueness of the path.
+ * @nota-bene Can be used in conjunction with CSS Colors that have an alpha value.
+ */
+ this.opacity = 1.0;
+
+ /**
+ * @name Two.Path#className
+ * @property {String} - A class to be applied to the element to be compatible with CSS styling.
+ * @nota-bene Only available for the SVG renderer.
+ */
+ this.className = '';
+
+ /**
+ * @name Two.Path#visible
+ * @property {Boolean} - Display the path or not.
+ * @nota-bene For {@link Two.CanvasRenderer} and {@link Two.WebGLRenderer} when set to false all updating is disabled improving performance dramatically with many objects in the scene.
+ * @property {Two.Anchor[]} - An ordered list of anchor points for rendering the path.
+ * @description A list of {@link Two.Anchor} objects that consist of what form the path takes.
+ * @nota-bene The array when manipulating is actually a {@link Two.Collection}.
+ */
+ this.vertices = vertices;
+
+ /**
+ * @name Two.Path#automatic
+ * @property {Boolean} - Determines whether or not Two.js should calculate curves, lines, and commands automatically for you or to let the developer manipulate them for themselves.
+ */
+ this.automatic = !manual;
+
+ /**
+ * @name Two.Path#dashes
+ * @property {Number[]} - Array of numbers. Odd indices represent dash length. Even indices represent dash space.
+ * @description A list of numbers that represent the repeated dash length and dash space applied to the stroke of the text.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray} for more information on the SVG stroke-dasharray attribute.
+ */
+ this.dashes = [];
+
+ /**
+ * @name Two.Path#dashes#offset
+ * @property {Number} - A number in pixels to offset {@link Two.Path#dashes} display.
+ */
+ this.dashes.offset = 0;
+
+ }
+
+ _.extend(Path, {
+
+ /**
+ * @name Two.Path.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Path}.
+ */
+ Properties: [
+ 'fill',
+ 'stroke',
+ 'linewidth',
+ 'opacity',
+ 'visible',
+ 'cap',
+ 'join',
+ 'miter',
+
+ 'closed',
+ 'curved',
+ 'automatic',
+ 'beginning',
+ 'ending'
+ ],
+
+ Utils: {
+ getCurveLength: getCurveLength
+ },
+
+ /**
+ * @name Two.Path.FlagVertices
+ * @function
+ * @description Cached method to let renderers know vertices have been updated on a {@link Two.Path}.
+ */
+ FlagVertices: function() {
+ this._flagVertices = true;
+ this._flagLength = true;
+ if (this.parent) {
+ this.parent._flagLength = true;
+ }
+ },
+
+ /**
+ * @name Two.Path.BindVertices
+ * @function
+ * @description Cached method to let {@link Two.Path} know vertices have been added to the instance.
+ * @description Cached method to let {@link Two.Path} know the fill has changed.
+ */
+ FlagFill: function() {
+ this._flagFill = true;
+ },
+
+ /**
+ * @name Two.Path.FlagFill
+ * @function
+ * @description Cached method to let {@link Two.Path} know the stroke has changed.
+ */
+ FlagStroke: function() {
+ this._flagStroke = true;
+ },
+
+ /**
+ * @name Two.Path.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Path} to any object. Handy if you'd like to extend the {@link Two.Path} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ Shape.MakeObservable(object);
+
+ // Only the 7 defined properties are flagged like this. The subsequent
+ // properties behave differently and need to be hand written.
+ * @property {Number} - The sum of distances between all {@link Two.Path#vertices}.
+ */
+ Object.defineProperty(object, 'length', {
+ get: function() {
+ if (this._flagLength) {
+ this._updateLength();
+ }
+ return this._length;
+ }
+ });
+
+ Object.defineProperty(object, 'closed', {
+ enumerable: true,
+ get: function() {
+ return this._closed;
+ },
+ set: function(v) {
+ this._closed = !!v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'curved', {
+ enumerable: true,
+ get: function() {
+ return this._curved;
+ },
+ set: function(v) {
+ this._curved = !!v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'automatic', {
+ enumerable: true,
+ get: function() {
+ return this._automatic;
+ },
+ set: function(v) {
+ if (v === this._automatic) {
+ return;
+ }
+ this._automatic = !!v;
+ var method = this._automatic ? 'ignore' : 'listen';
+ _.each(this.vertices, function(v) {
+ v[method]();
+ });
+ }
+ });
+
+ Object.defineProperty(object, 'beginning', {
+ enumerable: true,
+ get: function() {
+ return this._beginning;
+ },
+ set: function(v) {
+ this._beginning = v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'ending', {
+ enumerable: true,
+ get: function() {
+ return this._ending;
+ },
+ set: function(v) {
+ this._ending = v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'vertices', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._collection;
+ },
+
+ set: function(vertices) {
+
+ var bindVertices = this._renderer.bindVertices;
+ var unbindVertices = this._renderer.unbindVertices;
+
+ // Remove previous listeners
+ if (this._collection) {
+ this._collection
+ .unbind(Events.Types.insert, bindVertices)
+ .unbind(Events.Types.remove, unbindVertices);
+ }
+
+ // Create new Collection with copy of vertices
+ if (vertices instanceof Collection) {
+ this._collection = vertices;
+ } else {
+ this._collection = new Collection(vertices || []);
+ }
+
+
+ // Listen for Collection changes and bind / unbind
+ this._collection
+ .bind(Events.Types.insert, bindVertices)
+ .bind(Events.Types.remove, unbindVertices);
+
+ // Bind Initial Vertices
+ bindVertices(this._collection);
+
+ }
+
+ });
+
+ /**
+ * @name Two.Path#mask
+ * @property {Two.Shape} - The shape whose alpha property becomes a clipping area for the path.
+ * @nota-bene This property is currently not working becuase of SVG spec issues found here {@link https://code.google.com/p/chromium/issues/detail?id=370951}.
+ */
+ Object.defineProperty(object, 'mask', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._mask;
+ },
+
+ set: function(v) {
+ this._mask = v;
+ this._flagMask = true;
+ if (!v.clip) {
+ v.clip = true;
+ }
+ }
+
+ });
+
+ /**
+ * @name Two.Path#clip
+ * @property {Boolean} - Tells Two.js renderer if this object represents a mask for another object (or not).
+ */
+ Object.defineProperty(object, 'clip', {
+ enumerable: true,
+ get: function() {
+ return this._clip;
+ },
+ set: function(v) {
+ this._clip = v;
+ this._flagClip = true;
+ }
+ });
+
+ Object.defineProperty(object, 'dashes', {
+ enumerable: true,
+ get: function() {
+ return this._dashes;
+ },
+ set: function(v) {
+ if (typeof v.offset !== 'number') {
+ v.offset = this._dashes.offset || 0;
+ }
+ this._dashes = v;
+ }
+ });
+
+ }
+
+ });
+
+ _.extend(Path.prototype, Shape.prototype, {
+
+ constructor: Path,
+
+ // Flags
+ // http://en.wikipedia.org/wiki/Flag
+
+ /**
+ * @name Two.Path#_flagVertices
+ * @private
+ * @property {Boolean} - Determines whether the {@link Two.Path#vertices} need updating.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices) {
+
+ if (this._automatic) {
+ this.plot();
+ }
+
+ if (this._flagLength) {
+ this._updateLength(undefined, true);
+ }
+
+ var l = this._collection.length;
+ var closed = this._closed;
+
+ var beginning = Math.min(this._beginning, this._ending);
+ var ending = Math.max(this._beginning, this._ending);
+
+ var bid = getIdByLength(this, beginning * this._length);
+ var eid = getIdByLength(this, ending * this._length);
+ * @param {Number} [x=0] - The x position of the rectangle.
+ * @param {Number} [y=0] - The y position of the rectangle.
+ * @param {Number} [width] - The width value of the rectangle.
+ * @param {Number} [height] - The width value of the rectangle.
+ */
+ function Rectangle(x, y, width, height) {
+
+ Path.call(this, [
+ new Anchor(),
+ new Anchor(),
+ new Anchor(),
+ new Anchor()
+ // new Anchor() // TODO: Figure out how to handle this for `beginning` / `ending` animations
+ ], true, false, true);
+
+ /**
+ * @name Two.Rectangle#width
+ * @property {Number} - The size of the width of the rectangle.
+ */
+ this.width = width;
+ /**
+ * @name Two.Rectangle#height
+ * @property {Number} - The size of the height of the rectangle.
+ */
+ this.height = height;
+
+ /**
+ * @name Two.Rectangle#origin
+ * @property {Number} - A two-component vector describing the origin offset to draw the rectangle. Default is `0, 0`.
+ */
+ this.origin = new Vector();
+ this.translation.set(x, y);
+
+ this._update();
+
+ }
+
+ _.extend(Rectangle, {
+
+ /**
+ * @name Two.Rectangle.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Rectangle}.
+ */
+ Properties: ['width', 'height'],
+
+ /**
+ * @name Two.Rectangle.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Rectangle} to any object. Handy if you'd like to extend the {@link Two.Rectangle} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight) {
+
+ var xr = this._width / 2;
+ var yr = this._height / 2;
+
+ if (!this._closed && this.vertices.length === 4) {
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = false;
+ Path.prototype.flagReset.call(this);
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Rectangle#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Rectangle}
+ * @description Create a new instance of {@link Two.Rectangle} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var clone = new Rectangle(0, 0, this.width, this.height);
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ _.each(Path.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Rectangle#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var object = Path.prototype.toObject.call(this);
+ object.width = this.width;
+ object.height = this.height;
+ object.origin = this.origin.toObject();
+ return object;
+
+ }
+
+ });
+
+ Rectangle.MakeObservable(Rectangle.prototype);
+
+ /**
+ * @name Two.Sprite
+ * @class
+ * @extends Two.Rectangle
+ * @param {String|Two.Texture} [path] - The URL path or {@link Two.Texture} to be used as the bitmap data displayed on the sprite.
+ * @param {Number} [ox=0] - The initial `x` position of the Two.Sprite.
+ * @param {Number} [oy=0] - The initial `y` position of the Two.Sprite.
+ * @param {Number} [cols=1] - The number of columns the sprite contains.
+ * @param {Number} [rows=1] - The number of rows the sprite contains.
+ * @param {Number} [frameRate=0] - The frame rate at which the partitions of the image should playback at.
+ * @description A convenient package to display still or animated images through a tiled image source. For more information on the principals of animated imagery through tiling see [Texture Atlas](https://en.wikipedia.org/wiki/Texture_atlas) on Wikipedia.
+ */
+ function Sprite(path, ox, oy, cols, rows, frameRate) {
+
+ // Not using default constructor of Rectangle due to odd `beginning` / `ending` behavior.
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Sprite} to any object. Handy if you'd like to extend or inherit the {@link Two.Sprite} class on a custom class.
+ * @property {Number} - Number of frames for a given {@link Two.Sprite}.
+ */
+ _amount: 1,
+
+ /**
+ * @name Two.Sprite#_duration
+ * @private
+ * @property {Number} - Number of milliseconds a {@link Two.Sprite}.
+ */
+ _duration: 0,
+
+ /**
+ * @name Two.Sprite#_startTime
+ * @private
+ * @property {Milliseconds} - Epoch time in milliseconds of when the {@link Two.Sprite} started.
+ */
+ _startTime: 0,
+
+ /**
+ * @name Two.Sprite#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.Sprite} is animating or not.
+ */
+ _playing: false,
+
+ /**
+ * @name Two.Sprite#_firstFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.Sprite} should start with.
+ */
+ _firstFrame: 0,
+
+ /**
+ * @name Two.Sprite#_lastFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.Sprite} should end with.
+ */
+ _lastFrame: 0,
+
+ /**
+ * @name Two.Sprite#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.Sprite} should loop or not.
+ */
+ _loop: true,
+
+ // Exposed through getter-setter
+
+ /**
+ * @name Two.Sprite#_texture
+ * @private
+ * @see {@link Two.Sprite#texture}
+ */
+ _texture: null,
+
+ /**
+ * @name Two.Sprite#_columns
+ * @private
+ * @see {@link Two.Sprite#columns}
+ */
+ _columns: 1,
+
+ /**
+ * @name Two.Sprite#_rows
+ * @private
+ * @see {@link Two.Sprite#rows}
+ */
+ _rows: 1,
+
+ /**
+ * @name Two.Sprite#_frameRate
+ * @private
+ * @see {@link Two.Sprite#frameRate}
+ */
+ _frameRate: 0,
+
+ /**
+ * @name Two.Sprite#_index
+ * @private
+ * @property {Number} - The current frame the {@link Two.Sprite} is currently displaying.
+ */
+ _index: 0,
+
+ /**
+ * @name Two.Sprite#_origin
+ * @private
+ * @see {@link Two.Sprite#origin}
+ */
+ _origin: null,
+
+ /**
+ * @name Two.Sprite#play
+ * @function
+ * @param {Number} [firstFrame=0] - The index of the frame to start the animation with.
+ * @param {Number} [lastFrame] - The index of the frame to end the animation with. Defaults to the last item in the {@link Two.Sprite#textures}.
+ * @param {Function} [onLastFrame] - Optional callback function to be triggered after playing the last frame. This fires multiple times when the sprite is looped.
+ * @description Initiate animation playback of a {@link Two.Sprite}.
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+ var object = Rectangle.prototype.toObject.call(this);
+ object.texture = this.texture.toObject();
+ object.columns = this.columns;
+ object.rows = this.rows;
+ object.frameRate = this.frameRate;
+ object.index = this.index;
+ object._firstFrame = this._firstFrame;
+ object._lastFrame = this._lastFrame;
+ object._loop = this._loop;
+ return object;
+ },
+
+ /**
+ * @name Two.Sprite#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ * @param {Number} [x=0] - The x position of the circle.
+ * @param {Number} [y=0] - The y position of the circle.
+ * @param {Number} [radius=0] - The radius value of the circle.
+ * @param {Number} [resolution=4] - The number of vertices used to construct the circle.
+ */
+ function Circle(ox, oy, r, resolution) {
+
+ // At least 2 vertices are required for proper circlage
+ var amount = resolution ? Math.max(resolution, 2) : 4;
+
+ var points = [];
+ for (var i = 0; i < amount; i++) {
+ points.push(new Anchor(0, 0, 0, 0, 0, 0));
+ }
+
+ Path.call(this, points, true, true, true);
+
+ /**
+ * @name Two.Circle#radius
+ * @property {Number} - The size of the radius of the circle.
+ */
+ if (typeof r === 'number') {
+ this.radius = r;
+ }
+
+ this._update();
+
+ if (typeof ox === 'number') {
+ this.translation.x = ox;
+ }
+ if (typeof oy === 'number') {
+ this.translation.y = oy;
+ }
+
+ }
+
+ _.extend(Circle, {
+
+ /**
+ * @name Two.Circle.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Circle}.
+ */
+ Properties: ['radius'],
+
+ /**
+ * @name Two.Circle.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Circle} to any object. Handy if you'd like to extend the {@link Two.Circle} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagRadius) {
+
+ var length = this.vertices.length;
+
+ if (!this._closed && length > 2) {
+ length -= 1;
+ }
+
+ // Coefficient for approximating circular arcs with Bezier curves
+ var c = (4 / 3) * Math.tan(Math.PI / (length * 2));
+ var radius = this._radius;
+ var rc = radius * c;
+
+ for (var i = 0; i < this.vertices.length; i++) {
+ var pct = i / length;
+ var theta = pct * TWO_PI$4;
+
+ var x = radius * cos$3(theta);
+ var y = radius * sin$3(theta);
+
+ var lx = rc * cos$3(theta - HALF_PI$2);
+ var ly = rc * sin$3(theta - HALF_PI$2);
+
+ var rx = rc * cos$3(theta + HALF_PI$2);
+ var ry = rc * sin$3(theta + HALF_PI$2);
+
+ var v = this.vertices[i];
+
+ v.command = i === 0 ? Commands.move : Commands.curve;
+ v.set(x, y);
+ v.controls.left.set(lx, ly);
+ v.controls.right.set(rx, ry);
+ }
+ }
+
+ Path.prototype._update.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Circle#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagRadius = false;
+
+ Path.prototype.flagReset.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Circle#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Circle}
+ * @description Create a new instance of {@link Two.Circle} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var clone = new Circle(0, 0, this.radius, this.vertices.length);
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ _.each(Path.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Circle#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var object = Path.prototype.toObject.call(this);
+ * @param {Number} [x=0] - The x position of the ellipse.
+ * @param {Number} [y=0] - The y position of the ellipse.
+ * @param {Number} [rx=0] - The radius value of the ellipse in the x direction.
+ * @param {Number} [ry=0] - The radius value of the ellipse in the y direction.
+ * @param {Number} [resolution=4] - The number of vertices used to construct the ellipse.
+ */
+ function Ellipse(ox, oy, rx, ry, resolution) {
+
+ if (typeof ry !== 'number' && typeof rx === 'number') {
+ ry = rx;
+ }
+
+ // At least 2 vertices are required for proper circlage
+ var amount = resolution ? Math.max(resolution, 2) : 4;
+
+ var points = [];
+ for (var i = 0; i < amount; i++) {
+ points.push(new Anchor());
+ }
+
+ Path.call(this, points, true, true, true);
+
+ /**
+ * @name Two.Ellipse#width
+ * @property {Number} - The width of the ellipse.
+ */
+ if (typeof rx === 'number') {
+ this.width = rx * 2;
+ }
+
+ /**
+ * @name Two.Ellipse#height
+ * @property {Number} - The height of the ellipse.
+ */
+ if (typeof ry === 'number') {
+ this.height = ry * 2;
+ }
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ }
+
+ _.extend(Ellipse, {
+
+ /**
+ * @name Two.Ellipse.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Ellipse}.
+ */
+ Properties: ['width', 'height'],
+
+ /**
+ * @name Two.Ellipse.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Ellipse} to any object. Handy if you'd like to extend the {@link Two.Ellipse} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight) {
+
+ var length = this.vertices.length;
+
+ if (!this._closed && length > 2) {
+ length -= 1;
+ }
+
+ // Coefficient for approximating circular arcs with Bezier curves
+ var c = (4 / 3) * Math.tan(Math.PI / (this.vertices.length * 2));
+ var radiusX = this._width / 2;
+ var radiusY = this._height / 2;
+
+ for (var i = 0; i < this.vertices.length; i++) {
+ var pct = i / length;
+ var theta = pct * TWO_PI$3;
+
+ var x = radiusX * cos$2(theta);
+ var y = radiusY * sin$2(theta);
+
+ var lx = radiusX * c * cos$2(theta - HALF_PI$1);
+ var ly = radiusY * c * sin$2(theta - HALF_PI$1);
+
+ var rx = radiusX * c * cos$2(theta + HALF_PI$1);
+ var ry = radiusY * c * sin$2(theta + HALF_PI$1);
+
+ var v = this.vertices[i];
+
+ v.command = i === 0 ? Commands.move : Commands.curve;
+ v.set(x, y);
+ v.controls.left.set(lx, ly);
+ v.controls.right.set(rx, ry);
+ }
+ }
+
+ Path.prototype._update.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Ellipse#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = false;
+
+ Path.prototype.flagReset.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Ellipse#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Polygon}
+ * @description Create a new instance of {@link Two.Polygon} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var rx = this.width / 2;
+ var ry = this.height / 2;
+ var resolution = this.vertices.length;
+ var clone = new Ellipse(0, 0, rx, ry, resolution);
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ _.each(Path.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Ellipse#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var object = Path.prototype.toObject.call(this);
+
+ _.each(Ellipse.Properties, function(property) {
+ object[property] = this[property];
+ }, this);
+
+ return object;
+
+ }
+
+ });
+
+ Ellipse.MakeObservable(Ellipse.prototype);
+
+ /**
+ * @name Two.Line
+ * @class
+ * @extends Two.Path
+ * @param {Number} [x1=0] - The x position of the first vertex on the line.
+ * @param {Number} [y1=0] - The y position of the first vertex on the line.
+ * @param {Number} [x2=0] - The x position of the second vertex on the line.
+ * @param {Number} [y2=0] - The y position of the second vertex on the line.
+ */
+ function Line(x1, y1, x2, y2) {
+
+ Path.call(this, [
+ new Anchor(x1, y1),
+ new Anchor(x2, y2)
+ ]);
+
+ this.vertices[0].command = Commands.move;
+ this.vertices[1].command = Commands.line;
+
+ this.automatic = false;
+
+ }
+
+ _.extend(Line.prototype, Path.prototype, {
+
+ constructor: Line
+
+ });
+
+ Path.MakeObservable(Line.prototype);
+
+ /**
+ * @name Two.RoundedRectangle
+ * @class
+ * @extends Two.Path
+ * @param {Number} [x=0] - The x position of the rounded rectangle.
+ * @param {Number} [y=0] - The y position of the rounded rectangle.
+ * @param {Number} [width=0] - The width value of the rounded rectangle.
+ * @param {Number} [height=0] - The width value of the rounded rectangle.
+ * @param {Number} [radius=0] - The radius value of the rounded rectangle.
+ * @param {Number} [resolution=12] - The number of vertices used to construct the rounded rectangle.
+ */
+ function RoundedRectangle(ox, oy, width, height, radius) {
+ * @property {Number} - The width of the rounded rectangle.
+ */
+ if (typeof width === 'number') {
+ this.width = width;
+ }
+
+ /**
+ * @name Two.RoundedRectangle#height
+ * @property {Number} - The height of the rounded rectangle.
+ */
+ if (typeof height === 'number') {
+ this.height = height;
+ }
+
+ /**
+ * @name Two.RoundedRectangle#radius
+ * @property {Number} - The size of the radius of the rounded rectangle.
+ */
+ if (typeof radius === 'number') {
+ this.radius = radius;
+ }
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ }
+
+ _.extend(RoundedRectangle, {
+
+ /**
+ * @name Two.RoundedRectangle.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.RoundedRectangle}.
+ */
+ Properties: ['width', 'height'],
+
+ /**
+ * @name Two.RoundedRectangle.FlagRadius
+ * @property {Function} - A convenience function to trigger the flag for radius changing.
+ */
+ FlagRadius: function() {
+ this._flagRadius = true;
+ },
+
+ /**
+ * @name Two.RoundedRectangle.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.RoundedRectangle} to any object. Handy if you'd like to extend the {@link Two.RoundedRectangle} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight || this._flagRadius) {
+
+ var width = this._width;
+ var height = this._height;
+
+ var rx, ry;
+
+ if (this._radius instanceof Vector) {
+ rx = this._radius.x;
+ ry = this._radius.y;
+ } else {
+ rx = this._radius;
+ ry = this._radius;
+ }
+
+ var v;
+ var w = width / 2;
+ var h = height / 2;
+
+ v = this.vertices[0];
+ v.x = - (w - rx);
+ v.y = - h;
+
+ // Upper Right Corner
+
+ v = this.vertices[1];
+ v.x = (w - rx);
+ v.y = - h;
+ v.controls.left.clear();
+ v.controls.right.x = rx;
+ v.controls.right.y = 0;
+
+ v = this.vertices[2];
+ v.x = w;
+ v.y = - (h - ry);
+ v.controls.right.clear();
+ v.controls.left.clear();
+
+ // Bottom Right Corner
+
+ v = this.vertices[3];
+ v.x = w;
+ v.y = (h - ry);
+ v.controls.left.clear();
+ v.controls.right.x = 0;
+ v.controls.right.y = ry;
+
+ v = this.vertices[4];
+ v.x = (w - rx);
+ v.y = h;
+ v.controls.right.clear();
+ v.controls.left.clear();
+
+ // Bottom Left Corner
+
+ v = this.vertices[5];
+ v.x = - (w - rx);
+ v.y = h;
+ v.controls.left.clear();
+ v.controls.right.x = - rx;
+ v.controls.right.y = 0;
+
+ v = this.vertices[6];
+ v.x = - w;
+ v.y = (h - ry);
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ // Upper Left Corner
+
+ v = this.vertices[7];
+ v.x = - w;
+ v.y = - (h - ry);
+ v.controls.left.clear();
+ v.controls.right.x = 0;
+ v.controls.right.y = - ry;
+
+ v = this.vertices[8];
+ v.x = - (w - rx);
+ v.y = - h;
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ v = this.vertices[9];
+ v.copy(this.vertices[8]);
+
+ }
+
+ Path.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.RoundedRectangle#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @property {Number[]} - Array of numbers. Odd indices represent dash length. Even indices represent dash space.
+ * @description A list of numbers that represent the repeated dash length and dash space applied to the stroke of the text.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray} for more information on the SVG stroke-dasharray attribute.
+ */
+ this.dashes = [];
+
+ /**
+ * @name Two.Text#dashes#offset
+ * @property {Number} - A number in pixels to offset {@link Two.Text#dashes} display.
+ */
+ this.dashes.offset = 0;
+
+ if (!_.isObject(styles)) {
+ return this;
+ }
+
+ _.each(Text.Properties, function(property) {
+
+ if (property in styles) {
+ this[property] = styles[property];
+ }
+
+ }, this);
+
+ }
+
+ _.extend(Text, {
+
+ /**
+ * @name Two.Text.Ratio
+ * @property {Number} - Approximate aspect ratio of a typeface's character width to height.
+ */
+ Ratio: 0.6,
+
+ /**
+ * @name Two.Text.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Text}.
+ * @property {Boolean} - Determines whether the {@link Two.Text#clip} need updating.
+ */
+ _flagClip: false,
+
+ // Underlying Properties
+
+ /**
+ * @name Two.Text#value
+ * @property {String} - The characters to be rendered to the the screen. Referred to in the documentation sometimes as the `message`.
+ */
+ _value: '',
+
+ /**
+ * @name Two.Text#family
+ * @property {String} - The font family Two.js should attempt to regsiter for rendering. The default value is `'sans-serif'`. Comma separated font names can be supplied as a "stack", similar to the CSS implementation of `font-family`.
+ */
+ _family: 'sans-serif',
+
+ /**
+ * @name Two.Text#size
+ * @property {Number} - The font size in Two.js point space. Defaults to `13`.
+ */
+ _size: 13,
+
+ /**
+ * @name Two.Text#leading
+ * @property {Number} - The height between lines measured from base to base in Two.js point space. Defaults to `17`.
+ */
+ _leading: 17,
+
+ /**
+ * @name Two.Text#alignment
+ * @property {String} - Alignment of text in relation to {@link Two.Text#translation}'s coordinates. Possible values include `'left'`, `'center'`, `'right'`. Defaults to `'center'`.
+ */
+ _alignment: 'center',
+
+ /**
+ * @name Two.Text#baseline
+ * @property {String} - The vertical aligment of the text in relation to {@link Two.Text#translation}'s coordinates. Possible values include `'top'`, `'middle'`, `'bottom'`, and `'baseline'`. Defaults to `'baseline'`.
+ */
+ _baseline: 'middle',
+
+ /**
+ * @name Two.Text#style
+ * @property {String} - The font's style. Possible values include '`normal`', `'italic'`. Defaults to `'normal'`.
+ */
+ _style: 'normal',
+
+ /**
+ * @name Two.Text#weight
+ * @property {Number} - A number at intervals of 100 to describe the font's weight. This compatibility varies with the typeface's variant weights. Larger values are bolder. Smaller values are thinner. Defaults to `'500'`.
+ */
+ _weight: 500,
+
+ /**
+ * @name Two.Text#decoration
+ * @property {String} - String to delineate whether text should be decorated with for instance an `'underline'`. Defaults to `'none'`.
+ */
+ _decoration: 'none',
+
+ /**
+ * @name Two.Text#fill
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the text object should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _fill: '#000',
+
+ /**
+ * @name Two.Text#stroke
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the text object should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _stroke: 'transparent',
+
+ /**
+ * @name Two.Text#linewidth
+ * @property {Number} - The thickness in pixels of the stroke.
+ */
+ _linewidth: 1,
+
+ /**
+ * @name Two.Text#opacity
+ * @property {Number} - The opaqueness of the text object.
+ * @nota-bene Can be used in conjunction with CSS Colors that have an alpha value.
+ */
+ _opacity: 1,
+
+ /**
+ * @name Two.Text#className
+ * @property {String} - A class to be applied to the element to be compatible with CSS styling. Only available for the {@link Two.SvgRenderer}.
+ */
+ _className: '',
+
+ /**
+ * @name Two.Text#visible
+ * @property {Boolean} - Display the text object or not.
+ * @nota-bene For {@link Two.CanvasRenderer} and {@link Two.WebGLRenderer} when set to false all updating is disabled improving performance dramatically with many objects in the scene.
+ */
+ _visible: true,
+
+ /**
+ * @name Two.Text#mask
+ * @property {Two.Shape} - The shape whose alpha property becomes a clipping area for the text.
+ * @nota-bene This property is currently not working becuase of SVG spec issues found here {@link https://code.google.com/p/chromium/issues/detail?id=370951}.
+ */
+ _mask: null,
+
+ /**
+ * @name Two.Text#clip
+ * @property {Two.Shape} - Object to define clipping area.
+ * @nota-bene This property is currently not working becuase of SVG spec issues found here {@link https://code.google.com/p/chromium/issues/detail?id=370951}.
+ */
+ _clip: false,
+
+ /**
+ * @name Two.Text#_dashes
+ * @private
+ * @see {@link Two.Text#dashes}
+ */
+ _dashes: [],
+
+ /**
+ * @name Two.Text#remove
+ * @function
+ * @description Remove self from the scene / parent.
+ */
+ remove: function() {
+
+ if (!this.parent) {
+ return this;
+ }
+
+ this.parent.remove(this);
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Text#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Text}
+ * @description Create a new instance of {@link Two.Text} with the same properties of the current text object.
+ */
+ clone: function(parent) {
+
+ var clone = new Text(this.value);
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+
+ _.each(Text.Properties, function(property) {
+ clone[property] = this[property];
+ }, this);
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone._update();
+
+ },
+
+ /**
+ * @name Two.Text#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the text object.
+ */
+ toObject: function() {
+
+ var result = {
+ translation: this.translation.toObject(),
+ rotation: this.rotation,
+ scale: this.scale
+ };
+
+ if (this.matrix.manual) {
+ result.matrix = this.matrix.toObject();
+ }
+
+ _.each(Text.Properties, function(property) {
+ result[property] = this[property];
+ }, this);
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.Text#noFill
+ * @function
+ * @description Short hand method to set fill to `transparent`.
+ */
+ noFill: function() {
+ this.fill = 'transparent';
+ return this;
+ },
+
+ /**
+ * @name Two.Text#noStroke
+ * @function
+ * @description Short hand method to set stroke to `transparent`.
+ */
+ noStroke: function() {
+ this.stroke = undefined;
+ this.linewidth = undefined;
+ return this;
+ },
+
+ // A shim to not break `getBoundingClientRect` calls.
+ // TODO: Implement a way to calculate proper bounding
+ // boxes of `Two.Text`.
+
+ /**
+ * @name Two.Text#getBoundingClientRect
+ * @function
+ * @param {Boolean} [shallow=false] - Describes whether to calculate off local matrix or world matrix.
+ var keywords = ['id', 'class', 'transform', 'xmlns', 'viewBox'];
+
+ for (var i = 0; i < keywords.length; i++) {
+ var keyword = keywords[i];
+ var index = Array.prototype.indexOf.call(attributes, keyword);
+ if (index >= 0) {
+ attributes.splice(index, 1);
+ }
+ }
+
+ return attributes;
+
+ };
+
+ /**
+ * @name Two.Utils.applySvgViewBox
+ * @function
+ * @param {Two.Shape} node - The Two.js object to apply viewbox matrix to
+ * @param {String} value - The viewBox value from the SVG attribute
+ * @returns {Two.Shape} node
+ * @description Applies the transform of the SVG Viewbox on a given node.
+ */
+ var applySvgViewBox = function(node, value) {
+
+ var elements = value.split(/\s/);
+
+ var x = parseFloat(elements[0]);
+ var y = parseFloat(elements[1]);
+ var width = parseFloat(elements[2]);
+ var height = parseFloat(elements[3]);
+
+ var s = Math.min(this.width / width, this.height / height);
+
+ node.translation.x -= x * s;
+ node.translation.y -= y * s;
+ node.scale = s;
+
+ return node;
+
+ };
+
+ /**
+ * @name Two.Utils.applySvgAttributes
+ * @function
+ * @param {SVGElement} node - An SVG Node to extrapolate attributes from.
+ * @param {Two.Shape} elem - The Two.js object to apply extrapolated attributes to.
+ * @returns {Two.Shape} The Two.js object passed now with applied attributes.
+ * @description This function iterates through an SVG Node's properties and stores ones of interest. It tries to resolve styles applied via CSS as well.
+ * @TODO Reverse calculate {@link Two.Gradient}s for fill / stroke of any given path.
+ */
+ var applySvgAttributes = function(node, elem, parentStyles) {
+
+ var styles = {}, attributes = {}, extracted = {}, i, m, key, value, attr;
+ var transforms, x, y;
+ var id, scene, ref, tagName;
+
+ // Not available in non browser environments
+ if (root$1.getComputedStyle) {
+ // Convert CSSStyleDeclaration to a normal object
+ var computedStyles = root$1.getComputedStyle(node);
+ i = computedStyles.length;
+
+ while (i--) {
+ key = computedStyles[i];
+ value = computedStyles[key];
+ // Gecko returns undefined for unset properties
+ // Webkit returns the default value
+ if (typeof value !== 'undefined') {
+ styles[key] = value;
+ }
+ }
+ }
+
+ // Convert NodeMap to a normal object
+ for (i = 0; i < node.attributes.length; i++) {
+ attr = node.attributes[i];
+ if (/style/i.test(attr.nodeName)) {
+ extractCSSText(attr.value, extracted);
+ } else {
+ attributes[attr.nodeName] = attr.value;
+ }
+ }
+
+ // Getting the correct opacity is a bit tricky, since SVG path elements don't
+ // support opacity as an attribute, but you can apply it via CSS.
+ // So we take the opacity and set (stroke/fill)-opacity to the same value.
+ if (typeof styles.opacity !== 'undefined') {
+ styles['stroke-opacity'] = styles.opacity;
+ styles['fill-opacity'] = styles.opacity;
+ delete styles.opacity;
+ }
+
+ // Merge attributes and applied styles (attributes take precedence)
+ if (parentStyles) {
+ _.defaults(styles, parentStyles);
+ }
+ _.extend(styles, extracted, attributes);
+
+ // Similarly visibility is influenced by the value of both display and visibility.
+ // Calculate a unified value here which defaults to `true`.
+ // Overwritten id for non-conflicts on same page SVG documents
+ // TODO: Make this non-descructive
+ node.id = value + '-' + Constants.Identifier + 'applied';
+ break;
+ case 'class':
+ case 'className':
+ elem.classList = value.split(' ');
+ break;
+ case 'x':
+ case 'y':
+ var ca = elem instanceof Gradient;
+ var cb = elem instanceof LinearGradient;
+ var cc = elem instanceof RadialGradient;
+ if (ca || cb || cc) {
+ break;
+ }
+ if (value.match('[a-z%]$') && !value.endsWith('px')) {
+ var error = new TwoError(
+ 'only pixel values are supported with the ' + key + ' attribute.');
+ console.warn(error.name, error.message);
+ }
+ elem.translation[key] = parseFloat(value);
+ break;
+ case 'font-family':
+ if (elem instanceof Text) {
+ elem.family = value;
+ }
+ break;
+ case 'font-size':
+ if (elem instanceof Text) {
+ elem.size = value;
+ }
+ break;
+ case 'font-weight':
+ if (elem instanceof Text) {
+ elem.weight = value;
+ }
+ break;
+ case 'font-style':
+ if (elem instanceof Text) {
+ elem.style = value;
+ }
+ break;
+ case 'text-decoration':
+ if (elem instanceof Text) {
+ elem.decoration = value;
+ }
+ break;
+ case 'line-height':
+ if (elem instanceof Text) {
+ elem.leading = value;
+ }
+ break;
+ }
+ }
+
+ return styles;
+
+ };
+
+ /**
+ * @name Two.Utils.updateDefsCache
+ * @function
+ * @param {SVGElement} node - The SVG Node with which to update the defs cache.
+ * @param {Object} Object - The defs cache to be updated.
+ * @description Update the cache of children of <defs /> tags.
+ */
+ var updateDefsCache = function(node, defsCache) {
+ for (var i = 0, l = node.childNodes.length; i < l; i++) {
+ var n = node.childNodes[i];
+ if (!n.id) continue;
+
+ var tagName = getTagName(node.nodeName);
+ if (tagName === '#text') continue;
+
+ defsCache.add(n.id, n);
+ }
+ };
+
+ /**
+ * @name Two.Utils.getScene
+ * @param {Two.Shape} node - The currently available object in the scenegraph.
+ * @returns {Group} - The highest order {@link Two.Group} in the scenegraph.
+ * @property {Function}
+ */
+ var getScene = function(node) {
+
+ while (node.parent) {
+ node = node.parent;
+ }
+
+ return node.scene;
+
+ };
+
+ /**
+ * @name Two.Utils.read
+ * @property {Object} read - A map of functions to read any number of SVG node types and create Two.js equivalents of them. Primarily used by the {@link Two#interpret} method.
+ */
+ var read = {
+
+ svg: function(node) {
+
+ var defs = read.defs.current = new Registry();
+ var elements = node.getElementsByTagName('defs');
+
+ for (var i = 0; i < elements.length; i++) {
+ updateDefsCache(elements[i], defs);
+ }
+
+ var svg = read.g.call(this, node);
+ // var viewBox = node.getAttribute('viewBox');
+
+ svg.defs = defs; // Export out the <defs /> for later use
+ // Utils.applySvgViewBox(svg, viewBox);
+
+ delete read.defs.current;
+
+ return svg;
+
+ },
+
+ defs: function(node) {
+ return null;
+ },
+
+ use: function(node, styles) {
+
+ var error;
+ var href = node.getAttribute('href') || node.getAttribute('xlink:href');
+ if (!href) {
+ error = new TwoError('encountered <use /> with no href.');
+ console.warn(error.name, error.message);
+ return null;
+ }
+
+ var id = href.slice(1);
+ if (!read.defs.current.contains(id)) {
+ error = new TwoError(
+ 'unable to find element for reference ' + href + '.');
+ console.warn(error.name, error.message);
+ return null;
+ }
+
+ var template = read.defs.current.get(id);
+ var fullNode = template.cloneNode(true);
+ var overwriteAttrs = ['x', 'y', 'width', 'height', 'href', 'xlink:href'];
+
+ for (var i = 0; i < node.attributes.length; i++) {
+ var attr = node.attributes[i];
+ var ca = overwriteAttrs.includes(attr.nodeName);
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.ImageSequence} to any object. Handy if you'd like to extend or inherit the {@link Two.ImageSequence} class on a custom class.
+ * @property {Number} - Number of frames for a given {@link Two.ImageSequence}.
+ */
+ _amount: 1,
+
+ /**
+ * @name Two.ImageSequence#_duration
+ * @private
+ * @property {Number} - Number of milliseconds a {@link Two.ImageSequence}.
+ */
+ _duration: 0,
+
+ /**
+ * @name Two.ImageSequence#_index
+ * @private
+ * @property {Number} - The current frame the {@link Two.ImageSequence} is currently displaying.
+ */
+ _index: 0,
+
+ /**
+ * @name Two.ImageSequence#_startTime
+ * @private
+ * @property {Milliseconds} - Epoch time in milliseconds of when the {@link Two.ImageSequence} started.
+ */
+ _startTime: 0,
+
+ /**
+ * @name Two.ImageSequence#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.ImageSequence} is animating or not.
+ */
+ _playing: false,
+
+ /**
+ * @name Two.ImageSequence#_firstFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.ImageSequence} should start with.
+ */
+ _firstFrame: 0,
+
+ /**
+ * @name Two.ImageSequence#_lastFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.ImageSequence} should end with.
+ */
+ _lastFrame: 0,
+
+ /**
+ * @name Two.ImageSequence#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.ImageSequence} should loop or not.
+ */
+ _loop: true,
+
+ // Exposed through getter-setter
+
+ /**
+ * @name Two.ImageSequence#_textures
+ * @private
+ * @see {@link Two.ImageSequence#textures}
+ */
+ _textures: null,
+
+ /**
+ * @name Two.ImageSequence#_frameRate
+ * @private
+ * @see {@link Two.ImageSequence#frameRate}
+ */
+ _frameRate: 0,
+
+ /**
+ * @name Two.ImageSequence#_origin
+ * @private
+ * @see {@link Two.ImageSequence#origin}
+ */
+ _origin: null,
+
+ /**
+ * @name Two.ImageSequence#play
+ * @function
+ * @param {Number} [firstFrame=0] - The index of the frame to start the animation with.
+ * @param {Number} [lastFrame] - The index of the frame to end the animation with. Defaults to the last item in the {@link Two.ImageSequence#textures}.
+ * @param {Function} [onLastFrame] - Optional callback function to be triggered after playing the last frame. This fires multiple times when the image sequence is looped.
+ * @description Initiate animation playback of a {@link Two.ImageSequence}.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ var effects = this._textures;
+ var width, height, elapsed, amount, duration, texture;
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.ArcSegment} to any object. Handy if you'd like to extend the {@link Two.ArcSegment} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagStartAngle || this._flagEndAngle
+ * @param {Number} [x=0] - The x position of the polygon.
+ * @param {Number} [y=0] - The y position of the polygon.
+ * @param {Number} [radius=0] - The radius value of the polygon.
+ * @param {Number} [sides=12] - The number of vertices used to construct the polygon.
+ */
+ function Polygon(ox, oy, r, sides) {
+
+ sides = Math.max(sides || 0, 3);
+
+ Path.call(this);
+
+ this.closed = true;
+ this.automatic = false;
+
+ /**
+ * @name Two.Polygon#width
+ * @property {Number} - The size of the width of the polygon.
+ */
+ if (typeof r === 'number') {
+ this.width = r * 2;
+ }
+
+ /**
+ * @name Two.Polygon#height
+ * @property {Number} - The size of the height of the polygon.
+ */
+ if (typeof r === 'number') {
+ this.height = r * 2;
+ }
+
+ /**
+ * @name Two.Polygon#sides
+ * @property {Number} - The amount of sides the polyogn has.
+ */
+ if (typeof sides === 'number') {
+ this.sides = sides;
+ }
+
+ this._update();
+
+ if (typeof ox === 'number') {
+ this.translation.x = ox;
+ }
+ if (typeof oy === 'number') {
+ this.translation.y = oy;
+ }
+
+ }
+
+ _.extend(Polygon, {
+
+ /**
+ * @name Two.Polygon.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Polygon}.
+ */
+ Properties: ['width', 'height', 'sides'],
+
+ /**
+ * @name Two.Polygon.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Polygon} to any object. Handy if you'd like to extend the {@link Two.Polygon} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight || this._flagSides) {
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Star} to any object. Handy if you'd like to extend the {@link Two.Star} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagInnerRadius || this._flagOuterRadius || this._flagSides) {
+ * @param {Object} [parameters] - This object is inherited when constructing a new instance of {@link Two}.
+ * @param {Element} [parameters.domElement] - The `<svg />` to draw to. If none given a new one will be constructed.
+ * @description This class is used by {@link Two} when constructing with `type` of `Two.Types.svg` (the default type). It takes Two.js' scenegraph and renders it to a `<svg />`.
+ */
+ function Renderer$1(params) {
+
+ /**
+ * @name Two.SVGRenderer#domElement
+ * @property {Element} - The `<svg />` associated with the Two.js scene.
+ * @param {Object} [parameters] - This object is inherited when constructing a new instance of {@link Two}.
+ * @param {Element} [parameters.domElement] - The `<canvas />` to draw to. If none given a new one will be constructed.
+ * @param {HTMLCanvasElement} [parameters.offscreenElement] - The offscreen two dimensional `<canvas />` to render each element on WebGL texture updates.
+ * @param {Boolean} [parameters.antialias] - Determines whether the canvas should clear render with antialias on.
+ * @description This class is used by {@link Two} when constructing with `type` of `Two.Types.webgl`. It takes Two.js' scenegraph and renders it to a `<canvas />` through the WebGL api.
+ * @property {Object} - A massive object filled with utility functions and properties to render Two.js objects to a `<canvas />` through the WebGL API.
+ */
+ Utils: webgl
+
+ });
+
+ _.extend(Renderer.prototype, Events, {
+
+ constructor: Renderer,
+
+ /**
+ * @name Two.WebGLRenderer#setSize
+ * @function
+ * @fires resize
+ * @param {Number} width - The new width of the renderer.
+ * @param {Number} height - The new height of the renderer.
+ * @param {Number} [ratio] - The new pixel ratio (pixel density) of the renderer. Defaults to calculate the pixel density of the user's screen.
+ * @param {Boolean} [options.fullscreen=false] - Set to `true` to automatically make the stage adapt to the width and height of the parent document. This parameter overrides `width` and `height` parameters if set to `true`. This overrides `options.fitted` as well.
+ * @param {Boolean} [options.fitted=false] = Set to `true` to automatically make the stage adapt to the width and height of the parent element. This parameter overrides `width` and `height` parameters if set to `true`.
+ * @param {Number} [options.width=640] - The width of the stage on construction. This can be set at a later time.
+ * @param {Number} [options.height=480] - The height of the stage on construction. This can be set at a later time.
+ * @param {String} [options.type=Two.Types.svg] - The type of renderer to setup drawing with. See {@link Two.Types} for available options.
+ * @param {Boolean} [options.autostart=false] - Set to `true` to add the instance to draw on `requestAnimationFrame`. This is a convenient substitute for {@link Two#play}.
+ * @param {Element} [options.domElement] - The canvas or SVG element to draw into. This overrides the `options.type` argument.
+ * @description The entrypoint for Two.js. Instantiate a `new Two` in order to setup a scene to render to. `Two` is also the publicly accessible namespace that all other sub-classes, functions, and utilities attach to.
+ */
+ function Two(options) {
+
+ // Determine what Renderer to use and setup a scene.
+
+ var params = _.defaults(options || {}, {
+ fullscreen: false,
+ fitted: false,
+ width: 640,
+ height: 480,
+ type: Two.Types.svg,
+ autostart: false
+ });
+
+ _.each(params, function(v, k) {
+ if (/fullscreen/i.test(k) || /autostart/i.test(k)) {
+ return;
+ }
+ this[k] = v;
+ }, this);
+
+ // Specified domElement overrides type declaration only if the element does not support declared renderer type.
+ if (_.isElement(params.domElement)) {
+ var tagName = params.domElement.tagName.toLowerCase();
+ // TODO: Reconsider this if statement's logic.
+ if (!/^(CanvasRenderer-canvas|WebGLRenderer-canvas|SVGRenderer-svg)$/.test(this.type+'-'+tagName)) {
+ this.type = Two.Types[tagName];
+ }
+ }
+
+ this.renderer = new Two[this.type](this);
+ this.setPlaying(params.autostart);
+ this.frameCount = 0;
+
+ /**
+ * @name Two#fit
+ * @function
+ * @description If `options.fullscreen` or `options.fitted` in construction create this function. It sets the `width` and `height` of the instance to its respective parent `window` or `element` depending on the `options` passed.
+ * @property {String} - A string representing which type of renderer the instance has instantiated.
+ */
+ type: '',
+
+ /**
+ * @name Two#renderer
+ * @property {(Two.SVGRenderer|Two.CanvasRenderer|Two.WebGLRenderer)} - The instantiated rendering class for the instance. For a list of possible rendering types check out Two.Types.
+ */
+ renderer: null,
+
+ /**
+ * @name Two#scene
+ * @property {Two.Group} - The base level {@link Two.Group} which houses all objects for the instance. Because it is a {@link Two.Group} transformations can be applied to it that will affect all objects in the instance. This is handy as a makeshift inverted camera.
+ */
+ scene: null,
+
+ /**
+ * @name Two#width
+ * @property {Number} - The width of the instance's dom element.
+ */
+ width: 0,
+
+ /**
+ * @name Two#height
+ * @property {Number} - The height of the instance's dom element.
+ */
+ height: 0,
+
+ /**
+ * @name Two#frameCount
+ * @property {Number} - An integer representing how many frames have elapsed.
+ */
+ frameCount: 0,
+
+ /**
+ * @name Two#timeDelta
+ * @property {Number} - A number representing how much time has elapsed since the last frame in milliseconds.
+ */
+ timeDelta: 0,
+
+ /**
+ * @name Two#playing
+ * @property {Boolean} - A boolean representing whether or not the instance is being updated through the automatic `requestAnimationFrame`.
+ */
+ playing: false,
+
+ /**
+ * @name Two#appendTo
+ * @function
+ * @param {Element} elem - The DOM element to append the Two.js stage to.
+ * @description Shorthand method to append your instance of Two.js to the `document`.
+ */
+ appendTo: function(elem) {
+
+ elem.appendChild(this.renderer.domElement);
+
+ if (this.fit) {
+ if (this.fit.domElement !== window) {
+ this.fit.domElement = elem;
+ this.fit.attached = false;
+ }
+ this.update();
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two#play
+ * @function
+ * @fires Two.Events.Types.play event
+ * @description Call to start an internal animation loop.
+ * @nota-bene This function initiates a `requestAnimationFrame` loop.
+ */
+ play: function() {
+
+ this.playing = true;
+ raf.init();
+ return this.trigger(Events.Types.play);
+
+ },
+
+ /**
+ * @name Two#pause
+ * @function
+ * @fires Two.Events.Types.pause event
+ * @description Call to stop the internal animation loop for a specific instance of Two.js.
+ */
+ pause: function() {
+
+ this.playing = false;
+ return this.trigger(Events.Types.pause);
+
+ },
+
+ setPlaying: function(p) {
+ this.playing = p;
+ },
+
+ /**
+ * @name Two#release
+ * @function
+ * @param {Object} obj
+ * @returns {Object} The object passed for event deallocation.
+ * @description Release an arbitrary class' events from the Two.js corpus and recurse through its children and or vertices.
+ */
+ release: function(obj) {
+
+ var i, v, child;
+
+ if (!_.isObject(obj)) {
+ return;
+ }
+
+ if (typeof obj.unbind === 'function') {
+ obj.unbind();
+ }
+
+ if (obj.vertices) {
+ if (typeof obj.vertices.unbind === 'function') {
+ obj.vertices.unbind();
+ }
+ for (i = 0; i < obj.vertices.length; i++) {
+ v = obj.vertices[i];
+ if (typeof v.unbind === 'function') {
+ v.unbind();
+ }
+ }
+ }
+
+ if (obj.children) {
+ for (i = 0; i < obj.children.length; i++) {
+ child = obj.children[i];
+ this.release(child);
+ }
+ }
+
+ return obj;
+
+ },
+
+ /**
+ * @name Two#update
+ * @function
+ * @fires Two.Events.Types.update event
+ * @description Update positions and calculations in one pass before rendering. Then render to the canvas.
+ * @nota-bene This function is called automatically if using {@link Two#play} or the `autostart` parameter in construction.
+ * @description Removes all objects from the instance's scene. If you intend to have the browser garbage collect this, don't forget to delete the references in your application as well.
+ */
+ clear: function() {
+
+ this.scene.remove(this.scene.children);
+ return this;
+
+ },
+
+ /**
+ * @name Two#makeLine
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} x2
+ * @param {Number} y2
+ * @returns {Two.Line}
+ * @description Creates a Two.js line and adds it to the scene.
+ */
+ makeLine: function(x1, y1, x2, y2) {
+
+ var line = new Line(x1, y1, x2, y2);
+ this.scene.add(line);
+
+ return line;
+
+ },
+
+ /**
+ * @name Two#makeArrow
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} x2
+ * @param {Number} y2
+ * @returns {Two.Path}
+ * @description Creates a Two.js arrow and adds it to the scene.
+ var path = new Path(vertices, false, false, true);
+ path.noFill();
+ path.cap = 'round';
+ path.join = 'round';
+
+ this.scene.add(path);
+
+ return path;
+ },
+
+ /**
+ * @name Two#makeRectangle
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} width
+ * @param {Number} height
+ * @returns {Two.Rectangle}
+ * @description Creates a Two.js rectangle and adds it to the scene.
+ */
+ makeRectangle: function(x, y, width, height) {
+
+ var rect = new Rectangle(x, y, width, height);
+ this.scene.add(rect);
+
+ return rect;
+
+ },
+
+ /**
+ * @name Two#makeRoundedRectangle
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} width
+ * @param {Number} height
+ * @param {Number} sides
+ * @returns {Two.Rectangle}
+ * @description Creates a Two.js rounded rectangle and adds it to the scene.
+ */
+ makeRoundedRectangle: function(x, y, width, height, sides) {
+
+ var rect = new RoundedRectangle(x, y, width, height, sides);
+ this.scene.add(rect);
+
+ return rect;
+
+ },
+
+ /**
+ * @name Two#makeCircle
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} radius
+ * @param {Number} [resolution=4]
+ * @returns {Two.Circle}
+ * @description Creates a Two.js circle and adds it to the scene.
+ */
+ makeCircle: function(x, y, radius, resolution) {
+
+ var circle = new Circle(x, y, radius, resolution);
+ this.scene.add(circle);
+
+ return circle;
+
+ },
+
+ /**
+ * @name Two#makeEllipse
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} rx
+ * @param {Number} ry
+ * @param {Number} [resolution=4]
+ * @returns {Two.Ellipse}
+ * @description Creates a Two.js ellipse and adds it to the scene.
+ */
+ makeEllipse: function(x, y, rx, ry, resolution) {
+
+ var ellipse = new Ellipse(x, y, rx, ry, resolution);
+ this.scene.add(ellipse);
+
+ return ellipse;
+
+ },
+
+ /**
+ * @name Two#makeStar
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} outerRadius
+ * @param {Number} innerRadius
+ * @param {Number} sides
+ * @returns {Two.Star}
+ * @description Creates a Two.js star and adds it to the scene.
+ */
+ makeStar: function(ox, oy, outerRadius, innerRadius, sides) {
+
+ var star = new Star(ox, oy, outerRadius, innerRadius, sides);
+ this.scene.add(star);
+
+ return star;
+
+ },
+
+ /**
+ * @name Two#makeCurve
+ * @function
+ * @param {Two.Anchor[]} [points] - An array of {@link Two.Anchor} points.
+ * @param {...Number} - Alternatively you can pass alternating `x` / `y` coordinate values as individual arguments. These will be combined into {@link Two.Anchor}s for use in the path.
+ * @returns {Two.Path} - Where `path.curved` is set to `true`.
+ * @description Creates a Two.js path that is curved and adds it to the scene.
+ * @nota-bene In either case of passing an array or passing numbered arguments the last argument is an optional `Boolean` that defines whether the path should be open or closed.
+ */
+ makeCurve: function(p) {
+
+ var l = arguments.length, points = p;
+ if (!Array.isArray(p)) {
+ points = [];
+ for (var i = 0; i < l; i+=2) {
+ var x = arguments[i];
+ if (typeof x !== 'number') {
+ break;
+ }
+ var y = arguments[i + 1];
+ points.push(new Anchor(x, y));
+ }
+ }
+
+ var last = arguments[l - 1];
+ var curve = new Path(points, !(typeof last === 'boolean' ? last : undefined), true);
+ * @description Creates a Two.js polygon and adds it to the scene.
+ */
+ makePolygon: function(x, y, radius, sides) {
+
+ var poly = new Polygon(x, y, radius, sides);
+ this.scene.add(poly);
+
+ return poly;
+
+ },
+
+ /**
+ * @name Two#makeArcSegment
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} innerRadius
+ * @param {Number} outerRadius
+ * @param {Number} startAngle
+ * @param {Number} endAngle
+ * @param {Number} [resolution=Two.Resolution] - The number of vertices that should comprise the arc segment.
+ */
+ makeArcSegment: function(ox, oy, ir, or, sa, ea, res) {
+ var arcSegment = new ArcSegment(ox, oy, ir, or, sa, ea, res);
+ this.scene.add(arcSegment);
+ return arcSegment;
+ },
+
+ /**
+ * @name Two#makePath
+ * @function
+ * @param {Two.Anchor[]} [points] - An array of {@link Two.Anchor} points.
+ * @param {...Number} - Alternatively you can pass alternating `x` / `y` coordinate values as individual arguments. These will be combined into {@link Two.Anchor}s for use in the path.
+ * @returns {Two.Path}
+ * @description Creates a Two.js path and adds it to the scene.
+ * @nota-bene In either case of passing an array or passing numbered arguments the last argument is an optional `Boolean` that defines whether the path should be open or closed.
+ */
+ makePath: function(p) {
+
+ var l = arguments.length, points = p;
+ if (!Array.isArray(p)) {
+ points = [];
+ for (var i = 0; i < l; i+=2) {
+ var x = arguments[i];
+ if (typeof x !== 'number') {
+ break;
+ }
+ var y = arguments[i + 1];
+ points.push(new Anchor(x, y));
+ }
+ }
+
+ var last = arguments[l - 1];
+ var path = new Path(points, !(typeof last === 'boolean' ? last : undefined));
+ * @param {Object} [styles] - An object to describe any of the {@link Two.Text.Properties} including `fill`, `stroke`, `linewidth`, `family`, `alignment`, `leading`, `opacity`, etc..
+ * @returns {Two.Text}
+ * @description Creates a Two.js text object and adds it to the scene.
+ */
+ makeText: function(message, x, y, styles) {
+ var text = new Text(message, x, y, styles);
+ this.add(text);
+ return text;
+ },
+
+ /**
+ * @name Two#makeLinearGradient
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} x2
+ * @param {Number} y2
+ * @param {...Two.Stop} stops - Any number of color stops sometimes reffered to as ramp stops. If none are supplied then the default black-to-white two stop gradient is applied.
+ * @returns {Two.LinearGradient}
+ * @description Creates a Two.js linear gradient and ads it to the scene. In the case of an effect it's added to an invisible "definitions" group.
+ var stops = Array.prototype.slice.call(arguments, 4);
+ var gradient = new LinearGradient(x1, y1, x2, y2, stops);
+
+ this.add(gradient);
+
+ return gradient;
+
+ },
+
+ /**
+ * @name Two#makeRadialGradient
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} radius
+ * @param {...Two.Stop} stops - Any number of color stops sometimes reffered to as ramp stops. If none are supplied then the default black-to-white two stop gradient is applied.
+ * @returns {Two.RadialGradient}
+ * @description Creates a Two.js linear-gradient object and ads it to the scene. In the case of an effect it's added to an invisible "definitions" group.
+ */
+ makeRadialGradient: function(x1, y1, r /* stops */) {
+
+ var stops = Array.prototype.slice.call(arguments, 3);
+ var gradient = new RadialGradient(x1, y1, r, stops);
+
+ this.add(gradient);
+
+ return gradient;
+
+ },
+
+ /**
+ * @name Two#makeSprite
+ * @function
+ * @param {(String|Two.Texture)} pathOrTexture - The URL path to an image or an already created {@link Two.Texture}.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} [columns=1]
+ * @param {Number} [rows=1]
+ * @param {Number} [frameRate=0]
+ * @param {Boolean} [autostart=false]
+ * @returns {Two.Sprite}
+ * @description Creates a Two.js sprite object and adds it to the scene. Sprites can be used for still images as well as animations.
+ */
+ makeSprite: function(path, x, y, cols, rows, frameRate, autostart) {
+
+ var sprite = new Sprite(path, x, y, cols, rows, frameRate);
+ if (autostart) {
+ sprite.play();
+ }
+ this.add(sprite);
+
+ return sprite;
+
+ },
+
+ /**
+ * @name Two#makeImageSequence
+ * @function
+ * @param {(String[]|Two.Texture[])} pathsOrTextures - An array of paths or of {@link Two.Textures}.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} [frameRate=0]
+ * @param {Boolean} [autostart=false]
+ * @returns {Two.ImageSequence}
+ * @description Creates a Two.js image sequence object and adds it to the scene.
+ */
+ makeImageSequence: function(paths, x, y, frameRate, autostart) {
+
+ var imageSequence = new ImageSequence(paths, x, y, frameRate);
+ if (autostart) {
+ imageSequence.play();
+ }
+ this.add(imageSequence);
+
+ return imageSequence;
+
+ },
+
+ /**
+ * @name Two#makeTexture
+ * @function
+ * @param {(String|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement)} [pathOrSource] - The URL path to an image or a DOM image-like element.
+ * @param {Function} [callback] - Function to be invoked when the image is loaded.
+ * @returns {Two.Texture}
+ * @description Creates a Two.js texture object.
+ */
+ makeTexture: function(path, callback) {
+
+ var texture = new Texture(path, callback);
+ return texture;
+
+ },
+
+ /**
+ * @name Two#makeGroup
+ * @function
+ * @param {(Two.Shape[]|...Two.Shape)} [objects] - Two.js objects to be added to the group in the form of an array or as individual arguments.
+ * @returns {Two.Group}
+ * @description Creates a Two.js group object and adds it to the scene.
+ * @param {SVGElement} SVGElement - The SVG node to be parsed.
+ * @param {Boolean} shallow - Don't create a top-most group but append all content directly.
+ * @param {Boolean} add – Automatically add the reconstructed SVG node to scene.
+ * @returns {Two.Group}
+ * @description Interpret an SVG Node and add it to this instance's scene. The distinction should be made that this doesn't `import` svg's, it solely interprets them into something compatible for Two.js - this is slightly different than a direct transcription.
+ * @description Object inherited by many Two.js objects in order to facilitate custom events.
+ */
+var Events = {
+
+ /**
+ * @name Two.Events#on
+ * @function
+ * @param {String} [name] - The name of the event to bind a function to.
+ * @param {Function} [handler] - The function to be invoked when the event is dispatched.
+ * @description Call to add a listener to a specific event name.
+ */
+ on: addEventListener,
+
+ /**
+ * @name Two.Events#off
+ * @function
+ * @param {String} [name] - The name of the event intended to be removed.
+ * @param {Function} [handler] - The handler intended to be reomved.
+ * @description Call to remove listeners from a specific event. If only `name` is passed then all the handlers attached to that `name` will be removed. If no arguments are passed then all handlers for every event on the obejct are removed.
+ */
+ off: removeEventListener,
+
+ /**
+ * @name Two.Events#trigger
+ * @function
+ * @param {String} name - The name of the event to dispatch.
+ * @param arguments - Anything can be passed after the name and those will be passed on to handlers attached to the event in the order they are passed.
+ * @description Call to trigger a custom event. Any additional arguments passed after the name will be passed along to the attached handlers.
+ */
+ trigger: function(name) {
+ var scope = this;
+ if (!scope._events) return scope;
+ var args = Array.prototype.slice.call(arguments, 1);
+ var events = scope._events[name];
+ if (events) dispatch(scope, events, args);
+ return scope;
+ },
+
+ listen: function(obj, name, handler) {
+
+ var bound = this;
+
+ if (obj) {
+
+ var event = function () {
+ handler.apply(bound, arguments);
+ };
+
+ // Add references about the object that assigned this listener
+ event.obj = obj;
+ event.name = name;
+ event.handler = handler;
+
+ obj.on(name, event);
+
+ }
+
+ return bound;
+
+ },
+
+ ignore: function(obj, name, handler) {
+
+ var scope = this;
+ obj.off(name, handler);
+ return scope;
+
+ },
+
+ /**
+ * @name Two.Events.Types
+ * @property {Object} - Object of different types of Two.js specific events.
+ */
+ Types: {
+ play: 'play',
+ pause: 'pause',
+ update: 'update',
+ render: 'render',
+ resize: 'resize',
+ change: 'change',
+ remove: 'remove',
+ insert: 'insert',
+ order: 'order',
+ load: 'load'
+ }
+
+};
+
+
+/**
+ * @name Two.Events.bind
+ * @function
+ * @description Alias for {@link Two.Events.on}.
+ */
+Events.bind = addEventListener;
+
+/**
+ * @name Two.Events.unbind
+ * @function
+ * @description Alias for {@link Two.Events.off}.
+ */
+Events.unbind = removeEventListener;
+
+/**
+ * @private
+ * @returns {Two.Events} - Returns an instance of self for the purpose of chaining.
+ */
+function addEventListener(name, handler) {
+
+ var scope = this;
+
+ scope._events || (scope._events = {});
+ var list = scope._events[name] || (scope._events[name] = []);
+
+ list.push(handler);
+
+ return scope;
+
+}
+
+/**
+ * @private
+ * @returns {Two.Events} - Returns an instance of self for the purpose of chaining.
+ */
+function removeEventListener(name, handler) {
+
+ var scope = this;
+
+ if (!scope._events) {
+ return scope;
+ }
+ if (!name && !handler) {
+ scope._events = {};
+ return scope;
+ }
+
+ var names = name ? [name] : Object.keys(scope._events);
+ * @param {Number} [x=0] - Any number to represent the horizontal x-component of the vector.
+ * @param {Number} [y=0] - Any number to represent the vertical y-component of the vector.
+ * @description A class to store x / y component vector data. In addition to storing data `Two.Vector` has suped up methods for commonplace mathematical operations.
+ */
+function Vector(x, y) {
+
+ /**
+ * @name Two.Vector#x
+ * @property {Number} - The horizontal x-component of the vector.
+ */
+ this.x = x || 0;
+
+ /**
+ * @name Two.Vector#y
+ * @property {Number} - The vertical y-component of the vector.
+ */
+ this.y = y || 0;
+
+}
+
+_.extend(Vector, {
+
+ /**
+ * @name Two.Vector.zero
+ * @readonly
+ * @property {Two.Vector} - Handy reference to a vector with component values 0, 0 at all times.
+ */
+ zero: new Vector(),
+
+ /**
+ * @name Two.Vector.add
+ * @function
+ * @param {Two.Vector} v1
+ * @param {Two.Vector} v2
+ * @returns {Two.Vector}
+ * @description Add two vectors together.
+ */
+ add: function(v1, v2) {
+ return new Vector(v1.x + v2.x, v1.y + v2.y);
+ },
+
+ /**
+ * @name Two.Vector.sub
+ * @function
+ * @param {Two.Vector} v1
+ * @param {Two.Vector} v2
+ * @returns {Two.Vector}
+ * @description Subtract two vectors: `v2` from `v1`.
+ */
+ sub: function(v1, v2) {
+ return new Vector(v1.x - v2.x, v1.y - v2.y);
+ },
+
+ /**
+ * @name Two.Vector.subtract
+ * @function
+ * @description Alias for {@link Two.Vector.sub}.
+ */
+ subtract: function(v1, v2) {
+ return Vector.sub(v1, v2);
+ },
+
+ /**
+ * @name Two.Vector.ratioBetween
+ * @function
+ * @param {Two.Vector} A
+ * @param {Two.Vector} B
+ * @returns {Number} The ratio betwen two points `v1` and `v2`.
+ * @returns {Number} The squared distance between points `v1` and `v2`.
+ */
+ distanceBetweenSquared: function(v1, v2) {
+
+ var dx = v1.x - v2.x;
+ var dy = v1.y - v2.y;
+
+ return dx * dx + dy * dy;
+
+ },
+
+ /**
+ * @name Two.Vector.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Vector} to any object. Handy if you'd like to extend the {@link Two.Vector} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ // /**
+ // * Override Backbone bind / on in order to add properly broadcasting.
+ // * This allows Two.Vector to not broadcast events unless event listeners
+ // * are explicity bound to it.
+ // */
+
+ object.bind = object.on = function() {
+
+ if (!this._bound) {
+ this._x = this.x;
+ this._y = this.y;
+ Object.defineProperty(this, 'x', xgs);
+ Object.defineProperty(this, 'y', ygs);
+ _.extend(this, BoundProto);
+ this._bound = true; // Reserved for event initialization check
+ }
+
+ Events.bind.apply(this, arguments);
+
+ return this;
+
+ };
+
+ }
+
+});
+
+_.extend(Vector.prototype, Events, {
+
+ constructor: Vector,
+
+ /**
+ * @name Two.Vector#set
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @description Set the x / y components of a vector to specific number values.
+ */
+ set: function(x, y) {
+ this.x = x;
+ this.y = y;
+ return this;
+ },
+
+ /**
+ * @name Two.Vector#copy
+ * @function
+ * @param {Two.Vector} v
+ * @description Copy the x / y components of another object `v`.
+ */
+ copy: function(v) {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ },
+
+ /**
+ * @name Two.Vector#clear
+ * @function
+ * @description Set the x / y component values of the vector to zero.
+ */
+ clear: function() {
+ this.x = 0;
+ this.y = 0;
+ return this;
+ },
+
+ /**
+ * @name Two.Vector#clone
+ * @function
+ * @description Create a new vector and copy the existing values onto the newly created instance.
+ */
+ clone: function() {
+ return new Vector(this.x, this.y);
+ },
+
+ /**
+ * @name Two.Vector#add
+ * @function
+ * @param {Two.Vector} v
+ * @description Add an object with x / y component values to the instance.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Vector#add
+ * @function
+ * @param {Number} v
+ * @description Add the **same** number to both x / y component values of the instance.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Vector#add
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @description Add `x` / `y` values to their respective component value on the instance.
+ * @description Alias for {@link Two.Vector.divide}.
+ */
+ divideSelf: function(v) {
+ return this.divide.apply(this, arguments);
+ },
+
+ /**
+ * @name Two.Vector#divideScalar
+ * @function
+ * @param {Number} s - The scalar to divide by.
+ * @description Divide the vector by a single number. Shorthand to call {@link Two.Vector#divide} directly.
+ */
+ divideScalar: function(s) {
+ return this.divide(s);
+ },
+
+ /**
+ * @name Two.Vector#negate
+ * @function
+ * @description Invert each component's sign value.
+ */
+ negate: function() {
+ return this.multiply(-1);
+ },
+
+ /**
+ * @name Two.Vector#negate
+ * @function
+ * @returns {Number}
+ * @description Get the [dot product](https://en.wikipedia.org/wiki/Dot_product) of the vector.
+ */
+ dot: function(v) {
+ return this.x * v.x + this.y * v.y;
+ },
+
+ /**
+ * @name Two.Vector#length
+ * @function
+ * @returns {Number}
+ * @description Get the length of a vector.
+ */
+ length: function() {
+ return Math.sqrt(this.lengthSquared());
+ },
+
+ /**
+ * @name Two.Vector#lengthSquared
+ * @function
+ * @returns {Number}
+ * @description Get the length of the vector to the power of two. Widely used as less expensive than {@link Two.Vector#length}, because it isn't square-rooting any numbers.
+ */
+ lengthSquared: function() {
+ return this.x * this.x + this.y * this.y;
+ },
+
+ /**
+ * @name Two.Vector#normalize
+ * @function
+ * @description Normalize the vector from negative one to one.
+ */
+ normalize: function() {
+ return this.divideScalar(this.length());
+ },
+
+ /**
+ * @name Two.Vector#distanceTo
+ * @function
+ * @returns {Number}
+ * @description Get the distance between two vectors.
+ */
+ distanceTo: function(v) {
+ return Math.sqrt(this.distanceToSquared(v));
+ },
+
+ /**
+ * @name Two.Vector#distanceToSquared
+ * @function
+ * @returns {Number}
+ * @description Get the distance between two vectors to the power of two. Widely used as less expensive than {@link Two.Vector#distanceTo}, because it isn't square-rooting any numbers.
+ */
+ distanceToSquared: function(v) {
+ var dx = this.x - v.x,
+ dy = this.y - v.y;
+ return dx * dx + dy * dy;
+ },
+
+ /**
+ * @name Two.Vector#setLength
+ * @function
+ * @param {Number} l - length to set vector to.
+ * @description Set the length of a vector.
+ */
+ setLength: function(l) {
+ return this.normalize().multiplyScalar(l);
+ },
+
+ /**
+ * @name Two.Vector#equals
+ * @function
+ * @param {Two.Vector} v - The vector to compare against.
+ * @param {Number} [eps=0.0001] - An options epsilon for precision.
+ * @returns {Boolean}
+ * @description Qualify if one vector roughly equal another. With a margin of error defined by epsilon.
+ * @param {Number} [x=0] - The x position of the root anchor point.
+ * @param {Number} [y=0] - The y position of the root anchor point.
+ * @param {Number} [lx=0] - The x position of the left handle point.
+ * @param {Number} [ly=0] - The y position of the left handle point.
+ * @param {Number} [rx=0] - The x position of the right handle point.
+ * @param {Number} [ry=0] - The y position of the right handle point.
+ * @param {String} [command=Two.Commands.move] - The command to describe how to render. Applicable commands are {@link Two.Commands}
+ * @extends Two.Vector
+ * @description An object that holds 3 {@link Two.Vector}s, the anchor point and its corresponding handles: `left` and `right`. In order to properly describe the bezier curve about the point there is also a command property to describe what type of drawing should occur when Two.js renders the anchors.
+ */
+function Anchor(x, y, lx, ly, rx, ry, command) {
+
+ Vector.call(this, x, y);
+
+ this._broadcast = (function() {
+ this.trigger(Events.Types.change);
+ }).bind(this);
+
+ this._command = command || Commands.move;
+ this._relative = true;
+
+ var ilx = typeof lx === 'number';
+ var ily = typeof ly === 'number';
+ var irx = typeof rx === 'number';
+ var iry = typeof ry === 'number';
+
+ // Append the `controls` object only if control points are specified,
+ // keeping the Two.Anchor inline with a Two.Vector until it needs to
+ // evolve beyond those functions - e.g: a simple 2 component vector.
+ if (ilx || ily || irx || iry) {
+ Anchor.AppendCurveProperties(this);
+ }
+
+ if (ilx) {
+ this.controls.left.x = lx;
+ }
+ if (ily) {
+ this.controls.left.y = ly;
+ }
+ if (irx) {
+ this.controls.right.x = rx;
+ }
+ if (iry) {
+ this.controls.right.y = ry;
+ }
+
+}
+
+_.extend(Anchor, {
+
+ /**
+ * @name Two.Anchor.AppendCurveProperties
+ * @function
+ * @param {Two.Anchor} anchor - The instance to append the `control`object to.
+ * @description Adds the `controls` property as an object with `left` and `right` properties to access the bezier control handles that define how the curve is drawn. It also sets the `relative` property to `true` making vectors in the `controls` object relative to their corresponding root anchor point.
+ */
+ AppendCurveProperties: function(anchor) {
+
+ anchor.relative = true;
+
+ /**
+ * @name Two.Anchor#controls
+ * @property {Object} controls
+ * @description An plain object that holds the controls handles for a {@link Two.Anchor}.
+ */
+ anchor.controls = {};
+
+ /**
+ * @name Two.Anchor#controls#left
+ * @property {Two.Vector} left
+ * @description The "left" control point to define handles on a bezier curve.
+ */
+ anchor.controls.left = new Vector(0, 0);
+
+ /**
+ * @name Two.Anchor#controls#right
+ * @property {Two.Vector} right
+ * @description The "left" control point to define handles on a bezier curve.
+ */
+ anchor.controls.right = new Vector(0, 0);
+
+ },
+
+ /**
+ * @name Two.Anchor.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Anchor} to any object. Handy if you'd like to extend the {@link Two.Anchor} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ /**
+ * @name Two.Anchor#command
+ * @property {Two.Commands}
+ * @description A draw command associated with the anchor point.
+ */
+ Object.defineProperty(object, 'command', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._command;
+ },
+
+ set: function(c) {
+ this._command = c;
+ if (this._command === Commands.curve && !_.isObject(this.controls)) {
+ Anchor.AppendCurveProperties(this);
+ }
+ this.trigger(Events.Types.change);
+ }
+
+ });
+
+ /**
+ * @name Two.Anchor#relative
+ * @property {Boolean}
+ * @description A boolean to render control points relative to the root anchor point or in global coordinate-space to the rest of the scene.
+ // Make it possible to bind and still have the Anchor specific
+ // inheritance from Two.Vector. In this case relying on `Two.Vector`
+ // to do much of the heavy event-listener binding / unbinding.
+ object.bind = object.on = function() {
+ var bound = this._bound;
+ Vector.prototype.bind.apply(this, arguments);
+ if (!bound) {
+ _.extend(this, AnchorProto);
+ }
+ };
+
+ }
+
+});
+
+var AnchorProto = {
+
+ constructor: Anchor,
+
+ /**
+ * @name Two.Anchor#listen
+ * @function
+ * @description Convenience method used mainly by {@link Two.Path#vertices} to listen and propagate changes from control points up to their respective anchors and further if necessary.
+ * @param {Two.Anchor} v - The anchor to apply values to.
+ * @description Copy the properties of one {@link Two.Anchor} onto another.
+ */
+ copy: function(v) {
+
+ this.x = v.x;
+ this.y = v.y;
+
+ if (typeof v.command === 'string') {
+ this.command = v.command;
+ }
+ if (_.isObject(v.controls)) {
+ if (!_.isObject(this.controls)) {
+ Anchor.AppendCurveProperties(this);
+ }
+ // TODO: Do we need to listen here?
+ this.controls.left.copy(v.controls.left);
+ this.controls.right.copy(v.controls.right);
+ }
+ if (typeof v.relative === 'boolean') {
+ this.relative = v.relative;
+ }
+
+ // TODO: Hack for `Two.Commands.arc`
+ if (this.command === Commands.arc) {
+ this.rx = v.rx;
+ this.ry = v.ry;
+ this.xAxisRotation = v.xAxisRotation;
+ this.largeArcFlag = v.largeArcFlag;
+ this.sweepFlag = v.sweepFlag;
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Anchor#clone
+ * @function
+ * @returns {Two.Anchor}
+ * @description Create a new {@link Two.Anchor}, set all its values to the current instance and return it for use.
+ */
+ clone: function() {
+
+ var controls = this.controls;
+
+ var clone = new Anchor(
+ this.x,
+ this.y,
+ controls && controls.left.x,
+ controls && controls.left.y,
+ controls && controls.right.x,
+ controls && controls.right.y,
+ this.command
+ );
+ clone.relative = this._relative;
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Anchor#toObject
+ * @function
+ * @returns {Object} - An object with properties filled out to mirror {@link Two.Anchor}.
+ * @description Create a JSON compatible plain object of the current instance. Intended for use with storing values in a database.
+ */
+ toObject: function() {
+ var o = {
+ x: this.x,
+ y: this.y
+ };
+ if (this._command) {
+ o.command = this._command;
+ }
+ if (this._relative) {
+ o.relative = this._relative;
+ }
+ if (this.controls) {
+ o.controls = {
+ left: this.controls.left.toObject(),
+ right: this.controls.right.toObject()
+ };
+ }
+ return o;
+ },
+
+ /**
+ * @name Two.Anchor#toString
+ * @function
+ * @returns {String} - A String with comma-separated values reflecting the various values on the current instance.
+ * @description Create a string form of the current instance. Intended for use with storing values in a database. This is lighter to store than the JSON compatible {@link Two.Anchor#toObject}.
+ * @description The id of the next requestAnimationFrame function.
+ */
+ nextFrameID: null,
+
+ // Primitive
+
+ /**
+ * @name Two.Types
+ * @property {Object} - The different rendering types available in the library.
+ */
+ Types: {
+ webgl: 'WebGLRenderer',
+ svg: 'SVGRenderer',
+ canvas: 'CanvasRenderer'
+ },
+
+ /**
+ * @name Two.Version
+ * @property {String} - The current working version of the library.
+ */
+ Version: 'v0.7.6',
+
+ /**
+ * @name Two.PublishDate
+ * @property {String} - The automatically generated publish date in the build process to verify version release candidates.
+ */
+ PublishDate: '2021-06-08T20:19:33.699Z',
+
+ /**
+ * @name Two.Identifier
+ * @property {String} - String prefix for all Two.js object's ids. This trickles down to SVG ids.
+ */
+ Identifier: 'two-',
+
+ /**
+ * @name Two.Resolution
+ * @property {Number} - Default amount of vertices to be used for interpreting Arcs and ArcSegments.
+ */
+ Resolution: 12,
+
+ /**
+ * @name Two.AutoCalculateImportedMatrices
+ * @property {Boolean} - When importing SVGs through the {@link two#interpret} and {@link two#load}, this boolean determines whether Two.js infers and then overrides the exact transformation matrix of the reference SVG.
+ * @nota-bene `false` copies the exact transformation matrix values, but also sets the path's `matrix.manual = true`.
+ */
+ AutoCalculateImportedMatrices: true,
+
+ /**
+ * @name Two.Instances
+ * @property {Two[]} - Registered list of all Two.js instances in the current session.
+ */
+ Instances: [],
+
+ /**
+ * @function Two.uniqueId
+ * @description Simple method to access an incrementing value. Used for `id` allocation on all Two.js objects.
+ * @returns {Number} Ever increasing Number.
+ */
+ uniqueId: function() {
+ return count++;
+ }
+
+};
+
+var HALF_PI$3 = Math.PI / 2;
+
+/**
+ * @name Two.Utils.Curve
+ * @property {Object} - Additional utility constant variables related to curve math and calculations.
+ */
+var Curve = {
+
+ CollinearityEpsilon: Math.pow(10, -30),
+
+ RecursionLimit: 16,
+
+ CuspLimit: 0,
+
+ Tolerance: {
+ distance: 0.25,
+ angle: 0,
+ epsilon: Number.EPSILON
+ },
+
+ // Lookup tables for abscissas and weights with values for n = 2 .. 16.
+ // As values are symmetric, only store half of them and adapt algorithm
+ * @param {Number} t - Zero-to-one value describing what percentage to calculate.
+ * @param {Number} a - The firt point's component value.
+ * @param {Number} b - The first point's bezier component value.
+ * @param {Number} c - The second point's bezier component value.
+ * @param {Number} d - The second point's component value.
+ * @returns {Number} The coordinate value for a specific component along a cubic bezier curve by `t`.
+ */
+var getComponentOnCubicBezier = function(t, a, b, c, d) {
+ var k = 1 - t;
+ return (k * k * k * a) + (3 * k * k * t * b) + (3 * k * t * t * c) +
+ (t * t * t * d);
+};
+
+/**
+ * @name Two.Utils.subdivide
+ * @function
+ * @param {Number} x1 - x position of first anchor point.
+ * @param {Number} y1 - y position of first anchor point.
+ * @param {Number} x2 - x position of first anchor point's "right" bezier handle.
+ * @param {Number} y2 - y position of first anchor point's "right" bezier handle.
+ * @param {Number} x3 - x position of second anchor point's "left" bezier handle.
+ * @param {Number} y3 - y position of second anchor point's "left" bezier handle.
+ * @param {Number} x4 - x position of second anchor point.
+ * @param {Number} y4 - y position of second anchor point.
+ * @param {Number} [limit=Two.Utils.Curve.RecursionLimit] - The amount of vertices to create by subdividing.
+ * @returns {Anchor[]} A list of anchor points ordered in between `x1`, `y1` and `x4`, `y4`
+ * @description Given 2 points (a, b) and corresponding control point for each return an array of points that represent points plotted along the curve. The number of returned points is determined by `limit`.
+ var x = getComponentOnCubicBezier(t, x1, x2, x3, x4);
+ var y = getComponentOnCubicBezier(t, y1, y2, y3, y4);
+ result.push(new Anchor(x, y));
+ }
+
+ return result;
+
+};
+
+/**
+ * @name Two.Utils.getCurveLength
+ * @function
+ * @param {Number} x1 - x position of first anchor point.
+ * @param {Number} y1 - y position of first anchor point.
+ * @param {Number} x2 - x position of first anchor point's "right" bezier handle.
+ * @param {Number} y2 - y position of first anchor point's "right" bezier handle.
+ * @param {Number} x3 - x position of second anchor point's "left" bezier handle.
+ * @param {Number} y3 - y position of second anchor point's "left" bezier handle.
+ * @param {Number} x4 - x position of second anchor point.
+ * @param {Number} y4 - y position of second anchor point.
+ * @param {Number} [limit=Two.Utils.Curve.RecursionLimit] - The amount of vertices to create by subdividing.
+ * @returns {Number} The length of a curve.
+ * @description Given 2 points (a, b) and corresponding control point for each, return a float that represents the length of the curve using Gauss-Legendre algorithm. Limit iterations of calculation by `limit`.
+ sum = n & 1 ? w[i++] * f(B) : 0; // Handle odd n
+ while (i < m) {
+ var Ax = A * x[i];
+ sum += w[i++] * (f(B + Ax) + f(B - Ax));
+ }
+ return A * sum;
+};
+
+/**
+ * @name Two.Utils.getCurveFromPoints
+ * @function
+ * @param {Anchor[]} points
+ * @param {Boolean} closed
+ * @description Sets the bezier handles on {@link Anchor}s in the `points` list with estimated values to create a catmull-rom like curve. Used by {@link Two.Path#plot}.
+var cos$5 = Math.cos, sin$5 = Math.sin, tan = Math.tan;
+var array = [];
+
+/**
+ * @name Two.Matrix
+ * @class
+ * @param {Number} [a=1] - The value for element at the first column and first row.
+ * @param {Number} [b=0] - The value for element at the second column and first row.
+ * @param {Number} [c=0] - The value for element at the third column and first row.
+ * @param {Number} [d=0] - The value for element at the first column and second row.
+ * @param {Number} [e=1] - The value for element at the second column and second row.
+ * @param {Number} [f=0] - The value for element at the third column and second row.
+ * @param {Number} [g=0] - The value for element at the first column and third row.
+ * @param {Number} [h=0] - The value for element at the second column and third row.
+ * @param {Number} [i=1] - The value for element at the third column and third row.
+ * @description A class to store 3 x 3 transformation matrix information. In addition to storing data `Two.Matrix` has suped up methods for commonplace mathematical operations.
+ * @nota-bene Order is based on how to construct transformation strings for the browser.
+ */
+function Matrix(a, b, c, d, e, f) {
+
+ /**
+ * @name Two.Matrix#elements
+ * @property {Number[]} - The underlying data stored as an array.
+ */
+ this.elements = new NumArray(9);
+
+ var elements = a;
+ if (!Array.isArray(elements)) {
+ elements = Array.prototype.slice.call(arguments);
+ }
+
+ // initialize the elements with default values.
+ this.identity();
+
+ if (elements.length > 0) {
+ this.set(elements);
+ }
+
+}
+
+setMatrix(Matrix);
+
+_.extend(Matrix, {
+
+ /**
+ * @name Two.Matrix.Identity
+ * @property {Number[]} - A stored reference to the default value of a 3 x 3 matrix.
+ */
+ Identity: [
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
+ ],
+
+ /**
+ * @name Two.Matrix.Multiply
+ * @function
+ * @param {Two.Matrix} A
+ * @param {Two.Matrix} B
+ * @param {Two.Matrix} [C] - An optional matrix to apply the multiplication to.
+ * @returns {Two.Matrix} - If an optional `C` matrix isn't passed then a new one is created and returned.
+ * @description Multiply two matrices together and return the result.
+ */
+ Multiply: function(A, B, C) {
+
+ if (B.length <= 3) { // Multiply Vector
+
+ var x, y, z, e = A;
+
+ var a = B[0] || 0,
+ b = B[1] || 0,
+ c = B[2] || 0;
+
+ // Go down rows first
+ // a, d, g, b, e, h, c, f, i
+
+ x = e[0] * a + e[1] * b + e[2] * c;
+ y = e[3] * a + e[4] * b + e[5] * c;
+ z = e[6] * a + e[7] * b + e[8] * c;
+
+ return { x: x, y: y, z: z };
+
+ }
+
+ var A0 = A[0], A1 = A[1], A2 = A[2];
+ var A3 = A[3], A4 = A[4], A5 = A[5];
+ var A6 = A[6], A7 = A[7], A8 = A[8];
+
+ var B0 = B[0], B1 = B[1], B2 = B[2];
+ var B3 = B[3], B4 = B[4], B5 = B[5];
+ var B6 = B[6], B7 = B[7], B8 = B[8];
+
+ C = C || new NumArray(9);
+
+ C[0] = A0 * B0 + A1 * B3 + A2 * B6;
+ C[1] = A0 * B1 + A1 * B4 + A2 * B7;
+ C[2] = A0 * B2 + A1 * B5 + A2 * B8;
+ C[3] = A3 * B0 + A4 * B3 + A5 * B6;
+ C[4] = A3 * B1 + A4 * B4 + A5 * B7;
+ C[5] = A3 * B2 + A4 * B5 + A5 * B8;
+ C[6] = A6 * B0 + A7 * B3 + A8 * B6;
+ C[7] = A6 * B1 + A7 * B4 + A8 * B7;
+ C[8] = A6 * B2 + A7 * B5 + A8 * B8;
+
+ return C;
+
+ }
+
+});
+
+_.extend(Matrix.prototype, Events, {
+
+ constructor: Matrix,
+
+ /**
+ * @name Two.Matrix#manual
+ * @property {Boolean} - Determines whether Two.js automatically calculates the values for the matrix or if the developer intends to manage the matrix.
+ * @nota-bene - Setting to `true` nullifies {@link Two.Shape#translation}, {@link Two.Shape#rotation}, and {@link Two.Shape#scale}.
+ */
+ manual: false,
+
+ /**
+ * @name Two.Matrix#set
+ * @function
+ * @param {Number} a - The value for element at the first column and first row.
+ * @param {Number} b - The value for element at the second column and first row.
+ * @param {Number} c - The value for element at the third column and first row.
+ * @param {Number} d - The value for element at the first column and second row.
+ * @param {Number} e - The value for element at the second column and second row.
+ * @param {Number} f - The value for element at the third column and second row.
+ * @param {Number} g - The value for element at the first column and third row.
+ * @param {Number} h - The value for element at the second column and third row.
+ * @param {Number} i - The value for element at the third column and third row.
+ * @description Set an array of values onto the matrix. Order described in {@link Two.Matrix}.
+ */
+
+ /**
+ * @name Two.Matrix#set
+ * @function
+ * @param {Number[]} a - The array of elements to apply.
+ * @description Set an array of values onto the matrix. Order described in {@link Two.Matrix}.
+ */
+ set: function(a, b, c, d, e, f, g, h, i) {
+
+ var elements;
+
+ if (typeof b === 'undefined') {
+ elements = a;
+ a = elements[0];
+ b = elements[1];
+ c = elements[2];
+ d = elements[3];
+ e = elements[4];
+ f = elements[5];
+ g = elements[6];
+ h = elements[7];
+ i = elements[8];
+ }
+
+ this.elements[0] = a;
+ this.elements[1] = b;
+ this.elements[2] = c;
+ this.elements[3] = d;
+ this.elements[4] = e;
+ this.elements[5] = f;
+ this.elements[6] = g;
+ this.elements[7] = h;
+ this.elements[8] = i;
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#copy
+ * @function
+ * @description Copy the matrix of one to the current instance.
+ */
+ copy: function(m) {
+
+ this.elements[0] = m.elements[0];
+ this.elements[1] = m.elements[1];
+ this.elements[2] = m.elements[2];
+ this.elements[3] = m.elements[3];
+ this.elements[4] = m.elements[4];
+ this.elements[5] = m.elements[5];
+ this.elements[6] = m.elements[6];
+ this.elements[7] = m.elements[7];
+ this.elements[8] = m.elements[8];
+
+ this.manual = m.manual;
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#identity
+ * @function
+ * @description Turn matrix to the identity, like resetting.
+ */
+ identity: function() {
+
+ this.elements[0] = Matrix.Identity[0];
+ this.elements[1] = Matrix.Identity[1];
+ this.elements[2] = Matrix.Identity[2];
+ this.elements[3] = Matrix.Identity[3];
+ this.elements[4] = Matrix.Identity[4];
+ this.elements[5] = Matrix.Identity[5];
+ this.elements[6] = Matrix.Identity[6];
+ this.elements[7] = Matrix.Identity[7];
+ this.elements[8] = Matrix.Identity[8];
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#multiply
+ * @function
+ * @param {Number} a - The scalar to be multiplied.
+ * @description Multiply all components of the matrix against a single scalar value.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Matrix#multiply
+ * @function
+ * @param {Number} a - The x component to be multiplied.
+ * @param {Number} b - The y component to be multiplied.
+ * @param {Number} c - The z component to be multiplied.
+ * @description Multiply all components of a matrix against a 3 component vector.
+ * @overloaded
+ */
+
+ /**
+ * @name Two.Matrix#multiply
+ * @function
+ * @param {Number} a - The value at the first column and first row of the matrix to be multiplied.
+ * @param {Number} b - The value at the second column and first row of the matrix to be multiplied.
+ * @param {Number} c - The value at the third column and first row of the matrix to be multiplied.
+ * @param {Number} d - The value at the first column and second row of the matrix to be multiplied.
+ * @param {Number} e - The value at the second column and second row of the matrix to be multiplied.
+ * @param {Number} f - The value at the third column and second row of the matrix to be multiplied.
+ * @param {Number} g - The value at the first column and third row of the matrix to be multiplied.
+ * @param {Number} h - The value at the second column and third row of the matrix to be multiplied.
+ * @param {Number} i - The value at the third column and third row of the matrix to be multiplied.
+ * @description Multiply all components of a matrix against another matrix.
+ * @overloaded
+ */
+ multiply: function(a, b, c, d, e, f, g, h, i) {
+
+ // Multiply scalar
+
+ if (typeof b === 'undefined') {
+
+ this.elements[0] *= a;
+ this.elements[1] *= a;
+ this.elements[2] *= a;
+ this.elements[3] *= a;
+ this.elements[4] *= a;
+ this.elements[5] *= a;
+ this.elements[6] *= a;
+ this.elements[7] *= a;
+ this.elements[8] *= a;
+
+ return this.trigger(Events.Types.change);
+
+ }
+
+ if (typeof d === 'undefined') { // Multiply Vector
+
+ var x, y, z;
+ a = a || 0;
+ b = b || 0;
+ c = c || 0;
+ e = this.elements;
+
+ // Go down rows first
+ // a, d, g, b, e, h, c, f, i
+
+ x = e[0] * a + e[1] * b + e[2] * c;
+ y = e[3] * a + e[4] * b + e[5] * c;
+ z = e[6] * a + e[7] * b + e[8] * c;
+
+ return { x: x, y: y, z: z };
+
+ }
+
+ // Multiple matrix
+
+ var A = this.elements;
+ var B = [a, b, c, d, e, f, g, h, i];
+
+ var A0 = A[0], A1 = A[1], A2 = A[2];
+ var A3 = A[3], A4 = A[4], A5 = A[5];
+ var A6 = A[6], A7 = A[7], A8 = A[8];
+
+ var B0 = B[0], B1 = B[1], B2 = B[2];
+ var B3 = B[3], B4 = B[4], B5 = B[5];
+ var B6 = B[6], B7 = B[7], B8 = B[8];
+
+ this.elements[0] = A0 * B0 + A1 * B3 + A2 * B6;
+ this.elements[1] = A0 * B1 + A1 * B4 + A2 * B7;
+ this.elements[2] = A0 * B2 + A1 * B5 + A2 * B8;
+
+ this.elements[3] = A3 * B0 + A4 * B3 + A5 * B6;
+ this.elements[4] = A3 * B1 + A4 * B4 + A5 * B7;
+ this.elements[5] = A3 * B2 + A4 * B5 + A5 * B8;
+
+ this.elements[6] = A6 * B0 + A7 * B3 + A8 * B6;
+ this.elements[7] = A6 * B1 + A7 * B4 + A8 * B7;
+ this.elements[8] = A6 * B2 + A7 * B5 + A8 * B8;
+
+ return this.trigger(Events.Types.change);
+
+ },
+
+ /**
+ * @name Two.Matrix#inverse
+ * @function
+ * @param {Two.Matrix} [out] - The optional matrix to apply the inversion to.
+ * @description Return an inverted version of the matrix. If no optional one is passed a new matrix is created and returned.
+ * @description A list of class strings stored if imported / interpreted from an SVG element.
+ */
+ this.classList = [];
+
+ /**
+ * @name Two.Shape#matrix
+ * @property {Two.Matrix}
+ * @description The transformation matrix of the shape.
+ * @nota-bene {@link Two.Shape#translation}, {@link Two.Shape#rotation}, {@link Two.Shape#scale}, {@link Two.Shape#skewX}, and {@link Two.Shape#skewY} apply their values to the matrix when changed. The matrix is what is sent to the renderer to be drawn.
+ */
+ this.matrix = new Matrix();
+
+ /**
+ * @name Two.Shape#translation
+ * @property {Two.Vector} - The x and y value for where the shape is placed relative to its parent.
+ */
+ this.translation = new Vector();
+
+ /**
+ * @name Two.Shape#rotation
+ * @property {Number} - The value in Number for how much the shape is rotated relative to its parent.
+ */
+ this.rotation = 0;
+
+ /**
+ * @name Two.Shape#scale
+ * @property {Number} - The value for how much the shape is scaled relative to its parent.
+ * @nota-bene This value can be replaced with a {@link Two.Vector} to do non-uniform scaling. e.g: `shape.scale = new Two.Vector(2, 1);`
+ */
+ this.scale = 1;
+
+ /**
+ * @name Two.Shape#skewX
+ * @property {Number} - The value in Number for how much the shape is skewed relative to its parent.
+ * @description Skew the shape by an angle in the x axis direction.
+ */
+ this.skewX = 0;
+
+ /**
+ * @name Two.Shape#skewY
+ * @property {Number} - The value in Number for how much the shape is skewed relative to its parent.
+ * @description Skew the shape by an angle in the y axis direction.
+ */
+ this.skewY = 0;
+
+}
+
+_.extend(Shape, {
+
+ /**
+ * @name Two.Shape.FlagMatrix
+ * @function
+ * @description Utility function used in conjunction with event handlers to update the flagMatrix of a shape.
+ */
+ FlagMatrix: function() {
+ this._flagMatrix = true;
+ },
+
+ /**
+ * @name Two.Shape.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Shape} to any object. Handy if you'd like to extend the {@link Two.Shape} class on a custom class.
+ * @property {Boolean} - Determines whether the {@link Two.Group#className} need updating.
+ */
+ _flagClassName: false,
+
+ // Underlying Properties
+
+ _id: '',
+
+ /**
+ * @name Two.Shape#_translation
+ * @private
+ * @property {Two.Vector} - The translation values as a {@link Two.Vector}.
+ */
+ _translation: null,
+
+ /**
+ * @name Two.Shape#_rotation
+ * @private
+ * @property {Number} - The rotation value in Number.
+ */
+ _rotation: 0,
+
+ /**
+ * @name Two.Shape#_translation
+ * @private
+ * @property {Two.Vector} - The translation values as a {@link Two.Vector}.
+ */
+ _scale: 1,
+
+ /**
+ * @name Two.Shape#_skewX
+ * @private
+ * @property {Number} - The rotation value in Number.
+ */
+ _skewX: 0,
+
+ /**
+ * @name Two.Shape#_skewY
+ * @private
+ * @property {Number} - The rotation value in Number.
+ */
+ _skewY: 0,
+
+ /**
+ * @name Two.Shape#className
+ * @property {String} - A class to be applied to the element to be compatible with CSS styling.
+ * @nota-bene Only available for the SVG renderer.
+ */
+ _className: '',
+
+ /**
+ * @name Two.Shape#addTo
+ * @function
+ * @param {Two.Group} group - The parent the shape adds itself to.
+ * @description Convenience method to add itself to the scenegraph.
+ */
+ addTo: function(group) {
+ group.add(this);
+ return this;
+ },
+
+ /**
+ * @name Two.Shape#clone
+ * @function
+ * @param {Two.Group} [parent] - Optional argument to automatically add the shape to a scenegraph.
+ * @returns {Two.Shape}
+ * @description Create a new {@link Two.Shape} with the same values as the current shape.
+ */
+ clone: function(parent) {
+
+ var clone = new Shape();
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone._update();
+
+ },
+
+ /**
+ * @name Two.Shape#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ * @description An `Array` like object with additional event propagation on actions. `pop`, `shift`, and `splice` trigger `removed` events. `push`, `unshift`, and `splice` with more than 2 arguments trigger 'inserted'. Finally, `sort` and `reverse` trigger `order` events.
+ */
+function Collection() {
+
+ Array.call(this);
+
+ if (arguments[0] && Array.isArray(arguments[0])) {
+ if (arguments[0].length > 0) {
+ Array.prototype.push.apply(this, arguments[0]);
+ }
+ } else if (arguments.length > 0) {
+ Array.prototype.push.apply(this, arguments);
+ }
+
+}
+
+Collection.prototype = new Array();
+
+_.extend(Collection.prototype, Events, {
+
+ constructor: Collection,
+
+ pop: function() {
+ var popped = Array.prototype.pop.apply(this, arguments);
+ this.trigger(Events.Types.remove, [popped]);
+ return popped;
+ },
+
+ shift: function() {
+ var shifted = Array.prototype.shift.apply(this, arguments);
+ this.trigger(Events.Types.remove, [shifted]);
+ return shifted;
+ },
+
+ push: function() {
+ var pushed = Array.prototype.push.apply(this, arguments);
+ this.trigger(Events.Types.insert, arguments);
+ return pushed;
+ },
+
+ unshift: function() {
+ var unshifted = Array.prototype.unshift.apply(this, arguments);
+ this.trigger(Events.Types.insert, arguments);
+ return unshifted;
+ },
+
+ splice: function() {
+ var spliced = Array.prototype.splice.apply(this, arguments);
+ * @description A children collection which is accesible both by index and by object `id`.
+ */
+function Children(children) {
+
+ Collection.apply(this, arguments);
+
+ Object.defineProperty(this, '_events', {
+ value : {},
+ enumerable: false
+ });
+
+ /**
+ * @name Two.Group.Children#ids
+ * @property {Object} - Map of all elements in the list keyed by `id`s.
+ */
+ this.ids = {};
+
+ this.attach(
+ Array.isArray(children) ? children : Array.prototype.slice.call(arguments)
+ );
+
+ this.on(Events.Types.insert, this.attach);
+ this.on(Events.Types.remove, this.detach);
+
+}
+
+Children.prototype = new Collection();
+
+_.extend(Children.prototype, {
+
+ constructor: Children,
+
+ /**
+ * @function
+ * @name Two.Group.Children#attach
+ * @param {Two.Shape[]} children - The objects which extend {@link Two.Shape} to be added.
+ * @description Adds elements to the `ids` map.
+ */
+ attach: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if (child && child.id) {
+ this.ids[child.id] = child;
+ }
+ }
+ return this;
+ },
+
+ /**
+ * @function
+ * @name Two.Group.Children#detach
+ * @param {Two.Shape[]} children - The objects which extend {@link Two.Shape} to be removed.
+ * @description Removes elements to the `ids` map.
+ */
+ detach: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ delete this.ids[children[i].id];
+ }
+ return this;
+ }
+
+});
+
+// Constants
+
+var min$3 = Math.min, max$3 = Math.max;
+
+/**
+ * @name Two.Group
+ * @class
+ * @extends Two.Shape
+ * @param {Two.Shape[]} [children] - A list of objects that inherit {@link Two.Shape}. For instance, the array could be a {@link Two.Path}, {@link Two.Text}, and {@link Two.RoundedRectangle}.
+ * @description This is the primary class for grouping objects that are then drawn in Two.js. In Illustrator this is a group, in After Effects it would be a Null Object. Whichever the case, the `Two.Group` contains a transformation matrix and commands to style its children, but it by itself doesn't render to the screen.
+ * @nota-bene The {@link Two#scene} is an instance of `Two.Group`.
+ */
+function Group(children) {
+
+ Shape.call(this, true);
+
+ this._renderer.type = 'group';
+
+ /**
+ * @name Two.Group#additions
+ * @property {Two.Shape[]}
+ * @description An automatically updated list of children that need to be appended to the renderer's scenegraph.
+ */
+ this.additions = [];
+
+ /**
+ * @name Two.Group#subtractions
+ * @property {Two.Shape[]}
+ * @description An automatically updated list of children that need to be removed from the renderer's scenegraph.
+ */
+ this.subtractions = [];
+
+ /**
+ * @name Two.Group#children
+ * @property {Two.Group.Children}
+ * @description A list of all the children in the scenegraph.
+ * @nota-bene Ther order of this list indicates the order each element is rendered to the screen.
+ */
+ this.children = Array.isArray(children) ? children : Array.prototype.slice.call(arguments);
+
+}
+
+_.extend(Group, {
+
+ Children: Children,
+
+ /**
+ * @name Two.Group.InsertChildren
+ * @function
+ * @param {Two.Shape[]} children - The objects to be inserted.
+ * @description Cached method to let renderers know children have been added to a {@link Two.Group}.
+ */
+ InsertChildren: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ replaceParent.call(this, children[i], this);
+ }
+ },
+
+ /**
+ * @name Two.Group.RemoveChildren
+ * @function
+ * @param {Two.Shape[]} children - The objects to be removed.
+ * @description Cached method to let renderers know children have been removed from a {@link Two.Group}.
+ */
+ RemoveChildren: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ replaceParent.call(this, children[i]);
+ }
+ },
+
+ /**
+ * @name Two.Group.OrderChildren
+ * @function
+ * @description Cached method to let renderers know order has been updated on a {@link Two.Group}.
+ */
+ OrderChildren: function(children) {
+ this._flagOrder = true;
+ },
+
+ /**
+ * @name Two.Group.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Group}.
+ */
+ Properties: [
+ 'fill',
+ 'stroke',
+ 'linewidth',
+ 'cap',
+ 'join',
+ 'miter',
+
+ 'closed',
+ 'curved',
+ 'automatic'
+ ],
+
+ /**
+ * @name Two.Group.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Group} to any object. Handy if you'd like to extend the {@link Two.Group} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ var properties = Group.Properties;
+
+ Object.defineProperty(object, 'visible', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._visible;
+ },
+
+ set: function(v) {
+ this._flagVisible = this._visible !== v || this._flagVisible;
+ this._visible = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'opacity', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._opacity;
+ },
+
+ set: function(v) {
+ this._flagOpacity = this._opacity !== v || this._flagOpacity;
+ this._opacity = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'beginning', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._beginning;
+ },
+
+ set: function(v) {
+ this._flagBeginning = this._beginning !== v || this._flagBeginning;
+ this._beginning = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'ending', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._ending;
+ },
+
+ set: function(v) {
+ this._flagEnding = this._ending !== v || this._flagEnding;
+ this._ending = v;
+ }
+
+ });
+
+ Object.defineProperty(object, 'length', {
+
+ enumerable: true,
+
+ get: function() {
+ if (this._flagLength || this._length <= 0) {
+ this._length = 0;
+ if (!this.children) {
+ return this._length;
+ }
+ for (var i = 0; i < this.children.length; i++) {
+ var child = this.children[i];
+ this._length += child.length;
+ }
+ }
+ return this._length;
+ }
+
+ });
+
+ Shape.MakeObservable(object);
+ Group.MakeGetterSetters(object, properties);
+
+ Object.defineProperty(object, 'children', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._children;
+ },
+
+ set: function(children) {
+
+ var insertChildren = Group.InsertChildren.bind(this);
+ var removeChildren = Group.RemoveChildren.bind(this);
+ var orderChildren = Group.OrderChildren.bind(this);
+ * @param {Two.Group} group - The group to apply getters and setters.
+ * @param {String} key - The key which will become a property on the group.
+ * @description Convenience method to apply getter / setter logic specific to how `Two.Group`s trickle down styles to their children. Used in {@link Two.Group.MakeObservable}.
+ */
+ MakeGetterSetter: function(group, key) {
+
+ var secret = '_' + key;
+
+ Object.defineProperty(group, key, {
+
+ enumerable: true,
+
+ get: function() {
+ return this[secret];
+ },
+
+ set: function(v) {
+ this[secret] = v;
+ // Trickle down styles
+ for (var i = 0; i < this.children.length; i++) {
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what all child shapes should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _fill: '#fff',
+
+ /**
+ * @name Two.Group#stroke
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what all child shapes should be outlined in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _stroke: '#000',
+
+ /**
+ * @name Two.Group#linewidth
+ * @property {Number} - The thickness in pixels of the stroke for all child shapes.
+ */
+ _linewidth: 1.0,
+
+ /**
+ * @name Two.Group#opacity
+ * @property {Number} - The opaqueness of all child shapes.
+ * @nota-bene Becomes multiplied by the individual child's opacity property.
+ */
+ _opacity: 1.0,
+
+ /**
+ * @name Two.Group#visible
+ * @property {Boolean} - Display the path or not.
+ * @nota-bene For {@link Two.CanvasRenderer} and {@link Two.WebGLRenderer} when set to false all updating is disabled improving performance dramatically with many objects in the scene.
+ * @property {Boolean} - Determines whether a final line is drawn between the final point in the `vertices` array and the first point of all child shapes.
+ */
+ _closed: true,
+
+ /**
+ * @name Two.Group#curved
+ * @property {Boolean} - When the child's path is `automatic = true` this boolean determines whether the lines between the points are curved or not.
+ */
+ _curved: false,
+
+ /**
+ * @name Two.Group#automatic
+ * @property {Boolean} - Determines whether or not Two.js should calculate curves, lines, and commands automatically for you or to let the developer manipulate them for themselves.
+ */
+ _automatic: true,
+
+ /**
+ * @name Two.Group#beginning
+ * @property {Number} - Number between zero and one to state the beginning of where the path is rendered.
+ * @description {@link Two.Group#beginning} is a percentage value that represents at what percentage into all child shapes should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Group#ending}.
+ */
+ _beginning: 0,
+
+ /**
+ * @name Two.Group#ending
+ * @property {Number} - Number between zero and one to state the ending of where the path is rendered.
+ * @description {@link Two.Group#ending} is a percentage value that represents at what percentage into all child shapes should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Group#beginning}.
+ */
+ _ending: 1.0,
+
+ /**
+ * @name Two.Group#length
+ * @property {Number} - The sum of distances between all child lengths.
+ */
+ _length: 0,
+
+ /**
+ * @name Two.Group#mask
+ * @property {Two.Shape} - The Two.js object to clip from a group's rendering.
+ */
+ _mask: null,
+
+ /**
+ * @name Two.Group#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Group}
+ * @description Create a new instance of {@link Two.Group} with the same properties of the current group.
+ */
+ clone: function(parent) {
+
+ // /**
+ // * TODO: Group has a gotcha in that it's at the moment required to be bound to
+ // * an instance of two in order to add elements correctly. This needs to
+ // * be rethought and fixed.
+ // */
+
+ var clone = new Group();
+ var children = this.children.map(function(child) {
+ return child.clone();
+ });
+
+ clone.add(children);
+
+ clone.opacity = this.opacity;
+
+ if (this.mask) {
+ clone.mask = this.mask;
+ }
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.className = this.className;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone._update();
+
+ },
+
+ /**
+ * @name Two.Group#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the group.
+ for (var i = 0; i < this.children.length; i++) {
+ var child = this.children[i];
+ if (child.isShape) {
+ child.translation.x -= cx;
+ child.translation.y -= cy;
+ }
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Group#getById
+ * @function
+ * @description Recursively search for id. Returns the first element found.
+ * @returns {Two.Shape} - Or `null` if nothing is found.
+ */
+ getById: function (id) {
+ var found = null;
+ function search(node) {
+ if (node.id === id) {
+ return node;
+ } else if (node.children) {
+ for (var i = 0; i < node.children.length; i++) {
+ found = search(node.children[i]);
+ if (found) {
+ return found;
+ }
+ }
+ }
+ return null;
+ }
+ return search(this);
+ },
+
+ /**
+ * @name Two.Group#getByClassName
+ * @function
+ * @description Recursively search for classes. Returns an array of matching elements.
+ * @returns {Two.Shape[]} - Or empty array if nothing is found.
+ */
+ getByClassName: function(className) {
+ var found = [];
+ function search(node) {
+ if (Array.prototype.indexOf.call(node.classList, className) >= 0) {
+ found.push(node);
+ }
+ if (node.children) {
+ for (var i = 0; i < node.children.length; i++) {
+ var child = node.children[i];
+ search(child);
+ }
+ }
+ return found;
+ }
+ return search(this);
+ },
+
+ /**
+ * @name Two.Group#getByType
+ * @function
+ * @description Recursively search for children of a specific type, e.g. {@link Two.Path}. Pass a reference to this type as the param. Returns an array of matching elements.
+ * @returns {Two.Shape[]} - Empty array if nothing is found.
+ */
+ getByType: function(type) {
+ var found = [];
+ function search(node) {
+ if (node instanceof type) {
+ found.push(node);
+ }
+ if (node.children) {
+ for (var i = 0; i < node.children.length; i++) {
+ var child = node.children[i];
+ search(child);
+ }
+ }
+ return found;
+ }
+ return search(this);
+ },
+
+ /**
+ * @name Two.Group#add
+ * @function
+ * @param {Two.Shape[]} objects - An array of objects to be added. Can be also be supplied as individual arguments.
+ * @description Add objects to the group.
+ */
+ add: function(objects) {
+
+ // Allow to pass multiple objects either as array or as multiple arguments
+ // If it's an array also create copy of it in case we're getting passed
+ * @description Apply `noFill` method to all child shapes.
+ */
+ noFill: function() {
+ this.children.forEach(function(child) {
+ child.noFill();
+ });
+ return this;
+ },
+
+ /**
+ * @name Two.Group#noStroke
+ * @function
+ * @description Apply `noStroke` method to all child shapes.
+ */
+ noStroke: function() {
+ this.children.forEach(function(child) {
+ child.noStroke();
+ });
+ return this;
+ },
+
+ /**
+ * @name Two.Group#subdivide
+ * @function
+ * @description Apply `subdivide` method to all child shapes.
+ */
+ subdivide: function() {
+ var args = arguments;
+ this.children.forEach(function(child) {
+ child.subdivide.apply(child, args);
+ });
+ return this;
+ },
+
+ /**
+ * @name Two.Group#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ var i, l, child;
+
+ if (this._flagBeginning || this._flagEnding) {
+
+ var beginning = Math.min(this._beginning, this._ending);
+ var ending = Math.max(this._beginning, this._ending);
+ * @param {Object} [parameters] - This object is inherited when constructing a new instance of {@link Two}.
+ * @param {Element} [parameters.domElement] - The `<canvas />` to draw to. If none given a new one will be constructed.
+ * @param {Boolean} [parameters.overdraw] - Determines whether the canvas should clear the background or not. Defaults to `true`.
+ * @param {Boolean} [parameters.smoothing=true] - Determines whether the canvas should antialias drawing. Set it to `false` when working with pixel art. `false` can lead to better performance, since it would use a cheaper interpolation algorithm.
+ * @description This class is used by {@link Two} when constructing with `type` of `Two.Types.canvas`. It takes Two.js' scenegraph and renders it to a `<canvas />`.
+ */
+function Renderer$2(params) {
+
+ // It might not make a big difference on GPU backed canvases.
+ var smoothing = (params.smoothing !== false);
+
+ /**
+ * @name Two.CanvasRenderer#domElement
+ * @property {Element} - The `<canvas />` associated with the Two.js scene.
+ var samePoints = Math.abs(deltaAngle) < epsilon;
+
+ // ensures that deltaAngle is 0 .. 2 PI
+ deltaAngle = mod(deltaAngle, TWO_PI$5);
+
+ if (deltaAngle < epsilon) {
+
+ if (samePoints) {
+
+ deltaAngle = 0;
+
+ } else {
+
+ deltaAngle = TWO_PI$5;
+
+ }
+
+ }
+
+ if (clockwise === true && ! samePoints) {
+
+ if (deltaAngle === TWO_PI$5) {
+
+ deltaAngle = - TWO_PI$5;
+
+ } else {
+
+ deltaAngle = deltaAngle - TWO_PI$5;
+
+ }
+
+ }
+
+ for (var i = 0; i < Constants.Resolution; i++) {
+
+ var t = i / (Constants.Resolution - 1);
+
+ var angle = startAngle + t * deltaAngle;
+ var x = ox + rx * Math.cos(angle);
+ var y = oy + ry * Math.sin(angle);
+
+ if (xAxisRotation !== 0) {
+
+ var cos = Math.cos(xAxisRotation);
+ var sin = Math.sin(xAxisRotation);
+
+ var tx = x - ox;
+ var ty = y - oy;
+
+ // Rotate the point about the center of the ellipse.
+ x = tx * cos - ty * sin + ox;
+ y = tx * sin + ty * cos + oy;
+
+ }
+
+ ctx.lineTo(x, y);
+
+ }
+
+}
+
+function svgAngle(ux, uy, vx, vy) {
+
+ var dot = ux * vx + uy * vy;
+ var len = sqrt(ux * ux + uy * uy) * sqrt(vx * vx + vy * vy);
+ // floating point precision, slightly over values appear
+ var ang = acos(max$2(-1, min$2(1, dot / len)));
+ if ((ux * vy - uy * vx) < 0) {
+ ang = - ang;
+ }
+
+ return ang;
+
+}
+
+var CanvasShim = {
+
+ Image: null,
+
+ isHeadless: false,
+
+ /**
+ * @name Two.Utils.shim
+ * @function
+ * @param {canvas} canvas - The instanced `Canvas` object provided by `node-canvas`.
+ * @param {Image} [Image] - The prototypical `Image` object provided by `node-canvas`. This is only necessary to pass if you're going to load bitmap imagery.
+ * @returns {canvas} Returns the instanced canvas object you passed from with additional attributes needed for Two.js.
+ * @description Convenience method for defining all the dependencies from the npm package `node-canvas`. See [node-canvas](https://github.com/Automattic/node-canvas) for additional information on setting up HTML5 `<canvas />` drawing in a node.js environment.
+ if (_.isElement(temp) && !root$1.document.head.contains(temp)) {
+ _.extend(temp.style, {
+ display: 'none'
+ });
+ root$1.document.head.appendChild(temp);
+ }
+ return temp;
+ }
+});
+
+/**
+ * @name Two.Utils.Error
+ * @class
+ * @description Custom error throwing for Two.js specific identification.
+ */
+function TwoError(message) {
+ this.name = 'Two.js';
+ this.message = message;
+}
+
+TwoError.prototype = new Error();
+
+_.extend(TwoError.prototype, {
+ constructor: TwoError
+});
+
+/**
+ * @name Two.Utils.defineGetterSetter
+ * @function
+ * @this Two#
+ * @param {String} property - The property to add an enumerable getter / setter to.
+ * @description Convenience function to setup the flag based getter / setter that most properties are defined as in Two.js.
+ */
+var defineGetterSetter = function(property) {
+
+ var object = this;
+ var secret = '_' + property;
+ var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);
+
+ Object.defineProperty(object, property, {
+ enumerable: true,
+ get: function() {
+ return this[secret];
+ },
+ set: function(v) {
+ this[secret] = v;
+ this[flag] = true;
+ }
+ });
+
+};
+
+/**
+ * @name Two.Registry
+ * @class
+ * @description An arbitrary class to manage a directory of things. Mainly used for keeping tabs of textures in Two.js.
+ */
+function Registry() {
+
+ this.map = {};
+
+}
+
+_.extend(Registry.prototype, {
+
+ constructor: Registry,
+
+ /**
+ * @name Two.Registry#add
+ * @function
+ * @param {String} id - A unique identifier.
+ * @param value - Any type of variable to be registered to the directory.
+ * @description Adds any value to the directory. Assigned by the `id`.
+ */
+ add: function(id, obj) {
+ this.map[id] = obj;
+ return this;
+ },
+
+ /**
+ * @name Two.Registry#remove
+ * @function
+ * @param {String} id - A unique identifier.
+ * @description Remove any value from the directory by its `id`.
+ */
+ remove: function(id) {
+ delete this.map[id];
+ return this;
+ },
+
+ /**
+ * @name Two.Registry#get
+ * @function
+ * @param {String} id - A unique identifier.
+ * @returns {?Object} The associated value. If unavailable then `undefined` is returned.
+ * @description Get a registered value by its `id`.
+ */
+ get: function(id) {
+ return this.map[id];
+ },
+
+ /**
+ * @name Two.Registry#contains
+ * @function
+ * @param {String} id - A unique identifier.
+ * @returns {Boolean}
+ * @description Convenience method to see if a value is registered to an `id` already.
+ */
+ contains: function(id) {
+ return id in this.map;
+ }
+
+});
+
+/**
+ * @name Two.Stop
+ * @class
+ * @param {Number} [offset] - The offset percentage of the stop represented as a zero-to-one value. Default value flip flops from zero-to-one as new stops are created.
+ * @param {String} [color] - The color of the stop. Default value flip flops from white to black as new stops are created.
+ * @param {Number} [opacity] - The opacity value. Default value is 1, cannot be lower than 0.
+ * @nota-bene Used specifically in conjunction with {@link Two.Gradient}s to control color graduation.
+ */
+function Stop(offset, color, opacity) {
+
+ /**
+ * @name Two.Stop#renderer
+ * @property {Object}
+ * @description Object access to store relevant renderer specific variables. Warning: manipulating this object can create unintended consequences.
+ * @nota-bene With the {@link Two.SvgRenderer} you can access the underlying SVG element created via `shape.renderer.elem`.
+ */
+ this.renderer = {};
+ this._renderer.type = 'stop';
+
+ /**
+ * @name Two.Stop#offset
+ * @property {Number} - The offset percentage of the stop represented as a zero-to-one value.
+ this.color = (typeof color === 'string') ? color
+ : Stop.Index <= 0 ? '#fff' : '#000';
+
+ Stop.Index = (Stop.Index + 1) % 2;
+
+}
+
+_.extend(Stop, {
+
+ /**
+ * @name Two.Stop.Index
+ * @property {Number} - The current index being referenced for calculating a stop's default offset value.
+ */
+ Index: 0,
+
+ /**
+ * @name Two.Stop.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Stop}.
+ */
+ Properties: [
+ 'offset',
+ 'opacity',
+ 'color'
+ ],
+
+ /**
+ * @name Two.Stop.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Stop} to any object. Handy if you'd like to extend the {@link Two.Stop} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ _.each(Stop.Properties, function(property) {
+
+ var object = this;
+ var secret = '_' + property;
+ var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);
+
+ Object.defineProperty(object, property, {
+ enumerable: true,
+ get: function() {
+ return this[secret];
+ },
+ set: function(v) {
+ this[secret] = v;
+ this[flag] = true;
+ if (this.parent) {
+ this.parent._flagStops = true;
+ }
+ }
+ });
+
+ }, object);
+
+ Object.defineProperty(object, 'renderer', {
+
+ enumerable: false,
+
+ get: function() {
+ return this._renderer;
+ },
+
+ set: function(obj) {
+ this._renderer = obj;
+ }
+
+ });
+
+ }
+
+});
+
+_.extend(Stop.prototype, Events, {
+
+ constructor: Stop,
+
+ /**
+ * @name Two.Stop#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Stop}
+ * @description Create a new instance of {@link Two.Stop} with the same properties of the current path.
+ */
+ clone: function() {
+
+ var clone = new Stop();
+
+ _.each(Stop.Properties, function(property) {
+ clone[property] = this[property];
+ }, this);
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Stop#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = {};
+
+ _.each(Stop.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.Stop#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @param {Two.Stop[]} [stops] - A list of {@link Two.Stop}s that contain the gradient fill pattern for the gradient.
+ * @description This is the base class for constructing different types of gradients with Two.js. The two common gradients are {@link Two.LinearGradient} and {@link Two.RadialGradient}.
+ */
+function Gradient(stops) {
+
+ /**
+ * @name Two.Gradient#renderer
+ * @property {Object}
+ * @description Object access to store relevant renderer specific variables. Warning: manipulating this object can create unintended consequences.
+ * @nota-bene With the {@link Two.SvgRenderer} you can access the underlying SVG element created via `shape.renderer.elem`.
+ */
+ this.renderer = {};
+ this._renderer.type = 'gradient';
+
+ /**
+ * @name Two.Gradient#id
+ * @property {String} - Session specific unique identifier.
+ * @nota-bene In the {@link Two.SvgRenderer} change this to change the underlying SVG element's id too.
+ * @property {String} - Indicates what happens if the gradient starts or ends inside the bounds of the target rectangle. Possible values are `'pad'`, `'reflect'`, and `'repeat'`.
+ * @see {@link https://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementSpreadMethodAttribute} for more information
+ */
+ this.spread = 'pad';
+
+ /**
+ * @name Two.Gradient#stops
+ * @property {Two.Stop[]} - An ordered list of {@link Two.Stop}s for rendering the gradient.
+ */
+ if (stops) {
+ this.stops = stops;
+ }
+
+}
+
+_.extend(Gradient, {
+
+ /**
+ * @name Two.Gradient.Stop
+ * @see {@link Two.Stop}
+ */
+ Stop: Stop,
+
+ /**
+ * @name Two.Gradient.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Gradient}.
+ */
+ Properties: [
+ 'spread'
+ ],
+
+ /**
+ * @name Two.Gradient.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Gradient} to any object. Handy if you'd like to extend the {@link Two.Gradient} class on a custom class.
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Gradient}
+ * @description Create a new instance of {@link Two.Gradient} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var stops = this.stops.map(function(s) {
+ return s.clone();
+ });
+
+ var clone = new Gradient(stops);
+
+ _.each(Gradient.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Gradient#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = {
+ stops: this.stops.map(function(s) {
+ return s.toObject();
+ })
+ };
+
+ _.each(Gradient.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.Gradient#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagSpread || this._flagStops) {
+ this.trigger(Events.Types.change);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Gradient#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagSpread = this._flagStops = false;
+
+ return this;
+
+ }
+
+});
+
+Gradient.MakeObservable(Gradient.prototype);
+
+/**
+ * @name Two.LinearGradient
+ * @class
+ * @extends Two.Gradient
+ * @param {Number} [x1=0] - The x position of the first end point of the linear gradient.
+ * @param {Number} [y1=0] - The y position of the first end point of the linear gradient.
+ * @param {Number} [x2=0] - The x position of the second end point of the linear gradient.
+ * @param {Number} [y2=0] - The y position of the second end point of the linear gradient.
+ * @param {Two.Stop[]} [stops] - A list of {@link Two.Stop}s that contain the gradient fill pattern for the gradient.
+ * @nota-bene The linear gradient lives within the space of the parent object's matrix space.
+ */
+function LinearGradient(x1, y1, x2, y2, stops) {
+
+ Gradient.call(this, stops);
+
+ this._renderer.type = 'linear-gradient';
+
+ var flagEndPoints = LinearGradient.FlagEndPoints.bind(this);
+
+ /**
+ * @name Two.LinearGradient#left
+ * @property {Two.Vector} - The x and y value for where the first end point is placed on the canvas.
+ */
+ this.left = new Vector().bind(Events.Types.change, flagEndPoints);
+ /**
+ * @name Two.LinearGradient#right
+ * @property {Two.Vector} - The x and y value for where the second end point is placed on the canvas.
+ */
+ this.right = new Vector().bind(Events.Types.change, flagEndPoints);
+
+ if (typeof x1 === 'number') {
+ this.left.x = x1;
+ }
+ if (typeof y1 === 'number') {
+ this.left.y = y1;
+ }
+ if (typeof x2 === 'number') {
+ this.right.x = x2;
+ }
+ if (typeof y2 === 'number') {
+ this.right.y = y2;
+ }
+
+}
+
+_.extend(LinearGradient, {
+
+ /**
+ * @name Two.LinearGradient.Stop
+ * @see {@link Two.Stop}
+ */
+ Stop: Stop,
+
+ /**
+ * @name Two.LinearGradient.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.LinearGradient} to any object. Handy if you'd like to extend the {@link Two.LinearGradient} class on a custom class.
+ */
+ MakeObservable: function(object) {
+ Gradient.MakeObservable(object);
+ },
+
+ /**
+ * @name Two.LinearGradient.FlagEndPoints
+ * @function
+ * @description Cached method to let renderers know end points have been updated on a {@link Two.LinearGradient}.
+ * @property {Boolean} - Determines whether the {@link Two.LinearGradient#left} or {@link Two.LinearGradient#right} changed and needs to update.
+ */
+ _flagEndPoints: false,
+
+ /**
+ * @name Two.LinearGradient#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Gradient}
+ * @description Create a new instance of {@link Two.LinearGradient} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var stops = this.stops.map(function(stop) {
+ return stop.clone();
+ });
+
+ var clone = new LinearGradient(this.left._x, this.left._y,
+ this.right._x, this.right._y, stops);
+
+ _.each(Gradient.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.LinearGradient#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = Gradient.prototype.toObject.call(this);
+
+ result.left = this.left.toObject();
+ result.right = this.right.toObject();
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.LinearGradient#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagEndPoints || this._flagSpread || this._flagStops) {
+ this.trigger(Events.Types.change);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.LinearGradient#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @property {Two.Vector} - The x and y value for where the origin of the radial gradient is.
+ */
+ this.center = new Vector()
+ .bind(Events.Types.change, (function() {
+ this._flagCenter = true;
+ }).bind(this));
+
+ this.radius = typeof r === 'number' ? r : 20;
+
+ /**
+ * @name Two.RadialGradient#focal
+ * @property {Two.Vector} - The x and y value for where the focal point of the radial gradient is.
+ * @nota-bene This effects the spray or spread of the radial gradient.
+ */
+ this.focal = new Vector()
+ .bind(Events.Types.change, (function() {
+ this._flagFocal = true;
+ }).bind(this));
+
+ if (typeof cx === 'number') {
+ this.center.x = cx;
+ }
+ if (typeof cy === 'number') {
+ this.center.y = cy;
+ }
+
+ this.focal.copy(this.center);
+
+ if (typeof fx === 'number') {
+ this.focal.x = fx;
+ }
+ if (typeof fy === 'number') {
+ this.focal.y = fy;
+ }
+
+}
+
+_.extend(RadialGradient, {
+
+ /**
+ * @name Two.RadialGradient.Stop
+ * @see {@link Two.Stop}
+ */
+ Stop: Stop,
+
+ /**
+ * @name Two.RadialGradient.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.RadialGradient}.
+ */
+ Properties: [
+ 'radius'
+ ],
+
+ /**
+ * @name Two.RadialGradient.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.RadialGradient} to any object. Handy if you'd like to extend the {@link Two.RadialGradient} class on a custom class.
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var result = Gradient.prototype.toObject.call(this);
+
+ _.each(RadialGradient.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ result.center = this.center.toObject();
+ result.focal = this.focal.toObject();
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.RadialGradient#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagRadius || this._flatCenter || this._flagFocal
+ || this._flagSpread || this._flagStops) {
+ this.trigger(Events.Types.change);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.RadialGradient#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @param {String|HTMLImageElement} [src] - The URL path to an image file or an `<img />` element.
+ * @param {Function} [callback] - An optional callback function once the image has been loaded.
+ * @description Fundamental to work with bitmap data, a.k.a. pregenerated imagery, in Two.js. Supported formats include jpg, png, gif, and tiff. See {@link Two.Texture.RegularExpressions} for a full list of supported formats.
+ */
+function Texture(src, callback) {
+
+ /**
+ * @name Two.Texture#renderer
+ * @property {Object}
+ * @description Object access to store relevant renderer specific variables. Warning: manipulating this object can create unintended consequences.
+ * @nota-bene With the {@link Two.SvgRenderer} you can access the underlying SVG element created via `shape.renderer.elem`.
+ * @property {Two.Vector} - A two-component vector describing any pixel offset of the texture when applied to a {@link Two.Path}.
+ */
+ this.offset = new Vector();
+
+ if (typeof callback === 'function') {
+ var loaded = (function() {
+ this.unbind(Events.Types.load, loaded);
+ if (typeof callback === 'function') {
+ callback();
+ }
+ }).bind(this);
+ this.bind(Events.Types.load, loaded);
+ }
+
+ /**
+ * @name Two.Texture#src
+ * @property {String} - The URL path to the image data.
+ * @nota-bene This property is ultimately serialized in a {@link Two.Registry} to cache retrieval.
+ */
+ if (typeof src === 'string') {
+ this.src = src;
+ } else if (typeof src === 'object') {
+ var elemString = Object.prototype.toString.call(src);
+ if (
+ elemString === '[object HTMLImageElement]' ||
+ elemString === '[object HTMLCanvasElement]' ||
+ elemString === '[object HTMLVideoElement]' ||
+ elemString === '[object Image]'
+ ) {
+ /**
+ * @name Two.Texture#image
+ * @property {Element} - The corresponding DOM Element of the texture. Can be a `<img />`, `<canvas />`, or `<video />` element. See {@link Two.Texture.RegularExpressions} for a full list of supported elements.
+ * @nota-bene In headless environments this is a `Canvas.Image` object. See {@link https://github.com/Automattic/node-canvas} for more information on headless image objects.
+ */
+ this.image = src;
+ }
+ }
+
+ this._update();
+
+}
+
+_.extend(Texture, {
+
+ /**
+ * @name Two.Texture.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Texture}.
+ */
+ Properties: [
+ 'id',
+ 'src',
+ 'loaded',
+ 'repeat'
+ ],
+
+ /**
+ * @name Two.Texture.RegularExpressions
+ * @property {Object} - A map of compatible DOM Elements categorized by media format.
+ */
+ RegularExpressions: regex$1,
+
+ /**
+ * @name Two.Texture.ImageRegistry
+ * @property {Two.Registry} - A canonical listing of image data used in a single session of Two.js.
+ * @nota-bene This object is used to cache image data between different textures.
+ */
+ ImageRegistry: new Registry(),
+
+ /**
+ * @name Two.Texture.getAbsoluteURL
+ * @property {Function} - Serializes a URL as an absolute path for canonical attribution in {@link Two.ImageRegistry}.
+ * @param {String} path
+ * @returns {String} - The serialized absolute path.
+ */
+ getAbsoluteURL: function(path) {
+ if (!anchor) {
+ // TODO: Fix for headless environments
+ return path;
+ }
+ anchor.href = path;
+ return anchor.href;
+ },
+
+ /**
+ * @name Two.Texture.loadHeadlessBuffer
+ * @property {Function} - Loads an image as a buffer in headless environments.
+ * @param {Two.Texture} texture - The {@link Two.Texture} to be loaded.
+ * @param {Function} loaded - The callback function to be triggered once the image is loaded.
+ * @nota-bene - This function uses node's `fs.readFileSync` to spoof the `<img />` loading process in the browser.
+ */
+ loadHeadlessBuffer: function(texture, loaded) {
+
+ texture.image.onload = loaded;
+ texture.image.src = texture.src;
+
+ },
+
+ /**
+ * @name Two.Texture.getTag
+ * @property {Function} - Retrieves the tag name of an image, video, or canvas node.
+ * @param {HTMLImageElement} - The image to infer the tag name from.
+ * @returns {String} - Returns the tag name of an image, video, or canvas node.
+ * @property {Function} - Convenience function to set {@link Two.Texture#image} properties with canonincal versions set in {@link Two.Texture.ImageRegistry}.
+ * @param {String} src - The URL path of the image.
+ * @returns {HTMLImageElement} - Returns either a cached version of the image or a new one that is registered in {@link Two.Texture.ImageRegistry}.
+ */
+ getImage: function(src) {
+
+ var absoluteSrc = Texture.getAbsoluteURL(src);
+
+ if (Texture.ImageRegistry.contains(absoluteSrc)) {
+ return Texture.ImageRegistry.get(absoluteSrc);
+ }
+
+ var image;
+
+ if (CanvasShim.Image) {
+
+ // TODO: Fix for headless environments
+ image = new CanvasShim.Image();
+ Renderer$2.Utils.shim(image, 'img');
+
+ } else if (root$1.document) {
+
+ if (regex$1.video.test(absoluteSrc)) {
+ image = document.createElement('video');
+ } else {
+ image = document.createElement('img');
+ }
+
+ } else {
+
+ console.warn('Two.js: no prototypical image defined for Two.Texture');
+
+ }
+
+ image.crossOrigin = 'anonymous';
+
+ return image;
+
+ },
+
+ /**
+ * @name Two.Register
+ * @interface
+ * @description A collection of functions to register different types of textures. Used internally by a {@link Two.Texture}.
+ * @description Cached method to let renderers know `offset` has been updated on a {@link Two.Texture}.
+ */
+ FlagOffset: function() {
+ this._flagOffset = true;
+ },
+
+ /**
+ * @name Two.Texture.FlagScale
+ * @function
+ * @description Cached method to let renderers know `scale` has been updated on a {@link Two.Texture}.
+ */
+ FlagScale: function() {
+ this._flagScale = true;
+ },
+
+ /**
+ * @name Two.Texture.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Texture} to any object. Handy if you'd like to extend or inherit the {@link Two.Texture} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagSrc || this._flagImage) {
+
+ this.trigger(Events.Types.change);
+
+ if (this._flagSrc || this._flagImage) {
+ this.loaded = false;
+ Texture.load(this, (function() {
+ this.loaded = true;
+ this
+ .trigger(Events.Types.change)
+ .trigger(Events.Types.load);
+ }).bind(this));
+ }
+
+ }
+
+ if (this._image && this._image.readyState >= 4) {
+ this._flagVideo = true;
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Texture#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @param {Two.Anchor[]} [vertices] - A list of {@link Two.Anchor}s that represent the order and coordinates to construct the rendered shape.
+ * @param {Boolean} [closed=false] - Describes whether the shape is closed or open.
+ * @param {Boolean} [curved=false] - Describes whether the shape automatically calculates bezier handles for each vertex.
+ * @param {Boolean} [manual=false] - Describes whether the developer controls how vertices are plotted or if Two.js automatically plots coordinates based on closed and curved booleans.
+ * @description This is the primary primitive class for creating all drawable shapes in Two.js. Unless specified methods return their instance of `Two.Path` for the purpose of chaining.
+ * @property {Boolean} - Determines whether a final line is drawn between the final point in the `vertices` array and the first point.
+ */
+ this._closed = !!closed;
+
+ /**
+ * @name Two.Path#curved
+ * @property {Boolean} - When the path is `automatic = true` this boolean determines whether the lines between the points are curved or not.
+ */
+ this._curved = !!curved;
+
+ /**
+ * @name Two.Path#beginning
+ * @property {Number} - Number between zero and one to state the beginning of where the path is rendered.
+ * @description {@link Two.Path#beginning} is a percentage value that represents at what percentage into the path should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Path#ending}.
+ */
+ this.beginning = 0;
+
+ /**
+ * @name Two.Path#ending
+ * @property {Number} - Number between zero and one to state the ending of where the path is rendered.
+ * @description {@link Two.Path#ending} is a percentage value that represents at what percentage into the path should the renderer start drawing.
+ * @nota-bene This is great for animating in and out stroked paths in conjunction with {@link Two.Path#beginning}.
+ */
+ this.ending = 1;
+
+ // Style properties
+
+ /**
+ * @name Two.Path#fill
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the path should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ this.fill = '#fff';
+
+ /**
+ * @name Two.Path#stroke
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the path should be outlined in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ this.stroke = '#000';
+
+ /**
+ * @name Two.Path#linewidth
+ * @property {Number} - The thickness in pixels of the stroke.
+ */
+ this.linewidth = 1.0;
+
+ /**
+ * @name Two.Path#opacity
+ * @property {Number} - The opaqueness of the path.
+ * @nota-bene Can be used in conjunction with CSS Colors that have an alpha value.
+ */
+ this.opacity = 1.0;
+
+ /**
+ * @name Two.Path#className
+ * @property {String} - A class to be applied to the element to be compatible with CSS styling.
+ * @nota-bene Only available for the SVG renderer.
+ */
+ this.className = '';
+
+ /**
+ * @name Two.Path#visible
+ * @property {Boolean} - Display the path or not.
+ * @nota-bene For {@link Two.CanvasRenderer} and {@link Two.WebGLRenderer} when set to false all updating is disabled improving performance dramatically with many objects in the scene.
+ * @property {Two.Anchor[]} - An ordered list of anchor points for rendering the path.
+ * @description A list of {@link Two.Anchor} objects that consist of what form the path takes.
+ * @nota-bene The array when manipulating is actually a {@link Two.Collection}.
+ */
+ this.vertices = vertices;
+
+ /**
+ * @name Two.Path#automatic
+ * @property {Boolean} - Determines whether or not Two.js should calculate curves, lines, and commands automatically for you or to let the developer manipulate them for themselves.
+ */
+ this.automatic = !manual;
+
+ /**
+ * @name Two.Path#dashes
+ * @property {Number[]} - Array of numbers. Odd indices represent dash length. Even indices represent dash space.
+ * @description A list of numbers that represent the repeated dash length and dash space applied to the stroke of the text.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray} for more information on the SVG stroke-dasharray attribute.
+ */
+ this.dashes = [];
+
+ /**
+ * @name Two.Path#dashes#offset
+ * @property {Number} - A number in pixels to offset {@link Two.Path#dashes} display.
+ */
+ this.dashes.offset = 0;
+
+}
+
+_.extend(Path, {
+
+ /**
+ * @name Two.Path.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Path}.
+ */
+ Properties: [
+ 'fill',
+ 'stroke',
+ 'linewidth',
+ 'opacity',
+ 'visible',
+ 'cap',
+ 'join',
+ 'miter',
+
+ 'closed',
+ 'curved',
+ 'automatic',
+ 'beginning',
+ 'ending'
+ ],
+
+ Utils: {
+ getCurveLength: getCurveLength
+ },
+
+ /**
+ * @name Two.Path.FlagVertices
+ * @function
+ * @description Cached method to let renderers know vertices have been updated on a {@link Two.Path}.
+ */
+ FlagVertices: function() {
+ this._flagVertices = true;
+ this._flagLength = true;
+ if (this.parent) {
+ this.parent._flagLength = true;
+ }
+ },
+
+ /**
+ * @name Two.Path.BindVertices
+ * @function
+ * @description Cached method to let {@link Two.Path} know vertices have been added to the instance.
+ * @description Cached method to let {@link Two.Path} know the fill has changed.
+ */
+ FlagFill: function() {
+ this._flagFill = true;
+ },
+
+ /**
+ * @name Two.Path.FlagFill
+ * @function
+ * @description Cached method to let {@link Two.Path} know the stroke has changed.
+ */
+ FlagStroke: function() {
+ this._flagStroke = true;
+ },
+
+ /**
+ * @name Two.Path.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Path} to any object. Handy if you'd like to extend the {@link Two.Path} class on a custom class.
+ */
+ MakeObservable: function(object) {
+
+ Shape.MakeObservable(object);
+
+ // Only the 7 defined properties are flagged like this. The subsequent
+ // properties behave differently and need to be hand written.
+ * @property {Number} - The sum of distances between all {@link Two.Path#vertices}.
+ */
+ Object.defineProperty(object, 'length', {
+ get: function() {
+ if (this._flagLength) {
+ this._updateLength();
+ }
+ return this._length;
+ }
+ });
+
+ Object.defineProperty(object, 'closed', {
+ enumerable: true,
+ get: function() {
+ return this._closed;
+ },
+ set: function(v) {
+ this._closed = !!v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'curved', {
+ enumerable: true,
+ get: function() {
+ return this._curved;
+ },
+ set: function(v) {
+ this._curved = !!v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'automatic', {
+ enumerable: true,
+ get: function() {
+ return this._automatic;
+ },
+ set: function(v) {
+ if (v === this._automatic) {
+ return;
+ }
+ this._automatic = !!v;
+ var method = this._automatic ? 'ignore' : 'listen';
+ _.each(this.vertices, function(v) {
+ v[method]();
+ });
+ }
+ });
+
+ Object.defineProperty(object, 'beginning', {
+ enumerable: true,
+ get: function() {
+ return this._beginning;
+ },
+ set: function(v) {
+ this._beginning = v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'ending', {
+ enumerable: true,
+ get: function() {
+ return this._ending;
+ },
+ set: function(v) {
+ this._ending = v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'vertices', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._collection;
+ },
+
+ set: function(vertices) {
+
+ var bindVertices = this._renderer.bindVertices;
+ var unbindVertices = this._renderer.unbindVertices;
+
+ // Remove previous listeners
+ if (this._collection) {
+ this._collection
+ .unbind(Events.Types.insert, bindVertices)
+ .unbind(Events.Types.remove, unbindVertices);
+ }
+
+ // Create new Collection with copy of vertices
+ if (vertices instanceof Collection) {
+ this._collection = vertices;
+ } else {
+ this._collection = new Collection(vertices || []);
+ }
+
+
+ // Listen for Collection changes and bind / unbind
+ this._collection
+ .bind(Events.Types.insert, bindVertices)
+ .bind(Events.Types.remove, unbindVertices);
+
+ // Bind Initial Vertices
+ bindVertices(this._collection);
+
+ }
+
+ });
+
+ /**
+ * @name Two.Path#mask
+ * @property {Two.Shape} - The shape whose alpha property becomes a clipping area for the path.
+ * @nota-bene This property is currently not working becuase of SVG spec issues found here {@link https://code.google.com/p/chromium/issues/detail?id=370951}.
+ */
+ Object.defineProperty(object, 'mask', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._mask;
+ },
+
+ set: function(v) {
+ this._mask = v;
+ this._flagMask = true;
+ if (!v.clip) {
+ v.clip = true;
+ }
+ }
+
+ });
+
+ /**
+ * @name Two.Path#clip
+ * @property {Boolean} - Tells Two.js renderer if this object represents a mask for another object (or not).
+ */
+ Object.defineProperty(object, 'clip', {
+ enumerable: true,
+ get: function() {
+ return this._clip;
+ },
+ set: function(v) {
+ this._clip = v;
+ this._flagClip = true;
+ }
+ });
+
+ Object.defineProperty(object, 'dashes', {
+ enumerable: true,
+ get: function() {
+ return this._dashes;
+ },
+ set: function(v) {
+ if (typeof v.offset !== 'number') {
+ v.offset = this._dashes.offset || 0;
+ }
+ this._dashes = v;
+ }
+ });
+
+ }
+
+});
+
+_.extend(Path.prototype, Shape.prototype, {
+
+ constructor: Path,
+
+ // Flags
+ // http://en.wikipedia.org/wiki/Flag
+
+ /**
+ * @name Two.Path#_flagVertices
+ * @private
+ * @property {Boolean} - Determines whether the {@link Two.Path#vertices} need updating.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices) {
+
+ if (this._automatic) {
+ this.plot();
+ }
+
+ if (this._flagLength) {
+ this._updateLength(undefined, true);
+ }
+
+ var l = this._collection.length;
+ var closed = this._closed;
+
+ var beginning = Math.min(this._beginning, this._ending);
+ var ending = Math.max(this._beginning, this._ending);
+
+ var bid = getIdByLength(this, beginning * this._length);
+ var eid = getIdByLength(this, ending * this._length);
+ * @param {Number} [x=0] - The x position of the rectangle.
+ * @param {Number} [y=0] - The y position of the rectangle.
+ * @param {Number} [width] - The width value of the rectangle.
+ * @param {Number} [height] - The width value of the rectangle.
+ */
+function Rectangle(x, y, width, height) {
+
+ Path.call(this, [
+ new Anchor(),
+ new Anchor(),
+ new Anchor(),
+ new Anchor()
+ // new Anchor() // TODO: Figure out how to handle this for `beginning` / `ending` animations
+ ], true, false, true);
+
+ /**
+ * @name Two.Rectangle#width
+ * @property {Number} - The size of the width of the rectangle.
+ */
+ this.width = width;
+ /**
+ * @name Two.Rectangle#height
+ * @property {Number} - The size of the height of the rectangle.
+ */
+ this.height = height;
+
+ /**
+ * @name Two.Rectangle#origin
+ * @property {Number} - A two-component vector describing the origin offset to draw the rectangle. Default is `0, 0`.
+ */
+ this.origin = new Vector();
+ this.translation.set(x, y);
+
+ this._update();
+
+}
+
+_.extend(Rectangle, {
+
+ /**
+ * @name Two.Rectangle.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Rectangle}.
+ */
+ Properties: ['width', 'height'],
+
+ /**
+ * @name Two.Rectangle.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Rectangle} to any object. Handy if you'd like to extend the {@link Two.Rectangle} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight) {
+
+ var xr = this._width / 2;
+ var yr = this._height / 2;
+
+ if (!this._closed && this.vertices.length === 4) {
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = false;
+ Path.prototype.flagReset.call(this);
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Rectangle#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Rectangle}
+ * @description Create a new instance of {@link Two.Rectangle} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var clone = new Rectangle(0, 0, this.width, this.height);
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ _.each(Path.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Rectangle#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var object = Path.prototype.toObject.call(this);
+ object.width = this.width;
+ object.height = this.height;
+ object.origin = this.origin.toObject();
+ return object;
+
+ }
+
+});
+
+Rectangle.MakeObservable(Rectangle.prototype);
+
+/**
+ * @name Two.Sprite
+ * @class
+ * @extends Two.Rectangle
+ * @param {String|Two.Texture} [path] - The URL path or {@link Two.Texture} to be used as the bitmap data displayed on the sprite.
+ * @param {Number} [ox=0] - The initial `x` position of the Two.Sprite.
+ * @param {Number} [oy=0] - The initial `y` position of the Two.Sprite.
+ * @param {Number} [cols=1] - The number of columns the sprite contains.
+ * @param {Number} [rows=1] - The number of rows the sprite contains.
+ * @param {Number} [frameRate=0] - The frame rate at which the partitions of the image should playback at.
+ * @description A convenient package to display still or animated images through a tiled image source. For more information on the principals of animated imagery through tiling see [Texture Atlas](https://en.wikipedia.org/wiki/Texture_atlas) on Wikipedia.
+ */
+function Sprite(path, ox, oy, cols, rows, frameRate) {
+
+ // Not using default constructor of Rectangle due to odd `beginning` / `ending` behavior.
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Sprite} to any object. Handy if you'd like to extend or inherit the {@link Two.Sprite} class on a custom class.
+ * @property {Number} - Number of frames for a given {@link Two.Sprite}.
+ */
+ _amount: 1,
+
+ /**
+ * @name Two.Sprite#_duration
+ * @private
+ * @property {Number} - Number of milliseconds a {@link Two.Sprite}.
+ */
+ _duration: 0,
+
+ /**
+ * @name Two.Sprite#_startTime
+ * @private
+ * @property {Milliseconds} - Epoch time in milliseconds of when the {@link Two.Sprite} started.
+ */
+ _startTime: 0,
+
+ /**
+ * @name Two.Sprite#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.Sprite} is animating or not.
+ */
+ _playing: false,
+
+ /**
+ * @name Two.Sprite#_firstFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.Sprite} should start with.
+ */
+ _firstFrame: 0,
+
+ /**
+ * @name Two.Sprite#_lastFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.Sprite} should end with.
+ */
+ _lastFrame: 0,
+
+ /**
+ * @name Two.Sprite#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.Sprite} should loop or not.
+ */
+ _loop: true,
+
+ // Exposed through getter-setter
+
+ /**
+ * @name Two.Sprite#_texture
+ * @private
+ * @see {@link Two.Sprite#texture}
+ */
+ _texture: null,
+
+ /**
+ * @name Two.Sprite#_columns
+ * @private
+ * @see {@link Two.Sprite#columns}
+ */
+ _columns: 1,
+
+ /**
+ * @name Two.Sprite#_rows
+ * @private
+ * @see {@link Two.Sprite#rows}
+ */
+ _rows: 1,
+
+ /**
+ * @name Two.Sprite#_frameRate
+ * @private
+ * @see {@link Two.Sprite#frameRate}
+ */
+ _frameRate: 0,
+
+ /**
+ * @name Two.Sprite#_index
+ * @private
+ * @property {Number} - The current frame the {@link Two.Sprite} is currently displaying.
+ */
+ _index: 0,
+
+ /**
+ * @name Two.Sprite#_origin
+ * @private
+ * @see {@link Two.Sprite#origin}
+ */
+ _origin: null,
+
+ /**
+ * @name Two.Sprite#play
+ * @function
+ * @param {Number} [firstFrame=0] - The index of the frame to start the animation with.
+ * @param {Number} [lastFrame] - The index of the frame to end the animation with. Defaults to the last item in the {@link Two.Sprite#textures}.
+ * @param {Function} [onLastFrame] - Optional callback function to be triggered after playing the last frame. This fires multiple times when the sprite is looped.
+ * @description Initiate animation playback of a {@link Two.Sprite}.
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+ var object = Rectangle.prototype.toObject.call(this);
+ object.texture = this.texture.toObject();
+ object.columns = this.columns;
+ object.rows = this.rows;
+ object.frameRate = this.frameRate;
+ object.index = this.index;
+ object._firstFrame = this._firstFrame;
+ object._lastFrame = this._lastFrame;
+ object._loop = this._loop;
+ return object;
+ },
+
+ /**
+ * @name Two.Sprite#_update
+ * @function
+ * @private
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ * @param {Number} [x=0] - The x position of the circle.
+ * @param {Number} [y=0] - The y position of the circle.
+ * @param {Number} [radius=0] - The radius value of the circle.
+ * @param {Number} [resolution=4] - The number of vertices used to construct the circle.
+ */
+function Circle(ox, oy, r, resolution) {
+
+ // At least 2 vertices are required for proper circlage
+ var amount = resolution ? Math.max(resolution, 2) : 4;
+
+ var points = [];
+ for (var i = 0; i < amount; i++) {
+ points.push(new Anchor(0, 0, 0, 0, 0, 0));
+ }
+
+ Path.call(this, points, true, true, true);
+
+ /**
+ * @name Two.Circle#radius
+ * @property {Number} - The size of the radius of the circle.
+ */
+ if (typeof r === 'number') {
+ this.radius = r;
+ }
+
+ this._update();
+
+ if (typeof ox === 'number') {
+ this.translation.x = ox;
+ }
+ if (typeof oy === 'number') {
+ this.translation.y = oy;
+ }
+
+}
+
+_.extend(Circle, {
+
+ /**
+ * @name Two.Circle.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Circle}.
+ */
+ Properties: ['radius'],
+
+ /**
+ * @name Two.Circle.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Circle} to any object. Handy if you'd like to extend the {@link Two.Circle} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagRadius) {
+
+ var length = this.vertices.length;
+
+ if (!this._closed && length > 2) {
+ length -= 1;
+ }
+
+ // Coefficient for approximating circular arcs with Bezier curves
+ var c = (4 / 3) * Math.tan(Math.PI / (length * 2));
+ var radius = this._radius;
+ var rc = radius * c;
+
+ for (var i = 0; i < this.vertices.length; i++) {
+ var pct = i / length;
+ var theta = pct * TWO_PI$4;
+
+ var x = radius * cos$3(theta);
+ var y = radius * sin$3(theta);
+
+ var lx = rc * cos$3(theta - HALF_PI$2);
+ var ly = rc * sin$3(theta - HALF_PI$2);
+
+ var rx = rc * cos$3(theta + HALF_PI$2);
+ var ry = rc * sin$3(theta + HALF_PI$2);
+
+ var v = this.vertices[i];
+
+ v.command = i === 0 ? Commands.move : Commands.curve;
+ v.set(x, y);
+ v.controls.left.set(lx, ly);
+ v.controls.right.set(rx, ry);
+ }
+ }
+
+ Path.prototype._update.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Circle#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagRadius = false;
+
+ Path.prototype.flagReset.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Circle#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Circle}
+ * @description Create a new instance of {@link Two.Circle} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var clone = new Circle(0, 0, this.radius, this.vertices.length);
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ _.each(Path.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Circle#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var object = Path.prototype.toObject.call(this);
+ * @param {Number} [x=0] - The x position of the ellipse.
+ * @param {Number} [y=0] - The y position of the ellipse.
+ * @param {Number} [rx=0] - The radius value of the ellipse in the x direction.
+ * @param {Number} [ry=0] - The radius value of the ellipse in the y direction.
+ * @param {Number} [resolution=4] - The number of vertices used to construct the ellipse.
+ */
+function Ellipse(ox, oy, rx, ry, resolution) {
+
+ if (typeof ry !== 'number' && typeof rx === 'number') {
+ ry = rx;
+ }
+
+ // At least 2 vertices are required for proper circlage
+ var amount = resolution ? Math.max(resolution, 2) : 4;
+
+ var points = [];
+ for (var i = 0; i < amount; i++) {
+ points.push(new Anchor());
+ }
+
+ Path.call(this, points, true, true, true);
+
+ /**
+ * @name Two.Ellipse#width
+ * @property {Number} - The width of the ellipse.
+ */
+ if (typeof rx === 'number') {
+ this.width = rx * 2;
+ }
+
+ /**
+ * @name Two.Ellipse#height
+ * @property {Number} - The height of the ellipse.
+ */
+ if (typeof ry === 'number') {
+ this.height = ry * 2;
+ }
+
+ this._update();
+ this.translation.set(ox, oy);
+
+}
+
+_.extend(Ellipse, {
+
+ /**
+ * @name Two.Ellipse.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Ellipse}.
+ */
+ Properties: ['width', 'height'],
+
+ /**
+ * @name Two.Ellipse.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Ellipse} to any object. Handy if you'd like to extend the {@link Two.Ellipse} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight) {
+
+ var length = this.vertices.length;
+
+ if (!this._closed && length > 2) {
+ length -= 1;
+ }
+
+ // Coefficient for approximating circular arcs with Bezier curves
+ var c = (4 / 3) * Math.tan(Math.PI / (this.vertices.length * 2));
+ var radiusX = this._width / 2;
+ var radiusY = this._height / 2;
+
+ for (var i = 0; i < this.vertices.length; i++) {
+ var pct = i / length;
+ var theta = pct * TWO_PI$3;
+
+ var x = radiusX * cos$2(theta);
+ var y = radiusY * sin$2(theta);
+
+ var lx = radiusX * c * cos$2(theta - HALF_PI$1);
+ var ly = radiusY * c * sin$2(theta - HALF_PI$1);
+
+ var rx = radiusX * c * cos$2(theta + HALF_PI$1);
+ var ry = radiusY * c * sin$2(theta + HALF_PI$1);
+
+ var v = this.vertices[i];
+
+ v.command = i === 0 ? Commands.move : Commands.curve;
+ v.set(x, y);
+ v.controls.left.set(lx, ly);
+ v.controls.right.set(rx, ry);
+ }
+ }
+
+ Path.prototype._update.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Ellipse#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ */
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = false;
+
+ Path.prototype.flagReset.call(this);
+ return this;
+
+ },
+
+ /**
+ * @name Two.Ellipse#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Polygon}
+ * @description Create a new instance of {@link Two.Polygon} with the same properties of the current path.
+ */
+ clone: function(parent) {
+
+ var rx = this.width / 2;
+ var ry = this.height / 2;
+ var resolution = this.vertices.length;
+ var clone = new Ellipse(0, 0, rx, ry, resolution);
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ clone.skewX = this.skewX;
+ clone.skewY = this.skewY;
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ _.each(Path.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ /**
+ * @name Two.Ellipse#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the path.
+ */
+ toObject: function() {
+
+ var object = Path.prototype.toObject.call(this);
+
+ _.each(Ellipse.Properties, function(property) {
+ object[property] = this[property];
+ }, this);
+
+ return object;
+
+ }
+
+});
+
+Ellipse.MakeObservable(Ellipse.prototype);
+
+/**
+ * @name Two.Line
+ * @class
+ * @extends Two.Path
+ * @param {Number} [x1=0] - The x position of the first vertex on the line.
+ * @param {Number} [y1=0] - The y position of the first vertex on the line.
+ * @param {Number} [x2=0] - The x position of the second vertex on the line.
+ * @param {Number} [y2=0] - The y position of the second vertex on the line.
+ */
+function Line(x1, y1, x2, y2) {
+
+ Path.call(this, [
+ new Anchor(x1, y1),
+ new Anchor(x2, y2)
+ ]);
+
+ this.vertices[0].command = Commands.move;
+ this.vertices[1].command = Commands.line;
+
+ this.automatic = false;
+
+}
+
+_.extend(Line.prototype, Path.prototype, {
+
+ constructor: Line
+
+});
+
+Path.MakeObservable(Line.prototype);
+
+/**
+ * @name Two.RoundedRectangle
+ * @class
+ * @extends Two.Path
+ * @param {Number} [x=0] - The x position of the rounded rectangle.
+ * @param {Number} [y=0] - The y position of the rounded rectangle.
+ * @param {Number} [width=0] - The width value of the rounded rectangle.
+ * @param {Number} [height=0] - The width value of the rounded rectangle.
+ * @param {Number} [radius=0] - The radius value of the rounded rectangle.
+ * @param {Number} [resolution=12] - The number of vertices used to construct the rounded rectangle.
+ */
+function RoundedRectangle(ox, oy, width, height, radius) {
+ * @property {Number} - The width of the rounded rectangle.
+ */
+ if (typeof width === 'number') {
+ this.width = width;
+ }
+
+ /**
+ * @name Two.RoundedRectangle#height
+ * @property {Number} - The height of the rounded rectangle.
+ */
+ if (typeof height === 'number') {
+ this.height = height;
+ }
+
+ /**
+ * @name Two.RoundedRectangle#radius
+ * @property {Number} - The size of the radius of the rounded rectangle.
+ */
+ if (typeof radius === 'number') {
+ this.radius = radius;
+ }
+
+ this._update();
+ this.translation.set(ox, oy);
+
+}
+
+_.extend(RoundedRectangle, {
+
+ /**
+ * @name Two.RoundedRectangle.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.RoundedRectangle}.
+ */
+ Properties: ['width', 'height'],
+
+ /**
+ * @name Two.RoundedRectangle.FlagRadius
+ * @property {Function} - A convenience function to trigger the flag for radius changing.
+ */
+ FlagRadius: function() {
+ this._flagRadius = true;
+ },
+
+ /**
+ * @name Two.RoundedRectangle.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.RoundedRectangle} to any object. Handy if you'd like to extend the {@link Two.RoundedRectangle} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight || this._flagRadius) {
+
+ var width = this._width;
+ var height = this._height;
+
+ var rx, ry;
+
+ if (this._radius instanceof Vector) {
+ rx = this._radius.x;
+ ry = this._radius.y;
+ } else {
+ rx = this._radius;
+ ry = this._radius;
+ }
+
+ var v;
+ var w = width / 2;
+ var h = height / 2;
+
+ v = this.vertices[0];
+ v.x = - (w - rx);
+ v.y = - h;
+
+ // Upper Right Corner
+
+ v = this.vertices[1];
+ v.x = (w - rx);
+ v.y = - h;
+ v.controls.left.clear();
+ v.controls.right.x = rx;
+ v.controls.right.y = 0;
+
+ v = this.vertices[2];
+ v.x = w;
+ v.y = - (h - ry);
+ v.controls.right.clear();
+ v.controls.left.clear();
+
+ // Bottom Right Corner
+
+ v = this.vertices[3];
+ v.x = w;
+ v.y = (h - ry);
+ v.controls.left.clear();
+ v.controls.right.x = 0;
+ v.controls.right.y = ry;
+
+ v = this.vertices[4];
+ v.x = (w - rx);
+ v.y = h;
+ v.controls.right.clear();
+ v.controls.left.clear();
+
+ // Bottom Left Corner
+
+ v = this.vertices[5];
+ v.x = - (w - rx);
+ v.y = h;
+ v.controls.left.clear();
+ v.controls.right.x = - rx;
+ v.controls.right.y = 0;
+
+ v = this.vertices[6];
+ v.x = - w;
+ v.y = (h - ry);
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ // Upper Left Corner
+
+ v = this.vertices[7];
+ v.x = - w;
+ v.y = - (h - ry);
+ v.controls.left.clear();
+ v.controls.right.x = 0;
+ v.controls.right.y = - ry;
+
+ v = this.vertices[8];
+ v.x = - (w - rx);
+ v.y = - h;
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ v = this.vertices[9];
+ v.copy(this.vertices[8]);
+
+ }
+
+ Path.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.RoundedRectangle#flagReset
+ * @function
+ * @private
+ * @description Called internally to reset all flags. Ensures that only properties that change are updated before being sent to the renderer.
+ * @property {Number[]} - Array of numbers. Odd indices represent dash length. Even indices represent dash space.
+ * @description A list of numbers that represent the repeated dash length and dash space applied to the stroke of the text.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray} for more information on the SVG stroke-dasharray attribute.
+ */
+ this.dashes = [];
+
+ /**
+ * @name Two.Text#dashes#offset
+ * @property {Number} - A number in pixels to offset {@link Two.Text#dashes} display.
+ */
+ this.dashes.offset = 0;
+
+ if (!_.isObject(styles)) {
+ return this;
+ }
+
+ _.each(Text.Properties, function(property) {
+
+ if (property in styles) {
+ this[property] = styles[property];
+ }
+
+ }, this);
+
+}
+
+_.extend(Text, {
+
+ /**
+ * @name Two.Text.Ratio
+ * @property {Number} - Approximate aspect ratio of a typeface's character width to height.
+ */
+ Ratio: 0.6,
+
+ /**
+ * @name Two.Text.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Text}.
+ * @property {Boolean} - Determines whether the {@link Two.Text#clip} need updating.
+ */
+ _flagClip: false,
+
+ // Underlying Properties
+
+ /**
+ * @name Two.Text#value
+ * @property {String} - The characters to be rendered to the the screen. Referred to in the documentation sometimes as the `message`.
+ */
+ _value: '',
+
+ /**
+ * @name Two.Text#family
+ * @property {String} - The font family Two.js should attempt to regsiter for rendering. The default value is `'sans-serif'`. Comma separated font names can be supplied as a "stack", similar to the CSS implementation of `font-family`.
+ */
+ _family: 'sans-serif',
+
+ /**
+ * @name Two.Text#size
+ * @property {Number} - The font size in Two.js point space. Defaults to `13`.
+ */
+ _size: 13,
+
+ /**
+ * @name Two.Text#leading
+ * @property {Number} - The height between lines measured from base to base in Two.js point space. Defaults to `17`.
+ */
+ _leading: 17,
+
+ /**
+ * @name Two.Text#alignment
+ * @property {String} - Alignment of text in relation to {@link Two.Text#translation}'s coordinates. Possible values include `'left'`, `'center'`, `'right'`. Defaults to `'center'`.
+ */
+ _alignment: 'center',
+
+ /**
+ * @name Two.Text#baseline
+ * @property {String} - The vertical aligment of the text in relation to {@link Two.Text#translation}'s coordinates. Possible values include `'top'`, `'middle'`, `'bottom'`, and `'baseline'`. Defaults to `'baseline'`.
+ */
+ _baseline: 'middle',
+
+ /**
+ * @name Two.Text#style
+ * @property {String} - The font's style. Possible values include '`normal`', `'italic'`. Defaults to `'normal'`.
+ */
+ _style: 'normal',
+
+ /**
+ * @name Two.Text#weight
+ * @property {Number} - A number at intervals of 100 to describe the font's weight. This compatibility varies with the typeface's variant weights. Larger values are bolder. Smaller values are thinner. Defaults to `'500'`.
+ */
+ _weight: 500,
+
+ /**
+ * @name Two.Text#decoration
+ * @property {String} - String to delineate whether text should be decorated with for instance an `'underline'`. Defaults to `'none'`.
+ */
+ _decoration: 'none',
+
+ /**
+ * @name Two.Text#fill
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the text object should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _fill: '#000',
+
+ /**
+ * @name Two.Text#stroke
+ * @property {(String|Two.Gradient|Two.Texture)} - The value of what the text object should be filled in with.
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value} for more information on CSS's colors as `String`.
+ */
+ _stroke: 'transparent',
+
+ /**
+ * @name Two.Text#linewidth
+ * @property {Number} - The thickness in pixels of the stroke.
+ */
+ _linewidth: 1,
+
+ /**
+ * @name Two.Text#opacity
+ * @property {Number} - The opaqueness of the text object.
+ * @nota-bene Can be used in conjunction with CSS Colors that have an alpha value.
+ */
+ _opacity: 1,
+
+ /**
+ * @name Two.Text#className
+ * @property {String} - A class to be applied to the element to be compatible with CSS styling. Only available for the {@link Two.SvgRenderer}.
+ */
+ _className: '',
+
+ /**
+ * @name Two.Text#visible
+ * @property {Boolean} - Display the text object or not.
+ * @nota-bene For {@link Two.CanvasRenderer} and {@link Two.WebGLRenderer} when set to false all updating is disabled improving performance dramatically with many objects in the scene.
+ */
+ _visible: true,
+
+ /**
+ * @name Two.Text#mask
+ * @property {Two.Shape} - The shape whose alpha property becomes a clipping area for the text.
+ * @nota-bene This property is currently not working becuase of SVG spec issues found here {@link https://code.google.com/p/chromium/issues/detail?id=370951}.
+ */
+ _mask: null,
+
+ /**
+ * @name Two.Text#clip
+ * @property {Two.Shape} - Object to define clipping area.
+ * @nota-bene This property is currently not working becuase of SVG spec issues found here {@link https://code.google.com/p/chromium/issues/detail?id=370951}.
+ */
+ _clip: false,
+
+ /**
+ * @name Two.Text#_dashes
+ * @private
+ * @see {@link Two.Text#dashes}
+ */
+ _dashes: [],
+
+ /**
+ * @name Two.Text#remove
+ * @function
+ * @description Remove self from the scene / parent.
+ */
+ remove: function() {
+
+ if (!this.parent) {
+ return this;
+ }
+
+ this.parent.remove(this);
+
+ return this;
+
+ },
+
+ /**
+ * @name Two.Text#clone
+ * @function
+ * @param {Two.Group} [parent] - The parent group or scene to add the clone to.
+ * @returns {Two.Text}
+ * @description Create a new instance of {@link Two.Text} with the same properties of the current text object.
+ */
+ clone: function(parent) {
+
+ var clone = new Text(this.value);
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+
+ _.each(Text.Properties, function(property) {
+ clone[property] = this[property];
+ }, this);
+
+ if (this.matrix.manual) {
+ clone.matrix.copy(this.matrix);
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone._update();
+
+ },
+
+ /**
+ * @name Two.Text#toObject
+ * @function
+ * @returns {Object}
+ * @description Return a JSON compatible plain object that represents the text object.
+ */
+ toObject: function() {
+
+ var result = {
+ translation: this.translation.toObject(),
+ rotation: this.rotation,
+ scale: this.scale
+ };
+
+ if (this.matrix.manual) {
+ result.matrix = this.matrix.toObject();
+ }
+
+ _.each(Text.Properties, function(property) {
+ result[property] = this[property];
+ }, this);
+
+ return result;
+
+ },
+
+ /**
+ * @name Two.Text#noFill
+ * @function
+ * @description Short hand method to set fill to `transparent`.
+ */
+ noFill: function() {
+ this.fill = 'transparent';
+ return this;
+ },
+
+ /**
+ * @name Two.Text#noStroke
+ * @function
+ * @description Short hand method to set stroke to `transparent`.
+ */
+ noStroke: function() {
+ this.stroke = undefined;
+ this.linewidth = undefined;
+ return this;
+ },
+
+ // A shim to not break `getBoundingClientRect` calls.
+ // TODO: Implement a way to calculate proper bounding
+ // boxes of `Two.Text`.
+
+ /**
+ * @name Two.Text#getBoundingClientRect
+ * @function
+ * @param {Boolean} [shallow=false] - Describes whether to calculate off local matrix or world matrix.
+ var keywords = ['id', 'class', 'transform', 'xmlns', 'viewBox'];
+
+ for (var i = 0; i < keywords.length; i++) {
+ var keyword = keywords[i];
+ var index = Array.prototype.indexOf.call(attributes, keyword);
+ if (index >= 0) {
+ attributes.splice(index, 1);
+ }
+ }
+
+ return attributes;
+
+};
+
+/**
+ * @name Two.Utils.applySvgViewBox
+ * @function
+ * @param {Two.Shape} node - The Two.js object to apply viewbox matrix to
+ * @param {String} value - The viewBox value from the SVG attribute
+ * @returns {Two.Shape} node
+ * @description Applies the transform of the SVG Viewbox on a given node.
+ */
+var applySvgViewBox = function(node, value) {
+
+ var elements = value.split(/\s/);
+
+ var x = parseFloat(elements[0]);
+ var y = parseFloat(elements[1]);
+ var width = parseFloat(elements[2]);
+ var height = parseFloat(elements[3]);
+
+ var s = Math.min(this.width / width, this.height / height);
+
+ node.translation.x -= x * s;
+ node.translation.y -= y * s;
+ node.scale = s;
+
+ return node;
+
+};
+
+/**
+ * @name Two.Utils.applySvgAttributes
+ * @function
+ * @param {SVGElement} node - An SVG Node to extrapolate attributes from.
+ * @param {Two.Shape} elem - The Two.js object to apply extrapolated attributes to.
+ * @returns {Two.Shape} The Two.js object passed now with applied attributes.
+ * @description This function iterates through an SVG Node's properties and stores ones of interest. It tries to resolve styles applied via CSS as well.
+ * @TODO Reverse calculate {@link Two.Gradient}s for fill / stroke of any given path.
+ for (var i = 0, l = node.childNodes.length; i < l; i++) {
+ var n = node.childNodes[i];
+ if (!n.id) continue;
+
+ var tagName = getTagName(node.nodeName);
+ if (tagName === '#text') continue;
+
+ defsCache.add(n.id, n);
+ }
+};
+
+/**
+ * @name Two.Utils.getScene
+ * @param {Two.Shape} node - The currently available object in the scenegraph.
+ * @returns {Group} - The highest order {@link Two.Group} in the scenegraph.
+ * @property {Function}
+ */
+var getScene = function(node) {
+
+ while (node.parent) {
+ node = node.parent;
+ }
+
+ return node.scene;
+
+};
+
+/**
+ * @name Two.Utils.read
+ * @property {Object} read - A map of functions to read any number of SVG node types and create Two.js equivalents of them. Primarily used by the {@link Two#interpret} method.
+ */
+var read = {
+
+ svg: function(node) {
+
+ var defs = read.defs.current = new Registry();
+ var elements = node.getElementsByTagName('defs');
+
+ for (var i = 0; i < elements.length; i++) {
+ updateDefsCache(elements[i], defs);
+ }
+
+ var svg = read.g.call(this, node);
+ // var viewBox = node.getAttribute('viewBox');
+
+ svg.defs = defs; // Export out the <defs /> for later use
+ // Utils.applySvgViewBox(svg, viewBox);
+
+ delete read.defs.current;
+
+ return svg;
+
+ },
+
+ defs: function(node) {
+ return null;
+ },
+
+ use: function(node, styles) {
+
+ var error;
+ var href = node.getAttribute('href') || node.getAttribute('xlink:href');
+ if (!href) {
+ error = new TwoError('encountered <use /> with no href.');
+ console.warn(error.name, error.message);
+ return null;
+ }
+
+ var id = href.slice(1);
+ if (!read.defs.current.contains(id)) {
+ error = new TwoError(
+ 'unable to find element for reference ' + href + '.');
+ console.warn(error.name, error.message);
+ return null;
+ }
+
+ var template = read.defs.current.get(id);
+ var fullNode = template.cloneNode(true);
+ var overwriteAttrs = ['x', 'y', 'width', 'height', 'href', 'xlink:href'];
+
+ for (var i = 0; i < node.attributes.length; i++) {
+ var attr = node.attributes[i];
+ var ca = overwriteAttrs.includes(attr.nodeName);
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.ImageSequence} to any object. Handy if you'd like to extend or inherit the {@link Two.ImageSequence} class on a custom class.
+ * @property {Number} - Number of frames for a given {@link Two.ImageSequence}.
+ */
+ _amount: 1,
+
+ /**
+ * @name Two.ImageSequence#_duration
+ * @private
+ * @property {Number} - Number of milliseconds a {@link Two.ImageSequence}.
+ */
+ _duration: 0,
+
+ /**
+ * @name Two.ImageSequence#_index
+ * @private
+ * @property {Number} - The current frame the {@link Two.ImageSequence} is currently displaying.
+ */
+ _index: 0,
+
+ /**
+ * @name Two.ImageSequence#_startTime
+ * @private
+ * @property {Milliseconds} - Epoch time in milliseconds of when the {@link Two.ImageSequence} started.
+ */
+ _startTime: 0,
+
+ /**
+ * @name Two.ImageSequence#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.ImageSequence} is animating or not.
+ */
+ _playing: false,
+
+ /**
+ * @name Two.ImageSequence#_firstFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.ImageSequence} should start with.
+ */
+ _firstFrame: 0,
+
+ /**
+ * @name Two.ImageSequence#_lastFrame
+ * @private
+ * @property {Number} - The frame the {@link Two.ImageSequence} should end with.
+ */
+ _lastFrame: 0,
+
+ /**
+ * @name Two.ImageSequence#_playing
+ * @private
+ * @property {Boolean} - Dictates whether the {@link Two.ImageSequence} should loop or not.
+ */
+ _loop: true,
+
+ // Exposed through getter-setter
+
+ /**
+ * @name Two.ImageSequence#_textures
+ * @private
+ * @see {@link Two.ImageSequence#textures}
+ */
+ _textures: null,
+
+ /**
+ * @name Two.ImageSequence#_frameRate
+ * @private
+ * @see {@link Two.ImageSequence#frameRate}
+ */
+ _frameRate: 0,
+
+ /**
+ * @name Two.ImageSequence#_origin
+ * @private
+ * @see {@link Two.ImageSequence#origin}
+ */
+ _origin: null,
+
+ /**
+ * @name Two.ImageSequence#play
+ * @function
+ * @param {Number} [firstFrame=0] - The index of the frame to start the animation with.
+ * @param {Number} [lastFrame] - The index of the frame to end the animation with. Defaults to the last item in the {@link Two.ImageSequence#textures}.
+ * @param {Function} [onLastFrame] - Optional callback function to be triggered after playing the last frame. This fires multiple times when the image sequence is looped.
+ * @description Initiate animation playback of a {@link Two.ImageSequence}.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ var effects = this._textures;
+ var width, height, elapsed, amount, duration, texture;
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.ArcSegment} to any object. Handy if you'd like to extend the {@link Two.ArcSegment} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagStartAngle || this._flagEndAngle
+ * @param {Number} [x=0] - The x position of the polygon.
+ * @param {Number} [y=0] - The y position of the polygon.
+ * @param {Number} [radius=0] - The radius value of the polygon.
+ * @param {Number} [sides=12] - The number of vertices used to construct the polygon.
+ */
+function Polygon(ox, oy, r, sides) {
+
+ sides = Math.max(sides || 0, 3);
+
+ Path.call(this);
+
+ this.closed = true;
+ this.automatic = false;
+
+ /**
+ * @name Two.Polygon#width
+ * @property {Number} - The size of the width of the polygon.
+ */
+ if (typeof r === 'number') {
+ this.width = r * 2;
+ }
+
+ /**
+ * @name Two.Polygon#height
+ * @property {Number} - The size of the height of the polygon.
+ */
+ if (typeof r === 'number') {
+ this.height = r * 2;
+ }
+
+ /**
+ * @name Two.Polygon#sides
+ * @property {Number} - The amount of sides the polyogn has.
+ */
+ if (typeof sides === 'number') {
+ this.sides = sides;
+ }
+
+ this._update();
+
+ if (typeof ox === 'number') {
+ this.translation.x = ox;
+ }
+ if (typeof oy === 'number') {
+ this.translation.y = oy;
+ }
+
+}
+
+_.extend(Polygon, {
+
+ /**
+ * @name Two.Polygon.Properties
+ * @property {String[]} - A list of properties that are on every {@link Two.Polygon}.
+ */
+ Properties: ['width', 'height', 'sides'],
+
+ /**
+ * @name Two.Polygon.MakeObservable
+ * @function
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Polygon} to any object. Handy if you'd like to extend the {@link Two.Polygon} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagWidth || this._flagHeight || this._flagSides) {
+ * @param {Object} object - The object to make observable.
+ * @description Convenience function to apply observable qualities of a {@link Two.Star} to any object. Handy if you'd like to extend the {@link Two.Star} class on a custom class.
+ * @param {Boolean} [bubbles=false] - Force the parent to `_update` as well.
+ * @description This is called before rendering happens by the renderer. This applies all changes necessary so that rendering is up-to-date but not updated more than it needs to be.
+ * @nota-bene Try not to call this method more than once a frame.
+ */
+ _update: function() {
+
+ if (this._flagVertices || this._flagInnerRadius || this._flagOuterRadius || this._flagSides) {
+ * @param {Object} [parameters] - This object is inherited when constructing a new instance of {@link Two}.
+ * @param {Element} [parameters.domElement] - The `<svg />` to draw to. If none given a new one will be constructed.
+ * @description This class is used by {@link Two} when constructing with `type` of `Two.Types.svg` (the default type). It takes Two.js' scenegraph and renders it to a `<svg />`.
+ */
+function Renderer$1(params) {
+
+ /**
+ * @name Two.SVGRenderer#domElement
+ * @property {Element} - The `<svg />` associated with the Two.js scene.
+ * @param {Object} [parameters] - This object is inherited when constructing a new instance of {@link Two}.
+ * @param {Element} [parameters.domElement] - The `<canvas />` to draw to. If none given a new one will be constructed.
+ * @param {HTMLCanvasElement} [parameters.offscreenElement] - The offscreen two dimensional `<canvas />` to render each element on WebGL texture updates.
+ * @param {Boolean} [parameters.antialias] - Determines whether the canvas should clear render with antialias on.
+ * @description This class is used by {@link Two} when constructing with `type` of `Two.Types.webgl`. It takes Two.js' scenegraph and renders it to a `<canvas />` through the WebGL api.
+ * @property {Object} - A massive object filled with utility functions and properties to render Two.js objects to a `<canvas />` through the WebGL API.
+ */
+ Utils: webgl
+
+});
+
+_.extend(Renderer.prototype, Events, {
+
+ constructor: Renderer,
+
+ /**
+ * @name Two.WebGLRenderer#setSize
+ * @function
+ * @fires resize
+ * @param {Number} width - The new width of the renderer.
+ * @param {Number} height - The new height of the renderer.
+ * @param {Number} [ratio] - The new pixel ratio (pixel density) of the renderer. Defaults to calculate the pixel density of the user's screen.
+ * @param {Boolean} [options.fullscreen=false] - Set to `true` to automatically make the stage adapt to the width and height of the parent document. This parameter overrides `width` and `height` parameters if set to `true`. This overrides `options.fitted` as well.
+ * @param {Boolean} [options.fitted=false] = Set to `true` to automatically make the stage adapt to the width and height of the parent element. This parameter overrides `width` and `height` parameters if set to `true`.
+ * @param {Number} [options.width=640] - The width of the stage on construction. This can be set at a later time.
+ * @param {Number} [options.height=480] - The height of the stage on construction. This can be set at a later time.
+ * @param {String} [options.type=Two.Types.svg] - The type of renderer to setup drawing with. See {@link Two.Types} for available options.
+ * @param {Boolean} [options.autostart=false] - Set to `true` to add the instance to draw on `requestAnimationFrame`. This is a convenient substitute for {@link Two#play}.
+ * @param {Element} [options.domElement] - The canvas or SVG element to draw into. This overrides the `options.type` argument.
+ * @description The entrypoint for Two.js. Instantiate a `new Two` in order to setup a scene to render to. `Two` is also the publicly accessible namespace that all other sub-classes, functions, and utilities attach to.
+ */
+function Two(options) {
+
+ // Determine what Renderer to use and setup a scene.
+
+ var params = _.defaults(options || {}, {
+ fullscreen: false,
+ fitted: false,
+ width: 640,
+ height: 480,
+ type: Two.Types.svg,
+ autostart: false
+ });
+
+ _.each(params, function(v, k) {
+ if (/fullscreen/i.test(k) || /autostart/i.test(k)) {
+ return;
+ }
+ this[k] = v;
+ }, this);
+
+ // Specified domElement overrides type declaration only if the element does not support declared renderer type.
+ if (_.isElement(params.domElement)) {
+ var tagName = params.domElement.tagName.toLowerCase();
+ // TODO: Reconsider this if statement's logic.
+ if (!/^(CanvasRenderer-canvas|WebGLRenderer-canvas|SVGRenderer-svg)$/.test(this.type+'-'+tagName)) {
+ this.type = Two.Types[tagName];
+ }
+ }
+
+ this.renderer = new Two[this.type](this);
+ this.setPlaying(params.autostart);
+ this.frameCount = 0;
+
+ /**
+ * @name Two#fit
+ * @function
+ * @description If `options.fullscreen` or `options.fitted` in construction create this function. It sets the `width` and `height` of the instance to its respective parent `window` or `element` depending on the `options` passed.
+ * @property {String} - A string representing which type of renderer the instance has instantiated.
+ */
+ type: '',
+
+ /**
+ * @name Two#renderer
+ * @property {(Two.SVGRenderer|Two.CanvasRenderer|Two.WebGLRenderer)} - The instantiated rendering class for the instance. For a list of possible rendering types check out Two.Types.
+ */
+ renderer: null,
+
+ /**
+ * @name Two#scene
+ * @property {Two.Group} - The base level {@link Two.Group} which houses all objects for the instance. Because it is a {@link Two.Group} transformations can be applied to it that will affect all objects in the instance. This is handy as a makeshift inverted camera.
+ */
+ scene: null,
+
+ /**
+ * @name Two#width
+ * @property {Number} - The width of the instance's dom element.
+ */
+ width: 0,
+
+ /**
+ * @name Two#height
+ * @property {Number} - The height of the instance's dom element.
+ */
+ height: 0,
+
+ /**
+ * @name Two#frameCount
+ * @property {Number} - An integer representing how many frames have elapsed.
+ */
+ frameCount: 0,
+
+ /**
+ * @name Two#timeDelta
+ * @property {Number} - A number representing how much time has elapsed since the last frame in milliseconds.
+ */
+ timeDelta: 0,
+
+ /**
+ * @name Two#playing
+ * @property {Boolean} - A boolean representing whether or not the instance is being updated through the automatic `requestAnimationFrame`.
+ */
+ playing: false,
+
+ /**
+ * @name Two#appendTo
+ * @function
+ * @param {Element} elem - The DOM element to append the Two.js stage to.
+ * @description Shorthand method to append your instance of Two.js to the `document`.
+ */
+ appendTo: function(elem) {
+
+ elem.appendChild(this.renderer.domElement);
+
+ if (this.fit) {
+ if (this.fit.domElement !== window) {
+ this.fit.domElement = elem;
+ this.fit.attached = false;
+ }
+ this.update();
+ }
+
+ return this;
+
+ },
+
+ /**
+ * @name Two#play
+ * @function
+ * @fires Two.Events.Types.play event
+ * @description Call to start an internal animation loop.
+ * @nota-bene This function initiates a `requestAnimationFrame` loop.
+ */
+ play: function() {
+
+ this.playing = true;
+ raf.init();
+ return this.trigger(Events.Types.play);
+
+ },
+
+ /**
+ * @name Two#pause
+ * @function
+ * @fires Two.Events.Types.pause event
+ * @description Call to stop the internal animation loop for a specific instance of Two.js.
+ */
+ pause: function() {
+
+ this.playing = false;
+ return this.trigger(Events.Types.pause);
+
+ },
+
+ setPlaying: function(p) {
+ this.playing = p;
+ },
+
+ /**
+ * @name Two#release
+ * @function
+ * @param {Object} obj
+ * @returns {Object} The object passed for event deallocation.
+ * @description Release an arbitrary class' events from the Two.js corpus and recurse through its children and or vertices.
+ */
+ release: function(obj) {
+
+ var i, v, child;
+
+ if (!_.isObject(obj)) {
+ return;
+ }
+
+ if (typeof obj.unbind === 'function') {
+ obj.unbind();
+ }
+
+ if (obj.vertices) {
+ if (typeof obj.vertices.unbind === 'function') {
+ obj.vertices.unbind();
+ }
+ for (i = 0; i < obj.vertices.length; i++) {
+ v = obj.vertices[i];
+ if (typeof v.unbind === 'function') {
+ v.unbind();
+ }
+ }
+ }
+
+ if (obj.children) {
+ for (i = 0; i < obj.children.length; i++) {
+ child = obj.children[i];
+ this.release(child);
+ }
+ }
+
+ return obj;
+
+ },
+
+ /**
+ * @name Two#update
+ * @function
+ * @fires Two.Events.Types.update event
+ * @description Update positions and calculations in one pass before rendering. Then render to the canvas.
+ * @nota-bene This function is called automatically if using {@link Two#play} or the `autostart` parameter in construction.
+ * @description Removes all objects from the instance's scene. If you intend to have the browser garbage collect this, don't forget to delete the references in your application as well.
+ */
+ clear: function() {
+
+ this.scene.remove(this.scene.children);
+ return this;
+
+ },
+
+ /**
+ * @name Two#makeLine
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} x2
+ * @param {Number} y2
+ * @returns {Two.Line}
+ * @description Creates a Two.js line and adds it to the scene.
+ */
+ makeLine: function(x1, y1, x2, y2) {
+
+ var line = new Line(x1, y1, x2, y2);
+ this.scene.add(line);
+
+ return line;
+
+ },
+
+ /**
+ * @name Two#makeArrow
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} x2
+ * @param {Number} y2
+ * @returns {Two.Path}
+ * @description Creates a Two.js arrow and adds it to the scene.
+ var path = new Path(vertices, false, false, true);
+ path.noFill();
+ path.cap = 'round';
+ path.join = 'round';
+
+ this.scene.add(path);
+
+ return path;
+ },
+
+ /**
+ * @name Two#makeRectangle
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} width
+ * @param {Number} height
+ * @returns {Two.Rectangle}
+ * @description Creates a Two.js rectangle and adds it to the scene.
+ */
+ makeRectangle: function(x, y, width, height) {
+
+ var rect = new Rectangle(x, y, width, height);
+ this.scene.add(rect);
+
+ return rect;
+
+ },
+
+ /**
+ * @name Two#makeRoundedRectangle
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} width
+ * @param {Number} height
+ * @param {Number} sides
+ * @returns {Two.Rectangle}
+ * @description Creates a Two.js rounded rectangle and adds it to the scene.
+ */
+ makeRoundedRectangle: function(x, y, width, height, sides) {
+
+ var rect = new RoundedRectangle(x, y, width, height, sides);
+ this.scene.add(rect);
+
+ return rect;
+
+ },
+
+ /**
+ * @name Two#makeCircle
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} radius
+ * @param {Number} [resolution=4]
+ * @returns {Two.Circle}
+ * @description Creates a Two.js circle and adds it to the scene.
+ */
+ makeCircle: function(x, y, radius, resolution) {
+
+ var circle = new Circle(x, y, radius, resolution);
+ this.scene.add(circle);
+
+ return circle;
+
+ },
+
+ /**
+ * @name Two#makeEllipse
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} rx
+ * @param {Number} ry
+ * @param {Number} [resolution=4]
+ * @returns {Two.Ellipse}
+ * @description Creates a Two.js ellipse and adds it to the scene.
+ */
+ makeEllipse: function(x, y, rx, ry, resolution) {
+
+ var ellipse = new Ellipse(x, y, rx, ry, resolution);
+ this.scene.add(ellipse);
+
+ return ellipse;
+
+ },
+
+ /**
+ * @name Two#makeStar
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} outerRadius
+ * @param {Number} innerRadius
+ * @param {Number} sides
+ * @returns {Two.Star}
+ * @description Creates a Two.js star and adds it to the scene.
+ */
+ makeStar: function(ox, oy, outerRadius, innerRadius, sides) {
+
+ var star = new Star(ox, oy, outerRadius, innerRadius, sides);
+ this.scene.add(star);
+
+ return star;
+
+ },
+
+ /**
+ * @name Two#makeCurve
+ * @function
+ * @param {Two.Anchor[]} [points] - An array of {@link Two.Anchor} points.
+ * @param {...Number} - Alternatively you can pass alternating `x` / `y` coordinate values as individual arguments. These will be combined into {@link Two.Anchor}s for use in the path.
+ * @returns {Two.Path} - Where `path.curved` is set to `true`.
+ * @description Creates a Two.js path that is curved and adds it to the scene.
+ * @nota-bene In either case of passing an array or passing numbered arguments the last argument is an optional `Boolean` that defines whether the path should be open or closed.
+ */
+ makeCurve: function(p) {
+
+ var l = arguments.length, points = p;
+ if (!Array.isArray(p)) {
+ points = [];
+ for (var i = 0; i < l; i+=2) {
+ var x = arguments[i];
+ if (typeof x !== 'number') {
+ break;
+ }
+ var y = arguments[i + 1];
+ points.push(new Anchor(x, y));
+ }
+ }
+
+ var last = arguments[l - 1];
+ var curve = new Path(points, !(typeof last === 'boolean' ? last : undefined), true);
+ * @description Creates a Two.js polygon and adds it to the scene.
+ */
+ makePolygon: function(x, y, radius, sides) {
+
+ var poly = new Polygon(x, y, radius, sides);
+ this.scene.add(poly);
+
+ return poly;
+
+ },
+
+ /**
+ * @name Two#makeArcSegment
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} innerRadius
+ * @param {Number} outerRadius
+ * @param {Number} startAngle
+ * @param {Number} endAngle
+ * @param {Number} [resolution=Two.Resolution] - The number of vertices that should comprise the arc segment.
+ */
+ makeArcSegment: function(ox, oy, ir, or, sa, ea, res) {
+ var arcSegment = new ArcSegment(ox, oy, ir, or, sa, ea, res);
+ this.scene.add(arcSegment);
+ return arcSegment;
+ },
+
+ /**
+ * @name Two#makePath
+ * @function
+ * @param {Two.Anchor[]} [points] - An array of {@link Two.Anchor} points.
+ * @param {...Number} - Alternatively you can pass alternating `x` / `y` coordinate values as individual arguments. These will be combined into {@link Two.Anchor}s for use in the path.
+ * @returns {Two.Path}
+ * @description Creates a Two.js path and adds it to the scene.
+ * @nota-bene In either case of passing an array or passing numbered arguments the last argument is an optional `Boolean` that defines whether the path should be open or closed.
+ */
+ makePath: function(p) {
+
+ var l = arguments.length, points = p;
+ if (!Array.isArray(p)) {
+ points = [];
+ for (var i = 0; i < l; i+=2) {
+ var x = arguments[i];
+ if (typeof x !== 'number') {
+ break;
+ }
+ var y = arguments[i + 1];
+ points.push(new Anchor(x, y));
+ }
+ }
+
+ var last = arguments[l - 1];
+ var path = new Path(points, !(typeof last === 'boolean' ? last : undefined));
+ * @param {Object} [styles] - An object to describe any of the {@link Two.Text.Properties} including `fill`, `stroke`, `linewidth`, `family`, `alignment`, `leading`, `opacity`, etc..
+ * @returns {Two.Text}
+ * @description Creates a Two.js text object and adds it to the scene.
+ */
+ makeText: function(message, x, y, styles) {
+ var text = new Text(message, x, y, styles);
+ this.add(text);
+ return text;
+ },
+
+ /**
+ * @name Two#makeLinearGradient
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} x2
+ * @param {Number} y2
+ * @param {...Two.Stop} stops - Any number of color stops sometimes reffered to as ramp stops. If none are supplied then the default black-to-white two stop gradient is applied.
+ * @returns {Two.LinearGradient}
+ * @description Creates a Two.js linear gradient and ads it to the scene. In the case of an effect it's added to an invisible "definitions" group.
+ var stops = Array.prototype.slice.call(arguments, 4);
+ var gradient = new LinearGradient(x1, y1, x2, y2, stops);
+
+ this.add(gradient);
+
+ return gradient;
+
+ },
+
+ /**
+ * @name Two#makeRadialGradient
+ * @function
+ * @param {Number} x1
+ * @param {Number} y1
+ * @param {Number} radius
+ * @param {...Two.Stop} stops - Any number of color stops sometimes reffered to as ramp stops. If none are supplied then the default black-to-white two stop gradient is applied.
+ * @returns {Two.RadialGradient}
+ * @description Creates a Two.js linear-gradient object and ads it to the scene. In the case of an effect it's added to an invisible "definitions" group.
+ */
+ makeRadialGradient: function(x1, y1, r /* stops */) {
+
+ var stops = Array.prototype.slice.call(arguments, 3);
+ var gradient = new RadialGradient(x1, y1, r, stops);
+
+ this.add(gradient);
+
+ return gradient;
+
+ },
+
+ /**
+ * @name Two#makeSprite
+ * @function
+ * @param {(String|Two.Texture)} pathOrTexture - The URL path to an image or an already created {@link Two.Texture}.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} [columns=1]
+ * @param {Number} [rows=1]
+ * @param {Number} [frameRate=0]
+ * @param {Boolean} [autostart=false]
+ * @returns {Two.Sprite}
+ * @description Creates a Two.js sprite object and adds it to the scene. Sprites can be used for still images as well as animations.
+ */
+ makeSprite: function(path, x, y, cols, rows, frameRate, autostart) {
+
+ var sprite = new Sprite(path, x, y, cols, rows, frameRate);
+ if (autostart) {
+ sprite.play();
+ }
+ this.add(sprite);
+
+ return sprite;
+
+ },
+
+ /**
+ * @name Two#makeImageSequence
+ * @function
+ * @param {(String[]|Two.Texture[])} pathsOrTextures - An array of paths or of {@link Two.Textures}.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} [frameRate=0]
+ * @param {Boolean} [autostart=false]
+ * @returns {Two.ImageSequence}
+ * @description Creates a Two.js image sequence object and adds it to the scene.
+ */
+ makeImageSequence: function(paths, x, y, frameRate, autostart) {
+
+ var imageSequence = new ImageSequence(paths, x, y, frameRate);
+ if (autostart) {
+ imageSequence.play();
+ }
+ this.add(imageSequence);
+
+ return imageSequence;
+
+ },
+
+ /**
+ * @name Two#makeTexture
+ * @function
+ * @param {(String|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement)} [pathOrSource] - The URL path to an image or a DOM image-like element.
+ * @param {Function} [callback] - Function to be invoked when the image is loaded.
+ * @returns {Two.Texture}
+ * @description Creates a Two.js texture object.
+ */
+ makeTexture: function(path, callback) {
+
+ var texture = new Texture(path, callback);
+ return texture;
+
+ },
+
+ /**
+ * @name Two#makeGroup
+ * @function
+ * @param {(Two.Shape[]|...Two.Shape)} [objects] - Two.js objects to be added to the group in the form of an array or as individual arguments.
+ * @returns {Two.Group}
+ * @description Creates a Two.js group object and adds it to the scene.
+ * @param {SVGElement} SVGElement - The SVG node to be parsed.
+ * @param {Boolean} shallow - Don't create a top-most group but append all content directly.
+ * @param {Boolean} add – Automatically add the reconstructed SVG node to scene.
+ * @returns {Two.Group}
+ * @description Interpret an SVG Node and add it to this instance's scene. The distinction should be made that this doesn't `import` svg's, it solely interprets them into something compatible for Two.js - this is slightly different than a direct transcription.
+I always wondered, if you can get a working solution for css-in-js with a smaller footprint. So, while I was working on a side-project I wanted a to use styled-components or more accurate the `styled` pattern. Looking at the JavaScript bundled sizes, I quickly realized that I would have to include ~12kB([styled-components](https://github.com/styled-components/styled-components)) or ~11kB([emotion](https://github.com/emotion-js/emotion)) just so I can use the `styled` paradigm. So, I embarked in a mission to create a smaller alternative for these well established apis.
+The API is inspired by emotion, `styled` function. Meaning, you call it with your `tagName` and returns a vDOM component for that tag. Note, `setup` is needed to be run before the `styled` function is used.
+
+```jsx
+import { h } from 'preact';
+import { styled, setup } from 'goober';
+
+// Should be called here, and just once
+setup(h);
+
+const Icon = styled('span')`
+ display: flex;
+ flex: 1;
+ color: red;
+`;
+
+const Button = styled('button')`
+ background: dodgerblue;
+ color: white;
+ border: ${Math.random()}px solid white;
+
+ &:focus,
+ &:hover {
+ padding: 1em;
+ }
+
+ .otherClass {
+ margin: 0;
+ }
+
+ ${Icon} {
+ color: black;
+ }
+`;
+```
+
+# Examples
+
+- [Vanilla](https://codesandbox.io/s/qlywyp7z4q)
+- [React](https://codesandbox.io/s/k0mnp40n7v)
+- [Preact](https://codesandbox.io/s/r15wj2qm7o)
+- [SSR with Preact](https://codesandbox.io/s/7m9zzl6746)
+You can get the critical CSS for SSR, via `extractCss`. Take a look at this example: [CodeSandbox: SSR with Preact and goober](https://codesandbox.io/s/7m9zzl6746) and read the full explanation for `extractCSS` and `targets` below.
+
+# Benchmarks
+
+The results are included inside the build output as well.
+
+## Browser
+
+Comming soon!
+
+## SSR
+
+The benchmark is testing the following scenario:
+
+```jsx
+import styled from 'package';
+
+// Create the dynamic styled component
+const Foo = styled('div')((props) => ({
+ opacity: props.counter > 0.5 ? 1 : 0,
+ '@media (min-width: 1px)': {
+ rule: 'all'
+ },
+ '&:hover': {
+ another: 1,
+ display: 'space'
+ }
+}));
+
+// Serialize the component
+renderToString(<Foo counter={Math.random()} />);
+```
+
+The results are:
+
+```
+goober x 200,437 ops/sec ±1.93% (87 runs sampled)
+styled-components@5.2.1 x 12,650 ops/sec ±9.09% (48 runs sampled)
+emotion@11.0.0 x 104,229 ops/sec ±2.06% (88 runs sampled)
+
+Fastest is: goober
+```
+
+# API
+
+As you can see it supports most of the syntaxes of CSS. If you find any issues, please submit a ticket or even a PR with a fix.
+Given the fact that `react` uses `createElement` for the transformed elements and `preact` uses `h`, `setup` should be called with the proper _pragma_ function. This was added to reduce the bundled size and being able to bundle esmodule version. At the moment I think it's the best tradeoff we can have.
+import React, { createContext, useContext, createElement } from 'react';
+import { setup, styled } from 'goober';
+
+const theme = { primary: 'blue' };
+const ThemeContext = createContext(theme);
+const useTheme = () => useContext(ThemeContext);
+
+setup(createElement, undefined, useTheme);
+
+const ContainerWithTheme = styled('div')`
+ color: ${(props) => props.theme.primary};
+`;
+```
+
+#### With forwardProps
+
+The `forwardProps` function, offers a way to achieve the same `shouldForwardProps` functionality as emotion and styled-components(with transient props) offer. The difference in here is that the function receives the whole props and you are in charge of removing the props that are should not end-up in the dom.
+
+This is a super useful functionality when paired with theme object, variants or any other customisation one might need.
+The difference between calling `css` directly and wrapping into a function is the timing of its execution. The former is when the component(file) is imported, the latter is when it is actually rendered.
+
+If you use `extractCSS` for SSR, you may prefer to use the latter or `styled` api to avoid inconsistent results.
+
+### `targets`
+
+By default, goober will append a style tag to the `<head>` of a document. You might want to target a different node, for instance, when you want to use goober with web components (so you'd want it to append style tags to individual shadowRoots). For this purpose, you can `.bind` a new target to the `styled` and `css` methods:
+If you don't provide a target, goober always defaults to `<head>` and in environments without a DOM (think certain SSR solutions), it will just use a plain string cache to store generated styles which you can extract with `extractCSS`(see below).
+
+### `extractCss(target?)`
+
+- `@returns {String}`
+
+Returns the `<style>` tag that is rendered in a target and clears the style sheet. Defaults to `<head>`.
+// Note: To be able to `hydrate` the styles you should use the proper `id` so `goober` can pick it up and use it as the target from now on
+```
+
+### `createGlobalStyles`
+
+To define your global styles you need to create a `GlobalStyles` component and use it as part of your tree. The `createGlobalStyles` is available at `goober/global` addon.
+
+```js
+import { createGlobalStyles } from 'goober/global';
+
+const GlobalStyles = createGlobalStyles`
+ html,
+ body {
+ background: light;
+ }
+
+ * {
+ box-sizing: border-box;
+ }
+`;
+
+export default function App() {
+ return (
+ <div id="root">
+ <GlobalStyles />
+ <Navigation>
+ <RestOfYourApp>
+ </div>
+ )
+}
+```
+
+#### How about using `glob` function directly?
+
+Before the global addon, `goober/global`, there was a method named `glob` that was part of the main package that would do the same thing, more or less. Having only that method to define global styles usually led to missing global styles from the extracted css, since the pattern did not enforced the evaluation of the styles at render time. The `glob` method it is still exported from `goober/global` if you have a hard dependency on it. It still has the same API:
+
+```js
+import { glob } from 'goober';
+
+glob`
+ html,
+ body {
+ background: light;
+ }
+
+ * {
+ box-sizing: border-box;
+ }
+`;
+```
+
+### `keyframes`
+
+`keyframes` is a helpful method to define reusable animations that can be decoupled from the main style declaration and shared across components.
+
+```js
+import { keyframes } from 'goober';
+
+const rotate = keyframes`
+ from, to {
+ transform: rotate(0deg);
+ }
+
+ 50% {
+ transform: rotate(180deg);
+ }
+`;
+
+const Wicked = styled('div')`
+ background: tomato;
+ color: white;
+ animation: ${rotate} 1s ease-in-out;
+`;
+```
+
+### `shouldForwardProp`
+
+To seamingly implement the `shouldForwardProp` without the need to provide the full loop over `props` you can use the `goober/should-forward-prop` addon.
+
+```js
+import { h } from 'preact';
+import { setup } from 'goober';
+import { shouldForwardProp } from 'goober/should-forward-prop';
+
+setup(
+ h,
+ undefined,
+ undefined,
+ shouldForwardProp((prop) => {
+ // Do NOT forward props that start with `$` symbol
+ return prop['0'] !== '$';
+ })
+);
+```
+
+# Integrations
+
+## Babel plugin
+
+You're in love with the `styled.div` syntax? Fear no more! We got you covered with a babel plugin that will take your lovely syntax from `styled.tag` and translate it to goober's `styled("tag")` call.
+
+```sh
+npm i --save-dev babel-plugin-transform-goober
+# or
+yarn add --dev babel-plugin-transform-goober
+```
+
+Visit the package in here for more info (https://github.com/cristianbote/goober/tree/master/packages/babel-plugin-transform-goober)
+
+## Babel macro plugin
+
+A babel-plugin-macros macro for [🥜goober][goober], rewriting `styled.div` syntax to `styled('div')` calls.
+
+### Usage
+
+Once you've configured [babel-plugin-macros](https://github.com/kentcdodds/babel-plugin-macros), change your imports from `goober` to `goober/macro`.
+
+Now you can create your components using `styled.*` syntax:.
+
+```js
+import { styled } from 'goober/macro';
+
+const Button = styled.button`
+ margin: 0;
+ padding: 1rem;
+ font-size: 1rem;
+ background-color: tomato;
+`;
+```
+
+## [Gatsby](https://github.com/gatsbyjs/gatsby)
+
+Want to use `goober` with Gatsby? We've got you covered! We have our own plugin to deal with styling your Gatsby projects.
+
+```sh
+npm i --save goober gatsby-plugin-goober
+# or
+yarn add goober gatsby-plugin-goober
+```
+
+## Preact CLI plugin
+
+If you use Goober with Preact CLI, you can use [preact-cli-goober-ssr](https://github.com/gerhardsletten/preact-cli-goober-ssr)
+Autoprefixing is a helpful way to make sure the generated css will work seamlessly on the whole spectrum of browsers. With that in mind, the core `goober` package can't hold that logic to determine the autoprefixing needs, so we added a new package that you can choose to address them.
+
+```sh
+npm install goober
+# or
+yarn add goober
+```
+
+After the main package is installed it's time to bootstrap goober with it:
+
+```js
+import { setup } from 'goober';
+import { prefix } from 'goober/prefixer';
+
+// Bootstrap goober
+setup(React.createElement, prefix);
+```
+
+And voila! It is done!
+
+# TypeScript
+
+`goober` comes with type definitions build in, making it easy to get started in TypeScript straight away.
+
+## Prop Types
+
+If you're utilising custom props and wish to style based on them, you can do so when initialising as follows:
+
+```ts
+interface Props {
+ size: number;
+}
+
+styled('div')<Props>`
+ border-radius: ${(props) => props.size}px;
+`;
+
+// This also works!
+
+styled<Props>('div')`
+ border-radius: ${(props) => props.size}px;
+`;
+```
+
+## Extending Theme
+
+If you're using a [custom theme](../api/setup.md#with-theme) with goober, to add types to it you should create a declaration file at the base of your project.
+
+```ts
+// goober.d.t.s
+
+import 'goober';
+
+declare module 'goober' {
+ export interface DefaultTheme {
+ colors: {
+ primary: string;
+ };
+ }
+}
+```
+
+You should now have autocompletion for your theme.
+`goober` uses microbundle to bundle and transpile it's src into code that browsers can leverage. As you might figure it out, until now, Internet Explorer was the buggiest of them all. `goober` works on IE9, as we've successfully test it.
+
+```
+IE 9
+iOS 9.3
+Chrome 42
+FF 34
+Safari 9
+```
+
+# Contributing
+
+Feel free to try it out and checkout the examples. If you wanna fix something feel free to open a issue or a PR.
+import{css as n,styled as l}from"goober";let o=n.bind({g:1});function r(){const n=l.call({g:1},"div").apply(null,arguments);return function(l){return n(l),null}}export{r as createGlobalStyles,o as glob};
+import{css as n,styled as l}from"goober";let o=n.bind({g:1});function r(){const n=l.call({g:1},"div").apply(null,arguments);return function(l){return n(l),null}}export{r as createGlobalStyles,o as glob};